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 }