Mercurial > mplayer.hg
comparison libvo/vo_fbdev.c @ 359:db6b78fa7331
video mode change supported
author | szabii |
---|---|
date | Wed, 11 Apr 2001 20:52:56 +0000 |
parents | 7de9e48c83a5 |
children | f02474901080 |
comparison
equal
deleted
inserted
replaced
358:223439e2de87 | 359:db6b78fa7331 |
---|---|
1 /* | 1 /* |
2 * Video driver for Framebuffer device | 2 * Video driver for Framebuffer device |
3 * by Szabolcs Berecz <szabi@inf.elte.hu> | 3 * by Szabolcs Berecz <szabi@inf.elte.hu> |
4 * (C) 2001 | |
4 * | 5 * |
5 * Some idea and code borrowed from Chris Lawrence's ppmtofb-0.27 | 6 * Some idea and code borrowed from Chris Lawrence's ppmtofb-0.27 |
6 */ | 7 */ |
7 | 8 |
8 #include <stdio.h> | 9 #include <stdio.h> |
9 #include <stdlib.h> | 10 #include <stdlib.h> |
10 #include <string.h> | 11 #include <string.h> |
11 #include <fcntl.h> | 12 #include <fcntl.h> |
12 #include <unistd.h> | 13 #include <unistd.h> |
13 #include <errno.h> | 14 #include <errno.h> |
15 #include <ctype.h> | |
16 #include <assert.h> | |
14 | 17 |
15 #include <sys/mman.h> | 18 #include <sys/mman.h> |
16 #include <sys/ioctl.h> | 19 #include <sys/ioctl.h> |
17 #include <linux/fb.h> | 20 #include <linux/fb.h> |
18 #include <linux/vt.h> | 21 #include <linux/vt.h> |
33 "fbdev", | 36 "fbdev", |
34 "Szabolcs Berecz <szabi@inf.elte.hu>", | 37 "Szabolcs Berecz <szabi@inf.elte.hu>", |
35 "" | 38 "" |
36 }; | 39 }; |
37 | 40 |
38 static int vt_active = -1; | 41 /****************************** |
39 static int vt_fd; | 42 * fb.modes parser * |
40 | 43 ******************************/ |
44 | |
45 /* | |
46 * read the fb.modes manual page! | |
47 */ | |
48 | |
49 typedef struct { | |
50 char *name; | |
51 uint32_t xres, yres, vxres, vyres, depth; | |
52 uint32_t pixclock, left, right, upper, lower, hslen, vslen; | |
53 uint32_t sync; | |
54 uint32_t vmode; | |
55 } fb_mode_t; | |
56 | |
57 #define PRINT_LINENUM printf(" at line %d\n", line_num) | |
58 | |
59 #define MAX_NR_TOKEN 16 | |
60 | |
61 #define MAX_LINE_LEN 1000 | |
62 | |
63 #define RET_EOF -1 | |
64 #define RET_EOL -2 | |
65 | |
66 static int validate_mode(fb_mode_t *m) | |
67 { | |
68 if (!m->xres) { | |
69 printf("needs geometry "); | |
70 return 0; | |
71 } | |
72 if (!m->pixclock) { | |
73 printf("needs timings "); | |
74 return 0; | |
75 } | |
76 return 1; | |
77 } | |
78 | |
79 static FILE *fp; | |
80 static int line_num = 0; | |
81 static char *line; | |
82 static char *token[MAX_NR_TOKEN]; | |
83 | |
84 static int get_token(int num) | |
85 { | |
86 static int read_nextline = 1; | |
87 static int line_pos; | |
88 int i; | |
89 char c; | |
90 | |
91 if (num >= MAX_NR_TOKEN) { | |
92 printf("get_token(): max >= MAX_NR_TOKEN!"); | |
93 goto out_eof; | |
94 } | |
95 | |
96 if (read_nextline) { | |
97 if (!fgets(line, MAX_LINE_LEN, fp)) | |
98 goto out_eof; | |
99 line_pos = 0; | |
100 ++line_num; | |
101 read_nextline = 0; | |
102 } | |
103 for (i = 0; i < num; i++) { | |
104 while (isspace(line[line_pos])) | |
105 ++line_pos; | |
106 if (line[line_pos] == '\0' || line[line_pos] == '#') { | |
107 read_nextline = 1; | |
108 if (i == num) | |
109 goto out_ok; | |
110 goto out_eol; | |
111 } | |
112 token[i] = line + line_pos; | |
113 c = line[line_pos]; | |
114 if (c == '"' || c == '\'') { | |
115 token[i]++; | |
116 while (line[++line_pos] != c && line[line_pos]) | |
117 /* NOTHING */; | |
118 } else { | |
119 for (/* NOTHING */; !isspace(line[line_pos]) && | |
120 line[line_pos]; line_pos++) | |
121 /* NOTHING */; | |
122 } | |
123 if (!line[line_pos]) { | |
124 read_nextline = 1; | |
125 if (i == num - 1) | |
126 goto out_ok; | |
127 goto out_eol; | |
128 } | |
129 line[line_pos] = '\0'; | |
130 line_pos++; | |
131 } | |
132 out_ok: | |
133 return i; | |
134 out_eof: | |
135 return RET_EOF; | |
136 out_eol: | |
137 return RET_EOL; | |
138 } | |
139 | |
140 static fb_mode_t *fb_modes = NULL; | |
141 static int nr_modes = 0; | |
142 | |
143 static int parse_fbmode_cfg(char *cfgfile) | |
144 { | |
145 fb_mode_t *mode = NULL; | |
146 char *endptr; // strtoul()... | |
147 int tmp, i; | |
148 | |
149 #ifdef DEBUG | |
150 assert(cfgfile != NULL); | |
151 #endif | |
152 | |
153 printf("Reading %s: ", cfgfile); | |
154 | |
155 if ((fp = fopen(cfgfile, "r")) == NULL) { | |
156 printf("can't open '%s': %s\n", cfgfile, strerror(errno)); | |
157 return -1; | |
158 } | |
159 | |
160 if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) { | |
161 printf("can't get memory for 'line': %s\n", strerror(errno)); | |
162 return -2; | |
163 } | |
164 | |
165 /* | |
166 * check if the cfgfile starts with 'mode' | |
167 */ | |
168 while ((tmp = get_token(1)) == RET_EOL) | |
169 /* NOTHING */; | |
170 if (tmp == RET_EOF) | |
171 goto out; | |
172 if (!strcmp(token[0], "mode")) | |
173 goto loop_enter; | |
174 goto err_out_parse_error; | |
175 | |
176 while ((tmp = get_token(1)) != RET_EOF) { | |
177 if (tmp == RET_EOL) | |
178 continue; | |
179 if (!strcmp(token[0], "mode")) { | |
180 if (!validate_mode(mode)) | |
181 goto err_out_not_valid; | |
182 loop_enter: | |
183 if (!(fb_modes = (fb_mode_t *) realloc(fb_modes, | |
184 sizeof(fb_mode_t) * (nr_modes + 1)))) { | |
185 printf("can't realloc 'fb_modes': %s\n", strerror(errno)); | |
186 goto err_out; | |
187 } | |
188 mode=fb_modes + nr_modes; | |
189 ++nr_modes; | |
190 memset(mode,0,sizeof(fb_mode_t)); | |
191 | |
192 if (get_token(1) < 0) | |
193 goto err_out_parse_error; | |
194 for (i = 0; i < nr_modes - 1; i++) { | |
195 if (!strcmp(token[0], fb_modes[i].name)) { | |
196 printf("mode name '%s' isn't unique", token[0]); | |
197 goto err_out_print_linenum; | |
198 } | |
199 } | |
200 if (!(mode->name = strdup(token[0]))) { | |
201 printf("can't strdup -> 'name': %s\n", strerror(errno)); | |
202 goto err_out; | |
203 } | |
204 } else if (!strcmp(token[0], "geometry")) { | |
205 if (get_token(5) < 0) | |
206 goto err_out_parse_error; | |
207 mode->xres = strtoul(token[0], &endptr, 0); | |
208 if (*endptr) | |
209 goto err_out_parse_error; | |
210 mode->yres = strtoul(token[1], &endptr, 0); | |
211 if (*endptr) | |
212 goto err_out_parse_error; | |
213 mode->vxres = strtoul(token[2], &endptr, 0); | |
214 if (*endptr) | |
215 goto err_out_parse_error; | |
216 mode->vyres = strtoul(token[3], &endptr, 0); | |
217 if (*endptr) | |
218 goto err_out_parse_error; | |
219 mode->depth = strtoul(token[4], &endptr, 0); | |
220 if (*endptr) | |
221 goto err_out_parse_error; | |
222 } else if (!strcmp(token[0], "timings")) { | |
223 if (get_token(7) < 0) | |
224 goto err_out_parse_error; | |
225 mode->pixclock = strtoul(token[0], &endptr, 0); | |
226 if (*endptr) | |
227 goto err_out_parse_error; | |
228 mode->left = strtoul(token[1], &endptr, 0); | |
229 if (*endptr) | |
230 goto err_out_parse_error; | |
231 mode->right = strtoul(token[2], &endptr, 0); | |
232 if (*endptr) | |
233 goto err_out_parse_error; | |
234 mode->upper = strtoul(token[3], &endptr, 0); | |
235 if (*endptr) | |
236 goto err_out_parse_error; | |
237 mode->lower = strtoul(token[4], &endptr, 0); | |
238 if (*endptr) | |
239 goto err_out_parse_error; | |
240 mode->hslen = strtoul(token[5], &endptr, 0); | |
241 if (*endptr) | |
242 goto err_out_parse_error; | |
243 mode->vslen = strtoul(token[6], &endptr, 0); | |
244 if (*endptr) | |
245 goto err_out_parse_error; | |
246 } else if (!strcmp(token[0], "endmode")) { | |
247 /* NOTHING for now*/ | |
248 } else if (!strcmp(token[0], "hsync")) { | |
249 if (get_token(1) < 0) | |
250 goto err_out_parse_error; | |
251 if (!strcmp(token[0], "low")) | |
252 mode->sync &= ~FB_SYNC_HOR_HIGH_ACT; | |
253 else if(!strcmp(token[0], "high")) | |
254 mode->sync |= FB_SYNC_HOR_HIGH_ACT; | |
255 else | |
256 goto err_out_parse_error; | |
257 } else if (!strcmp(token[0], "vsync")) { | |
258 if (get_token(1) < 0) | |
259 goto err_out_parse_error; | |
260 if (!strcmp(token[0], "low")) | |
261 mode->sync &= ~FB_SYNC_VERT_HIGH_ACT; | |
262 else if(!strcmp(token[0], "high")) | |
263 mode->sync |= FB_SYNC_VERT_HIGH_ACT; | |
264 else | |
265 goto err_out_parse_error; | |
266 } else if (!strcmp(token[0], "csync")) { | |
267 if (get_token(1) < 0) | |
268 goto err_out_parse_error; | |
269 if (!strcmp(token[0], "low")) | |
270 mode->sync &= ~FB_SYNC_COMP_HIGH_ACT; | |
271 else if(!strcmp(token[0], "high")) | |
272 mode->sync |= FB_SYNC_COMP_HIGH_ACT; | |
273 else | |
274 goto err_out_parse_error; | |
275 } else if (!strcmp(token[0], "extsync")) { | |
276 if (get_token(1) < 0) | |
277 goto err_out_parse_error; | |
278 if (!strcmp(token[0], "false")) | |
279 mode->sync &= ~FB_SYNC_EXT; | |
280 else if(!strcmp(token[0], "true")) | |
281 mode->sync |= FB_SYNC_EXT; | |
282 else | |
283 goto err_out_parse_error; | |
284 } else if (!strcmp(token[0], "laced")) { | |
285 if (get_token(1) < 0) | |
286 goto err_out_parse_error; | |
287 if (!strcmp(token[0], "false")) | |
288 mode->vmode = FB_VMODE_NONINTERLACED; | |
289 else if (!strcmp(token[0], "true")) | |
290 mode->vmode = FB_VMODE_INTERLACED; | |
291 else | |
292 goto err_out_parse_error; | |
293 } else if (!strcmp(token[0], "dblscan")) { | |
294 if (get_token(1) < 0) | |
295 goto err_out_parse_error; | |
296 if (!strcmp(token[0], "false")) | |
297 ; | |
298 else if (!strcmp(token[0], "true")) | |
299 mode->vmode = FB_VMODE_DOUBLE; | |
300 else | |
301 goto err_out_parse_error; | |
302 } else | |
303 goto err_out_parse_error; | |
304 } | |
305 if (!validate_mode(mode)) | |
306 goto err_out_not_valid; | |
307 out: | |
308 printf("%d modes\n", nr_modes); | |
309 free(line); | |
310 fclose(fp); | |
311 return nr_modes; | |
312 err_out_parse_error: | |
313 printf("parse error"); | |
314 err_out_print_linenum: | |
315 PRINT_LINENUM; | |
316 err_out: | |
317 if (fb_modes) | |
318 free(fb_modes); | |
319 free(line); | |
320 free(fp); | |
321 return -2; | |
322 err_out_not_valid: | |
323 printf("mode is not definied correctly"); | |
324 goto err_out_print_linenum; | |
325 } | |
326 | |
327 static fb_mode_t *find_mode_by_name(char *name) | |
328 { | |
329 int i; | |
330 | |
331 for (i = 0; i < nr_modes; i++) { | |
332 if (!strcmp(name, fb_modes[i].name)) | |
333 return fb_modes + i; | |
334 } | |
335 return NULL; | |
336 } | |
337 | |
338 /****************************** | |
339 * vo_fbdev * | |
340 ******************************/ | |
341 | |
342 static int fb_init_done = 0; | |
343 static int fb_works = 0; | |
41 char *fb_dev_name = NULL; | 344 char *fb_dev_name = NULL; |
42 static int fb_dev_fd; | 345 static int fb_dev_fd; |
43 static size_t fb_size; | 346 static size_t fb_size; |
44 static uint8_t *frame_buffer; | 347 static uint8_t *frame_buffer; |
45 static int fb_pixel_size; | 348 static struct fb_fix_screeninfo fb_finfo; |
46 static int fb_bpp; | 349 static struct fb_var_screeninfo fb_orig_vinfo; |
47 static int fb_bpp_on_screen; | 350 static struct fb_var_screeninfo fb_vinfo; |
48 struct fb_fix_screeninfo fb_fix_info; | 351 static struct fb_cmap *fb_oldcmap = NULL; |
49 struct fb_var_screeninfo fb_var_info; | 352 static int fb_pixel_size; // 32: 4 24: 3 16: 2 15: 2 |
50 static uint32_t fb_xres_virtual; | 353 static int fb_real_bpp; // 32: 24 24: 24 16: 16 15: 15 |
51 static uint32_t fb_yres_virtual; | 354 static int fb_bpp; // 32: 32 24: 24 16: 16 15: 15 |
52 static struct fb_cmap *oldcmap = NULL; | 355 static int fb_screen_width; |
53 | 356 |
357 char *fb_mode_cfgfile = "/etc/fb.modes"; | |
358 char *fb_mode_name = NULL; | |
359 static fb_mode_t *fb_mode = NULL; | |
360 static int fb_switch_mode = 0; | |
361 | |
362 static uint8_t *next_frame; | |
54 static int in_width; | 363 static int in_width; |
55 static int in_height; | 364 static int in_height; |
56 static int out_width; | 365 static int out_width; |
57 static int out_height; | 366 static int out_height; |
58 static uint8_t *next_frame; | |
59 static int screen_width; | |
60 static uint32_t pixel_format; | 367 static uint32_t pixel_format; |
61 | |
62 static int fb_init_done = 0; | |
63 static int fb_works = 0; | |
64 | 368 |
65 /* | 369 /* |
66 * Note: this function is completely cut'n'pasted from | 370 * Note: this function is completely cut'n'pasted from |
67 * Chris Lawrence's code. | 371 * Chris Lawrence's code. |
68 * (modified a bit to fit in my code...) | 372 * (modified a bit to fit in my code...) |
136 static int fb_init(void) | 440 static int fb_init(void) |
137 { | 441 { |
138 int fd; | 442 int fd; |
139 struct fb_cmap *cmap; | 443 struct fb_cmap *cmap; |
140 | 444 |
445 if (fb_mode_name) { | |
446 if (parse_fbmode_cfg(fb_mode_cfgfile) < 0) | |
447 return 1; | |
448 if (!(fb_mode = find_mode_by_name(fb_mode_name))) { | |
449 printf("fb_init: can't find requested video mode\n"); | |
450 return 1; | |
451 } | |
452 fb_switch_mode = 1; | |
453 } | |
454 | |
141 if (!fb_dev_name && !(fb_dev_name = getenv("FRAMEBUFFER"))) | 455 if (!fb_dev_name && !(fb_dev_name = getenv("FRAMEBUFFER"))) |
142 fb_dev_name = "/dev/fb0"; | 456 fb_dev_name = "/dev/fb0"; |
143 printf("fb_init: using %s\n", fb_dev_name); | 457 printf("fb_init: using %s\n", fb_dev_name); |
144 | 458 |
145 if ((fb_dev_fd = open(fb_dev_name, O_RDWR)) == -1) { | 459 if ((fb_dev_fd = open(fb_dev_name, O_RDWR)) == -1) { |
146 printf("fb_init: Can't open %s: %s\n", fb_dev_name, strerror(errno)); | 460 printf("fb_init: Can't open %s: %s\n", fb_dev_name, strerror(errno)); |
147 goto err_out; | 461 goto err_out; |
148 } | 462 } |
149 | 463 |
150 if (ioctl(fb_dev_fd, FBIOGET_VSCREENINFO, &fb_var_info)) { | 464 if (ioctl(fb_dev_fd, FBIOGET_VSCREENINFO, &fb_vinfo)) { |
151 printf("fb_init: Can't get VSCREENINFO: %s\n", strerror(errno)); | 465 printf("fb_init: Can't get VSCREENINFO: %s\n", strerror(errno)); |
152 goto err_out_fd; | 466 goto err_out_fd; |
153 } | 467 } |
154 | 468 |
155 /* disable scrolling */ | 469 fb_orig_vinfo = fb_vinfo; |
156 fb_xres_virtual = fb_var_info.xres_virtual; | 470 if (fb_switch_mode) { |
157 fb_yres_virtual = fb_var_info.yres_virtual; | 471 fb_vinfo.xres = fb_mode->xres; |
158 fb_var_info.xres_virtual = fb_var_info.xres; | 472 fb_vinfo.yres = fb_mode->yres; |
159 fb_var_info.yres_virtual = fb_var_info.yres; | 473 fb_vinfo.xres_virtual = fb_mode->vxres; |
160 | 474 fb_vinfo.yres_virtual = fb_mode->vyres; |
161 if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_var_info)) { | 475 fb_vinfo.bits_per_pixel = fb_mode->depth; |
476 switch (fb_mode->depth) { | |
477 case 32: | |
478 case 24: | |
479 fb_vinfo.red.offset = 16; | |
480 fb_vinfo.red.length = 8; | |
481 fb_vinfo.red.msb_right = 0; | |
482 fb_vinfo.green.offset = 8; | |
483 fb_vinfo.green.length = 8; | |
484 fb_vinfo.green.msb_right = 0; | |
485 fb_vinfo.blue.offset = 0; | |
486 fb_vinfo.blue.length = 8; | |
487 fb_vinfo.blue.msb_right = 0; | |
488 case 16: | |
489 fb_vinfo.red.offset = 11; | |
490 fb_vinfo.red.length = 5; | |
491 fb_vinfo.red.msb_right = 0; | |
492 fb_vinfo.green.offset = 5; | |
493 fb_vinfo.green.length = 6; | |
494 fb_vinfo.green.msb_right = 0; | |
495 fb_vinfo.blue.offset = 0; | |
496 fb_vinfo.blue.length = 5; | |
497 fb_vinfo.blue.msb_right = 0; | |
498 case 15: | |
499 fb_vinfo.red.offset = 10; | |
500 fb_vinfo.red.length = 5; | |
501 fb_vinfo.red.msb_right = 0; | |
502 fb_vinfo.green.offset = 5; | |
503 fb_vinfo.green.length = 5; | |
504 fb_vinfo.green.msb_right = 0; | |
505 fb_vinfo.blue.offset = 0; | |
506 fb_vinfo.blue.length = 5; | |
507 fb_vinfo.blue.msb_right = 0; | |
508 } | |
509 fb_vinfo.pixclock = fb_mode->pixclock; | |
510 fb_vinfo.left_margin = fb_mode->left; | |
511 fb_vinfo.right_margin = fb_mode->right; | |
512 fb_vinfo.upper_margin = fb_mode->upper; | |
513 fb_vinfo.lower_margin = fb_mode->lower; | |
514 fb_vinfo.hsync_len = fb_mode->hslen; | |
515 fb_vinfo.vsync_len = fb_mode->vslen; | |
516 fb_vinfo.sync = fb_mode->sync; | |
517 fb_vinfo.vmode = fb_mode->vmode; | |
518 } | |
519 fb_vinfo.xres_virtual = fb_vinfo.xres; | |
520 fb_vinfo.yres_virtual = fb_vinfo.yres; | |
521 | |
522 if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_vinfo)) { | |
162 printf("fb_init: Can't put VSCREENINFO: %s\n", strerror(errno)); | 523 printf("fb_init: Can't put VSCREENINFO: %s\n", strerror(errno)); |
163 goto err_out_fd; | 524 goto err_out_fd; |
164 } | 525 } |
165 | 526 |
166 if (ioctl(fb_dev_fd, FBIOGET_FSCREENINFO, &fb_fix_info)) { | 527 if (ioctl(fb_dev_fd, FBIOGET_FSCREENINFO, &fb_finfo)) { |
167 printf("fb_init: Can't get VSCREENINFO: %s\n", strerror(errno)); | 528 printf("fb_init: Can't get VSCREENINFO: %s\n", strerror(errno)); |
168 goto err_out_fd; | 529 goto err_out_fd; |
169 return 1; | 530 return 1; |
170 } | 531 } |
171 switch (fb_fix_info.type) { | 532 switch (fb_finfo.type) { |
172 case FB_TYPE_VGA_PLANES: | 533 case FB_TYPE_VGA_PLANES: |
173 printf("fb_init: FB_TYPE_VGA_PLANES not supported.\n"); | 534 printf("fb_init: FB_TYPE_VGA_PLANES not supported.\n"); |
174 goto err_out_fd; | 535 goto err_out_fd; |
175 break; | 536 break; |
176 case FB_TYPE_PLANES: | 537 case FB_TYPE_PLANES: |
190 case FB_TYPE_PACKED_PIXELS: | 551 case FB_TYPE_PACKED_PIXELS: |
191 /* OK */ | 552 /* OK */ |
192 printf("fb_init: FB_TYPE_PACKED_PIXELS: OK\n"); | 553 printf("fb_init: FB_TYPE_PACKED_PIXELS: OK\n"); |
193 break; | 554 break; |
194 default: | 555 default: |
195 printf("fb_init: unknown FB_TYPE: %d\n", fb_fix_info.type); | 556 printf("fb_init: unknown FB_TYPE: %d\n", fb_finfo.type); |
196 goto err_out_fd; | 557 goto err_out_fd; |
197 } | 558 } |
198 if (fb_fix_info.visual == FB_VISUAL_DIRECTCOLOR) { | 559 if (fb_finfo.visual == FB_VISUAL_DIRECTCOLOR) { |
199 printf("fb_init: creating cmap for directcolor\n"); | 560 printf("fb_init: creating cmap for directcolor\n"); |
200 if (ioctl(fb_dev_fd, FBIOGETCMAP, oldcmap)) { | 561 if (ioctl(fb_dev_fd, FBIOGETCMAP, fb_oldcmap)) { |
201 printf("fb_init: can't get cmap: %s\n", | 562 printf("fb_init: can't get cmap: %s\n", |
202 strerror(errno)); | 563 strerror(errno)); |
203 goto err_out_fd; | 564 goto err_out_fd; |
204 } | 565 } |
205 if (!(cmap = make_directcolor_cmap(&fb_var_info))) | 566 if (!(cmap = make_directcolor_cmap(&fb_vinfo))) |
206 goto err_out_fd; | 567 goto err_out_fd; |
207 if (ioctl(fb_dev_fd, FBIOPUTCMAP, cmap)) { | 568 if (ioctl(fb_dev_fd, FBIOPUTCMAP, cmap)) { |
208 printf("fb_init: can't put cmap: %s\n", | 569 printf("fb_init: can't put cmap: %s\n", |
209 strerror(errno)); | 570 strerror(errno)); |
210 goto err_out_fd; | 571 goto err_out_fd; |
211 } | 572 } |
212 free(cmap->red); | 573 free(cmap->red); |
213 free(cmap->green); | 574 free(cmap->green); |
214 free(cmap->blue); | 575 free(cmap->blue); |
215 free(cmap); | 576 free(cmap); |
216 } else if (fb_fix_info.visual != FB_VISUAL_TRUECOLOR) { | 577 } else if (fb_finfo.visual != FB_VISUAL_TRUECOLOR) { |
217 printf("fb_init: visual: %d not yet supported\n", | 578 printf("fb_init: visual: %d not yet supported\n", |
218 fb_fix_info.visual); | 579 fb_finfo.visual); |
219 goto err_out_fd; | 580 goto err_out_fd; |
220 } | 581 } |
221 | 582 |
222 fb_pixel_size = fb_var_info.bits_per_pixel / 8; | 583 fb_pixel_size = fb_vinfo.bits_per_pixel / 8; |
223 fb_bpp = fb_var_info.red.length + fb_var_info.green.length + | 584 fb_real_bpp = fb_vinfo.red.length + fb_vinfo.green.length + |
224 fb_var_info.blue.length; | 585 fb_vinfo.blue.length; |
225 fb_bpp_on_screen = (fb_pixel_size == 4) ? 32 : fb_bpp; | 586 fb_bpp = (fb_pixel_size == 4) ? 32 : fb_real_bpp; |
226 screen_width = fb_fix_info.line_length; | 587 fb_screen_width = fb_finfo.line_length; |
227 fb_size = fb_fix_info.smem_len; | 588 fb_size = fb_finfo.smem_len; |
228 if ((frame_buffer = (uint8_t *) mmap(0, fb_size, PROT_READ | PROT_WRITE, | 589 if ((frame_buffer = (uint8_t *) mmap(0, fb_size, PROT_READ | PROT_WRITE, |
229 MAP_SHARED, fb_dev_fd, 0)) == (uint8_t *) -1) { | 590 MAP_SHARED, fb_dev_fd, 0)) == (uint8_t *) -1) { |
230 printf("fb_init: Can't mmap %s: %s\n", fb_dev_name, strerror(errno)); | 591 printf("fb_init: Can't mmap %s: %s\n", fb_dev_name, strerror(errno)); |
231 goto err_out_fd; | 592 goto err_out_fd; |
232 } | 593 } |
233 | 594 |
234 printf("fb_init: framebuffer @ %p\n", frame_buffer); | 595 printf("fb_init: framebuffer @ %p\n", frame_buffer); |
235 printf("fb_init: framebuffer size: %d bytes\n", fb_size); | 596 printf("fb_init: framebuffer size: %d bytes\n", fb_size); |
236 printf("fb_init: bpp: %d\n", fb_bpp); | 597 printf("fb_init: bpp: %d\n", fb_bpp); |
237 printf("fb_init: bpp on screen: %d\n", fb_bpp_on_screen); | 598 printf("fb_init: real bpp: %d\n", fb_real_bpp); |
238 printf("fb_init: pixel size: %d\n", fb_pixel_size); | 599 printf("fb_init: pixel size: %d bytes\n", fb_pixel_size); |
239 printf("fb_init: pixel per line: %d\n", screen_width / fb_pixel_size); | 600 printf("fb_init: pixel per line: %d\n", fb_screen_width / fb_pixel_size); |
240 printf("fb_init: visual: %d\n", fb_fix_info.visual); | 601 printf("fb_init: visual: %d\n", fb_finfo.visual); |
241 printf("fb_init: red: %d %d %d\n", fb_var_info.red.offset, | 602 printf("fb_init: red: %d %d %d\n", fb_vinfo.red.offset, |
242 fb_var_info.red.length, fb_var_info.red.msb_right); | 603 fb_vinfo.red.length, fb_vinfo.red.msb_right); |
243 printf("fb_init: green: %d %d %d\n", fb_var_info.green.offset, | 604 printf("fb_init: green: %d %d %d\n", fb_vinfo.green.offset, |
244 fb_var_info.green.length, fb_var_info.green.msb_right); | 605 fb_vinfo.green.length, fb_vinfo.green.msb_right); |
245 printf("fb_init: blue: %d %d %d\n", fb_var_info.blue.offset, | 606 printf("fb_init: blue: %d %d %d\n", fb_vinfo.blue.offset, |
246 fb_var_info.blue.length, fb_var_info.blue.msb_right); | 607 fb_vinfo.blue.length, fb_vinfo.blue.msb_right); |
247 | 608 |
248 fb_init_done = 1; | 609 fb_init_done = 1; |
249 fb_works = 1; | 610 fb_works = 1; |
250 return 0; | 611 return 0; |
251 err_out_fd: | 612 err_out_fd: |
275 printf("Can't malloc next_frame: %s\n", strerror(errno)); | 636 printf("Can't malloc next_frame: %s\n", strerror(errno)); |
276 return 1; | 637 return 1; |
277 } | 638 } |
278 | 639 |
279 if (format == IMGFMT_YV12) | 640 if (format == IMGFMT_YV12) |
280 // yuv2rgb_init(fb_pixel_size * 8, MODE_RGB); | 641 yuv2rgb_init(fb_bpp, MODE_RGB); |
281 yuv2rgb_init(fb_bpp_on_screen, MODE_RGB); | |
282 return 0; | 642 return 0; |
283 } | 643 } |
284 | 644 |
285 static uint32_t query_format(uint32_t format) | 645 static uint32_t query_format(uint32_t format) |
286 { | 646 { |
290 if (!fb_works) | 650 if (!fb_works) |
291 return 0; | 651 return 0; |
292 | 652 |
293 if ((format & IMGFMT_BGR_MASK) == IMGFMT_BGR) { | 653 if ((format & IMGFMT_BGR_MASK) == IMGFMT_BGR) { |
294 int bpp = format & 0xff; | 654 int bpp = format & 0xff; |
295 if (bpp == fb_bpp_on_screen) | 655 if (bpp == fb_bpp) |
296 return 1; | 656 return 1; |
297 else if (bpp == 15 && fb_bpp_on_screen == 16) | 657 else if (bpp == 15 && fb_bpp == 16) |
298 return 1; | 658 return 1; |
299 else if (bpp == 24 && fb_bpp_on_screen == 32) | 659 else if (bpp == 24 && fb_bpp == 32) |
300 return 1; | 660 return 1; |
301 } | 661 } |
302 if (format == IMGFMT_YV12) | 662 if (format == IMGFMT_YV12) |
303 return 1; | 663 return 1; |
304 return 0; | 664 return 0; |
305 /* | |
306 printf("vo_fbdev: query_format(%#x(%.4s)): ", format, &format); | |
307 if (format & IMGFMT_BGR_MASK == IMGFMT_BGR) | |
308 goto not_supported; | |
309 switch (format) { | |
310 case IMGFMT_YV12: | |
311 goto supported; | |
312 | |
313 case IMGFMT_RGB32: | |
314 if (fb_bpp == 32) | |
315 goto supported; | |
316 break; | |
317 case IMGFMT_RGB24: | |
318 if (fb_bpp == 24) | |
319 goto supported; | |
320 break; | |
321 case IMGFMT_RGB16: | |
322 if (fb_bpp == 16) | |
323 goto supported; | |
324 break; | |
325 case IMGFMT_RGB15: | |
326 if (fb_bpp == 15) | |
327 goto supported; | |
328 break; | |
329 | |
330 case IMGFMT_BGR|32: | |
331 if (fb_bpp == 24 && fb_pixel_size == 4) | |
332 goto supported; | |
333 break; | |
334 case IMGFMT_BGR|24: | |
335 if (fb_bpp == 24 && fb_pixel_size == 3) | |
336 goto supported; | |
337 break; | |
338 case IMGFMT_BGR|16: | |
339 if (fb_bpp == 16) | |
340 goto supported; | |
341 break; | |
342 case IMGFMT_BGR|15: | |
343 if (fb_bpp == 15) | |
344 goto supported; | |
345 break; | |
346 } | |
347 not_supported: | |
348 printf("not_supported\n"); | |
349 return 0; | |
350 supported: | |
351 printf("supported\n"); | |
352 return 1; | |
353 */ | |
354 } | 665 } |
355 | 666 |
356 static const vo_info_t *get_info(void) | 667 static const vo_info_t *get_info(void) |
357 { | 668 { |
358 return &vo_info; | 669 return &vo_info; |
359 } | 670 } |
360 | 671 |
361 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, | 672 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, |
362 unsigned char *srca, int stride) | 673 unsigned char *srca, int stride) |
363 { | 674 { |
675 uint8_t *dst = next_frame + (in_width * y0 + x0) * fb_pixel_size; | |
676 int dstride = in_width * fb_pixel_size; | |
677 | |
678 switch (fb_real_bpp) { | |
679 case 24: | |
680 vo_draw_alpha_rgb24(w, h, src, srca, stride, dst, dstride); | |
681 break; | |
682 case 32: | |
683 vo_draw_alpha_rgb32(w, h, src, srca, stride, dst, dstride); | |
684 break; | |
685 case 15: | |
686 vo_draw_alpha_rgb15(w, h, src, srca, stride, dst, dstride); | |
687 break; | |
688 case 16: | |
689 vo_draw_alpha_rgb16(w, h, src, srca, stride, dst, dstride); | |
690 break; | |
691 } | |
692 #if 0 | |
364 int x, y; | 693 int x, y; |
365 uint8_t *dst; | 694 uint8_t *dst; |
366 | 695 |
367 // if (pixel_format == IMGFMT_YV12) { | 696 // if (pixel_format == IMGFMT_YV12) { |
368 for (y = 0; y < h; y++){ | 697 for (y = 0; y < h; y++){ |
377 } | 706 } |
378 src += stride; | 707 src += stride; |
379 srca += stride; | 708 srca += stride; |
380 } | 709 } |
381 // } | 710 // } |
711 #endif | |
382 } | 712 } |
383 | 713 |
384 static uint32_t draw_frame(uint8_t *src[]) | 714 static uint32_t draw_frame(uint8_t *src[]) |
385 { | 715 { |
386 if (pixel_format == IMGFMT_YV12) { | 716 if (pixel_format == IMGFMT_YV12) { |
390 } else { | 720 } else { |
391 int sbpp = ((pixel_format & 0xff) + 7) / 8; | 721 int sbpp = ((pixel_format & 0xff) + 7) / 8; |
392 char *d = next_frame; | 722 char *d = next_frame; |
393 char *s = src[0]; | 723 char *s = src[0]; |
394 if (sbpp == fb_pixel_size) { | 724 if (sbpp == fb_pixel_size) { |
395 if (fb_bpp == 16 && pixel_format == (IMGFMT_BGR|15)) { | 725 if (fb_real_bpp == 16 && pixel_format == (IMGFMT_BGR|15)) { |
396 #ifdef HAVE_MMX | 726 #ifdef HAVE_MMX |
397 rgb15to16_mmx(s, d, 2 * in_width * in_height); | 727 rgb15to16_mmx(s, d, 2 * in_width * in_height); |
398 #else | 728 #else |
399 unsigned short *s1 = (unsigned short *) s; | 729 unsigned short *s1 = (unsigned short *) s; |
400 unsigned short *d1 = (unsigned short *) d; | 730 unsigned short *d1 = (unsigned short *) d; |
406 #endif | 736 #endif |
407 } else | 737 } else |
408 memcpy(d, s, sbpp * in_width * in_height); | 738 memcpy(d, s, sbpp * in_width * in_height); |
409 } | 739 } |
410 } | 740 } |
411 /* | |
412 } else if ((pixel_format & IMGFMT_BGR_MASK) == IMGFMT_BGR) { | |
413 if (pixel_format == fb_bpp_on_screen) | |
414 memcpy(next_frame, src[0], | |
415 in_width * in_height * fb_pixel_size); | |
416 else { | |
417 | |
418 } | |
419 } | |
420 */ | |
421 return 0; | 741 return 0; |
422 } | 742 } |
423 | 743 |
424 static uint32_t draw_slice(uint8_t *src[], int stride[], int w, int h, int x, | 744 static uint32_t draw_slice(uint8_t *src[], int stride[], int w, int h, int x, |
425 int y) | 745 int y) |
441 int i, out_offset = 0, in_offset = 0; | 761 int i, out_offset = 0, in_offset = 0; |
442 | 762 |
443 for (i = 0; i < in_height; i++) { | 763 for (i = 0; i < in_height; i++) { |
444 memcpy(frame_buffer + out_offset, next_frame + in_offset, | 764 memcpy(frame_buffer + out_offset, next_frame + in_offset, |
445 in_width * fb_pixel_size); | 765 in_width * fb_pixel_size); |
446 out_offset += screen_width; | 766 out_offset += fb_screen_width; |
447 in_offset += in_width * fb_pixel_size; | 767 in_offset += in_width * fb_pixel_size; |
448 } | 768 } |
449 } | 769 } |
450 | 770 |
451 static void flip_page(void) | 771 static void flip_page(void) |
456 } | 776 } |
457 | 777 |
458 static void uninit(void) | 778 static void uninit(void) |
459 { | 779 { |
460 printf("vo_fbdev: uninit\n"); | 780 printf("vo_fbdev: uninit\n"); |
461 if (oldcmap) { | 781 if (fb_oldcmap) { |
462 if (ioctl(fb_dev_fd, FBIOPUTCMAP, oldcmap)) | 782 if (ioctl(fb_dev_fd, FBIOPUTCMAP, fb_oldcmap)) |
463 printf("vo_fbdev: Can't restore original cmap\n"); | 783 printf("vo_fbdev: Can't restore original cmap\n"); |
464 oldcmap = NULL; | 784 fb_oldcmap = NULL; |
465 } | 785 } |
466 fb_var_info.xres_virtual = fb_xres_virtual; | 786 if (fb_switch_mode) |
467 fb_var_info.yres_virtual = fb_yres_virtual; | 787 fb_vinfo = fb_orig_vinfo; |
468 if (fb_dev_fd != -1) { | 788 else { |
469 if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_var_info)) | 789 fb_vinfo.xres_virtual = fb_orig_vinfo.xres_virtual; |
470 printf("vo_fbdev: Can't set virtual screensize to original value: %s\n", strerror(errno)); | 790 fb_vinfo.yres_virtual = fb_orig_vinfo.yres_virtual; |
471 close(fb_dev_fd); | 791 } |
472 } | 792 if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_vinfo)) |
793 printf("vo_fbdev: Can't set virtual screensize to original value: %s\n", strerror(errno)); | |
794 close(fb_dev_fd); | |
473 memset(next_frame, '\0', in_height * in_width * fb_pixel_size); | 795 memset(next_frame, '\0', in_height * in_width * fb_pixel_size); |
474 put_frame(); | 796 put_frame(); |
475 if (vt_active >= 0) | |
476 ioctl(vt_fd, VT_ACTIVATE, vt_active); | |
477 free(next_frame); | 797 free(next_frame); |
478 munmap(frame_buffer, fb_size); | 798 munmap(frame_buffer, fb_size); |
479 } | 799 } |