Mercurial > mplayer.hg
annotate libvo/vo_fbdev.c @ 3603:baa8b0c0ff30
Removed unnecessary check after the protocol autodetection.
Now it will try to start streaming even if the autodetection failed.
This will allow to work with web server that doesn't report a
proper mime-type.
author | bertrand |
---|---|
date | Wed, 19 Dec 2001 09:02:52 +0000 |
parents | ae79207a3055 |
children | e7be28567230 |
rev | line source |
---|---|
305 | 1 /* |
2 * Video driver for Framebuffer device | |
3 * by Szabolcs Berecz <szabi@inf.elte.hu> | |
359 | 4 * (C) 2001 |
305 | 5 * |
6 * Some idea and code borrowed from Chris Lawrence's ppmtofb-0.27 | |
7 */ | |
8 | |
393 | 9 #define FBDEV "fbdev: " |
10 | |
225 | 11 #include <stdio.h> |
12 #include <stdlib.h> | |
13 #include <string.h> | |
14 #include <fcntl.h> | |
15 #include <unistd.h> | |
16 #include <errno.h> | |
359 | 17 #include <ctype.h> |
18 #include <assert.h> | |
225 | 19 |
20 #include <sys/mman.h> | |
21 #include <sys/ioctl.h> | |
2354
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
22 #include <sys/kd.h> |
225 | 23 #include <linux/fb.h> |
24 | |
25 #include "config.h" | |
26 #include "video_out.h" | |
27 #include "video_out_internal.h" | |
658 | 28 #include "fastmemcpy.h" |
633 | 29 #include "sub.h" |
2556 | 30 #include "../postproc/rgb2rgb.h" |
225 | 31 |
32 LIBVO_EXTERN(fbdev) | |
33 | |
34 static vo_info_t vo_info = { | |
35 "Framebuffer Device", | |
36 "fbdev", | |
37 "Szabolcs Berecz <szabi@inf.elte.hu>", | |
38 "" | |
39 }; | |
40 | |
379 | 41 extern int verbose; |
42 | |
359 | 43 /****************************** |
393 | 44 * fb.modes support * |
359 | 45 ******************************/ |
46 | |
47 typedef struct { | |
48 char *name; | |
49 uint32_t xres, yres, vxres, vyres, depth; | |
50 uint32_t pixclock, left, right, upper, lower, hslen, vslen; | |
51 uint32_t sync; | |
52 uint32_t vmode; | |
53 } fb_mode_t; | |
54 | |
55 #define PRINT_LINENUM printf(" at line %d\n", line_num) | |
56 | |
57 #define MAX_NR_TOKEN 16 | |
58 | |
59 #define MAX_LINE_LEN 1000 | |
60 | |
61 #define RET_EOF -1 | |
62 #define RET_EOL -2 | |
63 | |
64 static int validate_mode(fb_mode_t *m) | |
65 { | |
66 if (!m->xres) { | |
67 printf("needs geometry "); | |
68 return 0; | |
69 } | |
70 if (!m->pixclock) { | |
71 printf("needs timings "); | |
72 return 0; | |
73 } | |
74 return 1; | |
75 } | |
76 | |
77 static FILE *fp; | |
78 static int line_num = 0; | |
79 static char *line; | |
80 static char *token[MAX_NR_TOKEN]; | |
81 | |
82 static int get_token(int num) | |
83 { | |
84 static int read_nextline = 1; | |
85 static int line_pos; | |
86 int i; | |
87 char c; | |
88 | |
89 if (num >= MAX_NR_TOKEN) { | |
90 printf("get_token(): max >= MAX_NR_TOKEN!"); | |
91 goto out_eof; | |
92 } | |
93 | |
94 if (read_nextline) { | |
95 if (!fgets(line, MAX_LINE_LEN, fp)) | |
96 goto out_eof; | |
97 line_pos = 0; | |
98 ++line_num; | |
99 read_nextline = 0; | |
100 } | |
101 for (i = 0; i < num; i++) { | |
102 while (isspace(line[line_pos])) | |
103 ++line_pos; | |
104 if (line[line_pos] == '\0' || line[line_pos] == '#') { | |
105 read_nextline = 1; | |
106 goto out_eol; | |
107 } | |
108 token[i] = line + line_pos; | |
109 c = line[line_pos]; | |
110 if (c == '"' || c == '\'') { | |
111 token[i]++; | |
112 while (line[++line_pos] != c && line[line_pos]) | |
113 /* NOTHING */; | |
950 | 114 if (!line[line_pos]) |
115 goto out_eol; | |
116 line[line_pos] = ' '; | |
359 | 117 } else { |
118 for (/* NOTHING */; !isspace(line[line_pos]) && | |
119 line[line_pos]; line_pos++) | |
120 /* NOTHING */; | |
121 } | |
122 if (!line[line_pos]) { | |
123 read_nextline = 1; | |
124 if (i == num - 1) | |
125 goto out_ok; | |
126 goto out_eol; | |
127 } | |
950 | 128 line[line_pos++] = '\0'; |
359 | 129 } |
130 out_ok: | |
131 return i; | |
132 out_eof: | |
133 return RET_EOF; | |
134 out_eol: | |
135 return RET_EOL; | |
136 } | |
137 | |
138 static fb_mode_t *fb_modes = NULL; | |
139 static int nr_modes = 0; | |
140 | |
141 static int parse_fbmode_cfg(char *cfgfile) | |
142 { | |
977 | 143 #define CHECK_IN_MODE_DEF\ |
144 do {\ | |
145 if (!in_mode_def) {\ | |
146 printf("'needs 'mode' first");\ | |
147 goto err_out_print_linenum;\ | |
148 }\ | |
149 } while (0) | |
150 | |
359 | 151 fb_mode_t *mode = NULL; |
152 char *endptr; // strtoul()... | |
977 | 153 int in_mode_def = 0; |
359 | 154 int tmp, i; |
155 | |
950 | 156 if (verbose > 0) |
157 printf("Reading %s: ", cfgfile); | |
359 | 158 |
159 if ((fp = fopen(cfgfile, "r")) == NULL) { | |
160 printf("can't open '%s': %s\n", cfgfile, strerror(errno)); | |
161 return -1; | |
162 } | |
163 | |
164 if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) { | |
165 printf("can't get memory for 'line': %s\n", strerror(errno)); | |
166 return -2; | |
167 } | |
168 | |
169 /* | |
170 * check if the cfgfile starts with 'mode' | |
171 */ | |
172 while ((tmp = get_token(1)) == RET_EOL) | |
173 /* NOTHING */; | |
174 if (tmp == RET_EOF) | |
175 goto out; | |
176 if (!strcmp(token[0], "mode")) | |
177 goto loop_enter; | |
178 goto err_out_parse_error; | |
179 | |
180 while ((tmp = get_token(1)) != RET_EOF) { | |
181 if (tmp == RET_EOL) | |
182 continue; | |
183 if (!strcmp(token[0], "mode")) { | |
977 | 184 if (in_mode_def) { |
185 printf("'endmode' required"); | |
186 goto err_out_print_linenum; | |
187 } | |
359 | 188 if (!validate_mode(mode)) |
189 goto err_out_not_valid; | |
190 loop_enter: | |
191 if (!(fb_modes = (fb_mode_t *) realloc(fb_modes, | |
192 sizeof(fb_mode_t) * (nr_modes + 1)))) { | |
950 | 193 printf("can't realloc 'fb_modes' (nr_modes = %d):" |
194 " %s\n", nr_modes, strerror(errno)); | |
359 | 195 goto err_out; |
196 } | |
197 mode=fb_modes + nr_modes; | |
198 ++nr_modes; | |
199 memset(mode,0,sizeof(fb_mode_t)); | |
225 | 200 |
359 | 201 if (get_token(1) < 0) |
202 goto err_out_parse_error; | |
203 for (i = 0; i < nr_modes - 1; i++) { | |
204 if (!strcmp(token[0], fb_modes[i].name)) { | |
205 printf("mode name '%s' isn't unique", token[0]); | |
206 goto err_out_print_linenum; | |
207 } | |
208 } | |
209 if (!(mode->name = strdup(token[0]))) { | |
210 printf("can't strdup -> 'name': %s\n", strerror(errno)); | |
211 goto err_out; | |
212 } | |
977 | 213 in_mode_def = 1; |
359 | 214 } else if (!strcmp(token[0], "geometry")) { |
977 | 215 CHECK_IN_MODE_DEF; |
359 | 216 if (get_token(5) < 0) |
217 goto err_out_parse_error; | |
218 mode->xres = strtoul(token[0], &endptr, 0); | |
219 if (*endptr) | |
220 goto err_out_parse_error; | |
221 mode->yres = strtoul(token[1], &endptr, 0); | |
222 if (*endptr) | |
223 goto err_out_parse_error; | |
224 mode->vxres = strtoul(token[2], &endptr, 0); | |
225 if (*endptr) | |
226 goto err_out_parse_error; | |
227 mode->vyres = strtoul(token[3], &endptr, 0); | |
228 if (*endptr) | |
229 goto err_out_parse_error; | |
230 mode->depth = strtoul(token[4], &endptr, 0); | |
231 if (*endptr) | |
232 goto err_out_parse_error; | |
233 } else if (!strcmp(token[0], "timings")) { | |
977 | 234 CHECK_IN_MODE_DEF; |
359 | 235 if (get_token(7) < 0) |
236 goto err_out_parse_error; | |
237 mode->pixclock = strtoul(token[0], &endptr, 0); | |
238 if (*endptr) | |
239 goto err_out_parse_error; | |
240 mode->left = strtoul(token[1], &endptr, 0); | |
241 if (*endptr) | |
242 goto err_out_parse_error; | |
243 mode->right = strtoul(token[2], &endptr, 0); | |
244 if (*endptr) | |
245 goto err_out_parse_error; | |
246 mode->upper = strtoul(token[3], &endptr, 0); | |
247 if (*endptr) | |
248 goto err_out_parse_error; | |
249 mode->lower = strtoul(token[4], &endptr, 0); | |
250 if (*endptr) | |
251 goto err_out_parse_error; | |
252 mode->hslen = strtoul(token[5], &endptr, 0); | |
253 if (*endptr) | |
254 goto err_out_parse_error; | |
255 mode->vslen = strtoul(token[6], &endptr, 0); | |
256 if (*endptr) | |
257 goto err_out_parse_error; | |
258 } else if (!strcmp(token[0], "endmode")) { | |
977 | 259 CHECK_IN_MODE_DEF; |
260 in_mode_def = 0; | |
383 | 261 } else if (!strcmp(token[0], "accel")) { |
977 | 262 CHECK_IN_MODE_DEF; |
383 | 263 if (get_token(1) < 0) |
264 goto err_out_parse_error; | |
393 | 265 /* |
266 * it's only used for text acceleration | |
267 * so we just ignore it. | |
268 */ | |
359 | 269 } else if (!strcmp(token[0], "hsync")) { |
977 | 270 CHECK_IN_MODE_DEF; |
359 | 271 if (get_token(1) < 0) |
272 goto err_out_parse_error; | |
273 if (!strcmp(token[0], "low")) | |
274 mode->sync &= ~FB_SYNC_HOR_HIGH_ACT; | |
275 else if(!strcmp(token[0], "high")) | |
276 mode->sync |= FB_SYNC_HOR_HIGH_ACT; | |
277 else | |
278 goto err_out_parse_error; | |
279 } else if (!strcmp(token[0], "vsync")) { | |
977 | 280 CHECK_IN_MODE_DEF; |
359 | 281 if (get_token(1) < 0) |
282 goto err_out_parse_error; | |
283 if (!strcmp(token[0], "low")) | |
284 mode->sync &= ~FB_SYNC_VERT_HIGH_ACT; | |
285 else if(!strcmp(token[0], "high")) | |
286 mode->sync |= FB_SYNC_VERT_HIGH_ACT; | |
287 else | |
288 goto err_out_parse_error; | |
289 } else if (!strcmp(token[0], "csync")) { | |
977 | 290 CHECK_IN_MODE_DEF; |
359 | 291 if (get_token(1) < 0) |
292 goto err_out_parse_error; | |
293 if (!strcmp(token[0], "low")) | |
294 mode->sync &= ~FB_SYNC_COMP_HIGH_ACT; | |
295 else if(!strcmp(token[0], "high")) | |
296 mode->sync |= FB_SYNC_COMP_HIGH_ACT; | |
297 else | |
298 goto err_out_parse_error; | |
299 } else if (!strcmp(token[0], "extsync")) { | |
977 | 300 CHECK_IN_MODE_DEF; |
359 | 301 if (get_token(1) < 0) |
302 goto err_out_parse_error; | |
303 if (!strcmp(token[0], "false")) | |
304 mode->sync &= ~FB_SYNC_EXT; | |
305 else if(!strcmp(token[0], "true")) | |
306 mode->sync |= FB_SYNC_EXT; | |
307 else | |
308 goto err_out_parse_error; | |
309 } else if (!strcmp(token[0], "laced")) { | |
977 | 310 CHECK_IN_MODE_DEF; |
359 | 311 if (get_token(1) < 0) |
312 goto err_out_parse_error; | |
313 if (!strcmp(token[0], "false")) | |
314 mode->vmode = FB_VMODE_NONINTERLACED; | |
315 else if (!strcmp(token[0], "true")) | |
316 mode->vmode = FB_VMODE_INTERLACED; | |
317 else | |
318 goto err_out_parse_error; | |
479 | 319 } else if (!strcmp(token[0], "double")) { |
977 | 320 CHECK_IN_MODE_DEF; |
359 | 321 if (get_token(1) < 0) |
322 goto err_out_parse_error; | |
323 if (!strcmp(token[0], "false")) | |
324 ; | |
325 else if (!strcmp(token[0], "true")) | |
326 mode->vmode = FB_VMODE_DOUBLE; | |
327 else | |
328 goto err_out_parse_error; | |
329 } else | |
330 goto err_out_parse_error; | |
331 } | |
332 if (!validate_mode(mode)) | |
333 goto err_out_not_valid; | |
334 out: | |
950 | 335 if (verbose > 0) |
336 printf("%d modes\n", nr_modes); | |
359 | 337 free(line); |
338 fclose(fp); | |
339 return nr_modes; | |
340 err_out_parse_error: | |
341 printf("parse error"); | |
342 err_out_print_linenum: | |
343 PRINT_LINENUM; | |
344 err_out: | |
393 | 345 if (fb_modes) { |
359 | 346 free(fb_modes); |
393 | 347 fb_modes = NULL; |
348 } | |
349 nr_modes = 0; | |
359 | 350 free(line); |
351 free(fp); | |
352 return -2; | |
353 err_out_not_valid: | |
950 | 354 printf("previous mode is not correct"); |
359 | 355 goto err_out_print_linenum; |
356 } | |
357 | |
358 static fb_mode_t *find_mode_by_name(char *name) | |
359 { | |
360 int i; | |
361 | |
658 | 362 for (i = 0; i < nr_modes; i++) |
359 | 363 if (!strcmp(name, fb_modes[i].name)) |
364 return fb_modes + i; | |
365 return NULL; | |
366 } | |
367 | |
393 | 368 static float dcf(fb_mode_t *m) //driving clock frequency |
369 { | |
519 | 370 return 1e12f / m->pixclock; |
393 | 371 } |
372 | |
373 static float hsf(fb_mode_t *m) //horizontal scan frequency | |
374 { | |
375 int htotal = m->left + m->xres + m->right + m->hslen; | |
376 return dcf(m) / htotal; | |
377 } | |
378 | |
379 static float vsf(fb_mode_t *m) //vertical scan frequency | |
380 { | |
381 int vtotal = m->upper + m->yres + m->lower + m->vslen; | |
382 return hsf(m) / vtotal; | |
383 } | |
384 | |
385 typedef struct { | |
386 float min; | |
387 float max; | |
418 | 388 } range_t; |
393 | 389 |
418 | 390 static int in_range(range_t *r, float f) |
393 | 391 { |
658 | 392 for (/* NOTHING */; (r->min != -1 && r->max != -1); r++) |
393 | 393 if (f >= r->min && f <= r->max) |
394 return 1; | |
395 return 0; | |
396 } | |
397 | |
1561 | 398 static int mode_works(fb_mode_t *m, range_t *hfreq, range_t *vfreq, |
399 range_t *dotclock) | |
400 { | |
401 float h = hsf(m); | |
402 float v = vsf(m); | |
403 float d = dcf(m); | |
404 int ret = 1; | |
405 | |
406 if (verbose > 1) | |
407 printf(FBDEV "mode %dx%d:", m->xres, m->yres); | |
408 if (!in_range(hfreq, h)) { | |
409 ret = 0; | |
410 if (verbose > 1) | |
411 printf(" hsync out of range."); | |
412 } | |
413 if (!in_range(vfreq, v)) { | |
414 ret = 0; | |
415 if (verbose > 1) | |
416 printf(" vsync out of range."); | |
417 } | |
418 if (!in_range(dotclock, d)) { | |
419 ret = 0; | |
420 if (verbose > 1) | |
421 printf(" dotclock out of range."); | |
422 } | |
423 if (verbose > 1) { | |
424 if (ret) | |
425 printf(" hsync, vsync, dotclock ok.\n"); | |
426 else | |
427 printf("\n"); | |
428 } | |
429 | |
430 return ret; | |
431 } | |
432 | |
418 | 433 static fb_mode_t *find_best_mode(int xres, int yres, range_t *hfreq, |
434 range_t *vfreq, range_t *dotclock) | |
393 | 435 { |
436 int i; | |
437 fb_mode_t *best = fb_modes; | |
519 | 438 fb_mode_t *curr; |
439 | |
1561 | 440 if (verbose > 1) |
441 printf(FBDEV "Searching for first working mode\n"); | |
442 | |
950 | 443 for (i = 0; i < nr_modes; i++, best++) |
1561 | 444 if (mode_works(best, hfreq, vfreq, dotclock)) |
519 | 445 break; |
446 | |
950 | 447 if (i == nr_modes) |
519 | 448 return NULL; |
950 | 449 if (i == nr_modes - 1) |
519 | 450 return best; |
393 | 451 |
1561 | 452 if (verbose > 1) { |
453 printf(FBDEV "First working mode: %dx%d\n", best->xres, best->yres); | |
454 printf(FBDEV "Searching for better modes\n"); | |
455 } | |
950 | 456 |
1561 | 457 for (curr = best + 1; i < nr_modes - 1; i++, curr++) { |
458 if (!mode_works(curr, hfreq, vfreq, dotclock)) | |
519 | 459 continue; |
1561 | 460 |
519 | 461 if (verbose > 1) |
1561 | 462 printf(FBDEV); |
463 | |
464 if (best->xres < xres || best->yres < yres) { | |
465 if (curr->xres > best->xres || curr->yres > best->yres) { | |
519 | 466 if (verbose > 1) |
1561 | 467 printf("better than %dx%d, which is too small.\n", |
519 | 468 best->xres, best->yres); |
393 | 469 best = curr; |
519 | 470 } else if (verbose > 1) |
1561 | 471 printf("too small.\n"); |
472 } else if (curr->xres == best->xres && curr->yres == best->yres && | |
473 vsf(curr) > vsf(best)) { | |
474 if (verbose > 1) | |
475 printf("faster screen refresh.\n"); | |
476 best = curr; | |
477 } else if ((curr->xres <= best->xres && curr->yres <= best->yres) && | |
478 (curr->xres >= xres && curr->yres >= yres)) { | |
479 if (verbose > 1) | |
480 printf("better than %dx%d, which is too large.\n", | |
481 best->xres, best->yres); | |
482 best = curr; | |
483 } else if (verbose > 1) { | |
484 if (curr->xres < xres || curr->yres < yres) | |
485 printf("too small.\n"); | |
486 else if (curr->xres > best->xres || curr->yres > best->yres) | |
487 printf("too large.\n"); | |
488 else printf("it's worse, don't know why.\n"); | |
489 } | |
393 | 490 } |
1561 | 491 |
393 | 492 return best; |
493 } | |
494 | |
418 | 495 static void set_bpp(struct fb_var_screeninfo *p, int bpp) |
496 { | |
476 | 497 p->bits_per_pixel = (bpp + 1) & ~1; |
1087 | 498 p->red.msb_right = p->green.msb_right = p->blue.msb_right = p->transp.msb_right = 0; |
563 | 499 p->transp.offset = p->transp.length = 0; |
950 | 500 p->blue.offset = 0; |
418 | 501 switch (bpp) { |
502 case 32: | |
563 | 503 p->transp.offset = 24; |
504 p->transp.length = 8; | |
418 | 505 case 24: |
506 p->red.offset = 16; | |
507 p->red.length = 8; | |
508 p->green.offset = 8; | |
509 p->green.length = 8; | |
550 | 510 p->blue.length = 8; |
418 | 511 break; |
512 case 16: | |
513 p->red.offset = 11; | |
550 | 514 p->green.length = 6; |
418 | 515 p->red.length = 5; |
516 p->green.offset = 5; | |
550 | 517 p->blue.length = 5; |
418 | 518 break; |
519 case 15: | |
520 p->red.offset = 10; | |
550 | 521 p->green.length = 5; |
418 | 522 p->red.length = 5; |
523 p->green.offset = 5; | |
550 | 524 p->blue.length = 5; |
418 | 525 break; |
526 } | |
527 } | |
528 | |
529 static void fb_mode2fb_vinfo(fb_mode_t *m, struct fb_var_screeninfo *v) | |
530 { | |
531 v->xres = m->xres; | |
532 v->yres = m->yres; | |
533 v->xres_virtual = m->vxres; | |
534 v->yres_virtual = m->vyres; | |
535 set_bpp(v, m->depth); | |
536 v->pixclock = m->pixclock; | |
537 v->left_margin = m->left; | |
538 v->right_margin = m->right; | |
539 v->upper_margin = m->upper; | |
540 v->lower_margin = m->lower; | |
541 v->hsync_len = m->hslen; | |
542 v->vsync_len = m->vslen; | |
543 v->sync = m->sync; | |
544 v->vmode = m->vmode; | |
545 } | |
546 | |
547 static range_t *str2range(char *s) | |
548 { | |
549 float tmp_min, tmp_max; | |
550 char *endptr = s; // to start the loop | |
551 range_t *r = NULL; | |
950 | 552 int i; |
418 | 553 |
554 if (!s) | |
555 return NULL; | |
556 for (i = 0; *endptr; i++) { | |
557 if (*s == ',') | |
558 goto out_err; | |
538 | 559 if (!(r = (range_t *) realloc(r, sizeof(*r) * (i + 2)))) { |
418 | 560 printf("can't realloc 'r'\n"); |
561 return NULL; | |
562 } | |
563 tmp_min = strtod(s, &endptr); | |
564 if (*endptr == 'k' || *endptr == 'K') { | |
565 tmp_min *= 1000.0; | |
566 endptr++; | |
567 } else if (*endptr == 'm' || *endptr == 'M') { | |
568 tmp_min *= 1000000.0; | |
569 endptr++; | |
570 } | |
571 if (*endptr == '-') { | |
572 tmp_max = strtod(endptr + 1, &endptr); | |
573 if (*endptr == 'k' || *endptr == 'K') { | |
574 tmp_max *= 1000.0; | |
575 endptr++; | |
576 } else if (*endptr == 'm' || *endptr == 'M') { | |
577 tmp_max *= 1000000.0; | |
578 endptr++; | |
579 } | |
580 if (*endptr != ',' && *endptr) | |
581 goto out_err; | |
582 } else if (*endptr == ',' || !*endptr) { | |
583 tmp_max = tmp_min; | |
584 } else | |
585 goto out_err; | |
586 r[i].min = tmp_min; | |
587 r[i].max = tmp_max; | |
950 | 588 if (r[i].min < 0 || r[i].max < 0) |
589 goto out_err; | |
418 | 590 s = endptr + 1; |
591 } | |
592 r[i].min = r[i].max = -1; | |
593 return r; | |
594 out_err: | |
595 if (r) | |
596 free(r); | |
597 return NULL; | |
598 } | |
599 | |
359 | 600 /****************************** |
601 * vo_fbdev * | |
602 ******************************/ | |
603 | |
658 | 604 /* command line/config file options */ |
393 | 605 char *fb_dev_name = NULL; |
606 char *fb_mode_cfgfile = "/etc/fb.modes"; | |
607 char *fb_mode_name = NULL; | |
418 | 608 char *monitor_hfreq_str = NULL; |
609 char *monitor_vfreq_str = NULL; | |
610 char *monitor_dotclock_str = NULL; | |
611 | |
658 | 612 /* fb.modes related variables */ |
1087 | 613 static range_t *monitor_hfreq = NULL; |
614 static range_t *monitor_vfreq = NULL; | |
615 static range_t *monitor_dotclock = NULL; | |
658 | 616 static fb_mode_t *fb_mode = NULL; |
393 | 617 |
950 | 618 /* vt related variables */ |
1087 | 619 static int vt_fd; |
620 static FILE *vt_fp; | |
621 static int vt_doit = 1; | |
950 | 622 |
658 | 623 /* vo_fbdev related variables */ |
225 | 624 static int fb_dev_fd; |
2354
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
625 static int fb_tty_fd; |
225 | 626 static size_t fb_size; |
627 static uint8_t *frame_buffer; | |
658 | 628 static uint8_t *L123123875; /* thx .so :) */ |
359 | 629 static struct fb_fix_screeninfo fb_finfo; |
630 static struct fb_var_screeninfo fb_orig_vinfo; | |
631 static struct fb_var_screeninfo fb_vinfo; | |
481 | 632 static struct fb_cmap fb_oldcmap; |
633 static int fb_cmap_changed = 0; | |
359 | 634 static int fb_pixel_size; // 32: 4 24: 3 16: 2 15: 2 |
635 static int fb_real_bpp; // 32: 24 24: 24 16: 16 15: 15 | |
636 static int fb_bpp; // 32: 32 24: 24 16: 16 15: 15 | |
393 | 637 static int fb_bpp_we_want; // 32: 32 24: 24 16: 16 15: 15 |
950 | 638 static int fb_line_len; |
639 static int fb_xres; | |
640 static int fb_yres; | |
658 | 641 static void (*draw_alpha_p)(int w, int h, unsigned char *src, |
642 unsigned char *srca, int stride, unsigned char *dst, | |
643 int dstride); | |
359 | 644 |
645 static uint8_t *next_frame; | |
225 | 646 static int in_width; |
647 static int in_height; | |
648 static int out_width; | |
649 static int out_height; | |
950 | 650 static int first_row; |
651 static int last_row; | |
225 | 652 static uint32_t pixel_format; |
804 | 653 static int fs; |
654 static int flip; | |
225 | 655 |
305 | 656 /* |
657 * Note: this function is completely cut'n'pasted from | |
658 * Chris Lawrence's code. | |
311 | 659 * (modified a bit to fit in my code...) |
305 | 660 */ |
661 struct fb_cmap *make_directcolor_cmap(struct fb_var_screeninfo *var) | |
662 { | |
663 /* Hopefully any DIRECTCOLOR device will have a big enough palette | |
664 * to handle mapping the full color depth. | |
665 * e.g. 8 bpp -> 256 entry palette | |
666 * | |
667 * We could handle some sort of gamma here | |
668 */ | |
669 int i, cols, rcols, gcols, bcols; | |
670 uint16_t *red, *green, *blue; | |
671 struct fb_cmap *cmap; | |
672 | |
673 rcols = 1 << var->red.length; | |
674 gcols = 1 << var->green.length; | |
675 bcols = 1 << var->blue.length; | |
676 | |
677 /* Make our palette the length of the deepest color */ | |
678 cols = (rcols > gcols ? rcols : gcols); | |
679 cols = (cols > bcols ? cols : bcols); | |
680 | |
681 red = malloc(cols * sizeof(red[0])); | |
682 if(!red) { | |
683 printf("Can't allocate red palette with %d entries.\n", cols); | |
684 return NULL; | |
685 } | |
686 for(i=0; i< rcols; i++) | |
687 red[i] = (65535/(rcols-1)) * i; | |
688 | |
689 green = malloc(cols * sizeof(green[0])); | |
690 if(!green) { | |
691 printf("Can't allocate green palette with %d entries.\n", cols); | |
692 free(red); | |
693 return NULL; | |
694 } | |
695 for(i=0; i< gcols; i++) | |
696 green[i] = (65535/(gcols-1)) * i; | |
697 | |
698 blue = malloc(cols * sizeof(blue[0])); | |
699 if(!blue) { | |
700 printf("Can't allocate blue palette with %d entries.\n", cols); | |
701 free(red); | |
702 free(green); | |
703 return NULL; | |
704 } | |
705 for(i=0; i< bcols; i++) | |
706 blue[i] = (65535/(bcols-1)) * i; | |
707 | |
708 cmap = malloc(sizeof(struct fb_cmap)); | |
709 if(!cmap) { | |
710 printf("Can't allocate color map\n"); | |
711 free(red); | |
712 free(green); | |
713 free(blue); | |
714 return NULL; | |
715 } | |
716 cmap->start = 0; | |
717 cmap->transp = 0; | |
718 cmap->len = cols; | |
719 cmap->red = red; | |
720 cmap->blue = blue; | |
721 cmap->green = green; | |
722 cmap->transp = NULL; | |
723 | |
724 return cmap; | |
725 } | |
225 | 726 |
393 | 727 static int fb_preinit(void) |
225 | 728 { |
950 | 729 static int fb_preinit_done = 0; |
730 static int fb_works = 0; | |
731 | |
732 if (fb_preinit_done) | |
733 return fb_works; | |
734 | |
393 | 735 if (!fb_dev_name && !(fb_dev_name = getenv("FRAMEBUFFER"))) |
736 fb_dev_name = "/dev/fb0"; | |
737 if (verbose > 0) | |
738 printf(FBDEV "using %s\n", fb_dev_name); | |
225 | 739 |
393 | 740 if ((fb_dev_fd = open(fb_dev_name, O_RDWR)) == -1) { |
741 printf(FBDEV "Can't open %s: %s\n", fb_dev_name, strerror(errno)); | |
742 goto err_out; | |
743 } | |
744 if (ioctl(fb_dev_fd, FBIOGET_VSCREENINFO, &fb_vinfo)) { | |
745 printf(FBDEV "Can't get VSCREENINFO: %s\n", strerror(errno)); | |
746 goto err_out_fd; | |
747 } | |
418 | 748 fb_orig_vinfo = fb_vinfo; |
393 | 749 |
2354
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
750 if ((fb_tty_fd = open("/dev/tty", O_RDWR)) < 0) { |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
751 if (verbose > 0) |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
752 printf(FBDEV "notice: Can't open /dev/tty: %s\n", strerror(errno)); |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
753 } |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
754 |
663 | 755 fb_bpp = fb_vinfo.bits_per_pixel; |
756 | |
1076 | 757 if (fb_bpp == 8 && !vo_dbpp) { |
758 printf(FBDEV "8 bpp output is not supported.\n"); | |
2354
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
759 goto err_out_tty_fd; |
1076 | 760 } |
761 | |
1561 | 762 /* 16 and 15 bpp is reported as 16 bpp */ |
663 | 763 if (fb_bpp == 16) |
764 fb_bpp = fb_vinfo.red.length + fb_vinfo.green.length + | |
765 fb_vinfo.blue.length; | |
766 | |
418 | 767 if (vo_dbpp) { |
768 if (vo_dbpp != 15 && vo_dbpp != 16 && vo_dbpp != 24 && | |
769 vo_dbpp != 32) { | |
770 printf(FBDEV "can't switch to %d bpp\n", vo_dbpp); | |
1076 | 771 goto err_out_fd; |
359 | 772 } |
418 | 773 fb_bpp = vo_dbpp; |
359 | 774 } |
245
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
775 |
393 | 776 fb_preinit_done = 1; |
777 fb_works = 1; | |
950 | 778 return 1; |
2354
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
779 err_out_tty_fd: |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
780 close(fb_tty_fd); |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
781 fb_tty_fd = -1; |
393 | 782 err_out_fd: |
783 close(fb_dev_fd); | |
784 fb_dev_fd = -1; | |
785 err_out: | |
786 fb_preinit_done = 1; | |
950 | 787 fb_works = 0; |
788 return 0; | |
393 | 789 } |
245
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
790 |
633 | 791 static void lots_of_printf(void) |
792 { | |
793 if (verbose > 0) { | |
794 printf(FBDEV "var info:\n"); | |
795 printf(FBDEV "xres: %u\n", fb_vinfo.xres); | |
796 printf(FBDEV "yres: %u\n", fb_vinfo.yres); | |
797 printf(FBDEV "xres_virtual: %u\n", fb_vinfo.xres_virtual); | |
798 printf(FBDEV "yres_virtual: %u\n", fb_vinfo.yres_virtual); | |
799 printf(FBDEV "xoffset: %u\n", fb_vinfo.xoffset); | |
800 printf(FBDEV "yoffset: %u\n", fb_vinfo.yoffset); | |
801 printf(FBDEV "bits_per_pixel: %u\n", fb_vinfo.bits_per_pixel); | |
802 printf(FBDEV "grayscale: %u\n", fb_vinfo.grayscale); | |
803 printf(FBDEV "red: %lu %lu %lu\n", | |
804 (unsigned long) fb_vinfo.red.offset, | |
805 (unsigned long) fb_vinfo.red.length, | |
806 (unsigned long) fb_vinfo.red.msb_right); | |
807 printf(FBDEV "green: %lu %lu %lu\n", | |
808 (unsigned long) fb_vinfo.green.offset, | |
809 (unsigned long) fb_vinfo.green.length, | |
810 (unsigned long) fb_vinfo.green.msb_right); | |
811 printf(FBDEV "blue: %lu %lu %lu\n", | |
812 (unsigned long) fb_vinfo.blue.offset, | |
813 (unsigned long) fb_vinfo.blue.length, | |
814 (unsigned long) fb_vinfo.blue.msb_right); | |
815 printf(FBDEV "transp: %lu %lu %lu\n", | |
816 (unsigned long) fb_vinfo.transp.offset, | |
817 (unsigned long) fb_vinfo.transp.length, | |
818 (unsigned long) fb_vinfo.transp.msb_right); | |
819 printf(FBDEV "nonstd: %u\n", fb_vinfo.nonstd); | |
820 if (verbose > 1) { | |
821 printf(FBDEV "activate: %u\n", fb_vinfo.activate); | |
822 printf(FBDEV "height: %u\n", fb_vinfo.height); | |
823 printf(FBDEV "width: %u\n", fb_vinfo.width); | |
824 printf(FBDEV "accel_flags: %u\n", fb_vinfo.accel_flags); | |
825 printf(FBDEV "timing:\n"); | |
826 printf(FBDEV "pixclock: %u\n", fb_vinfo.pixclock); | |
827 printf(FBDEV "left_margin: %u\n", fb_vinfo.left_margin); | |
828 printf(FBDEV "right_margin: %u\n", fb_vinfo.right_margin); | |
829 printf(FBDEV "upper_margin: %u\n", fb_vinfo.upper_margin); | |
830 printf(FBDEV "lower_margin: %u\n", fb_vinfo.lower_margin); | |
831 printf(FBDEV "hsync_len: %u\n", fb_vinfo.hsync_len); | |
832 printf(FBDEV "vsync_len: %u\n", fb_vinfo.vsync_len); | |
833 printf(FBDEV "sync: %u\n", fb_vinfo.sync); | |
834 printf(FBDEV "vmode: %u\n", fb_vinfo.vmode); | |
835 } | |
836 printf(FBDEV "fix info:\n"); | |
837 printf(FBDEV "framebuffer size: %d bytes\n", fb_finfo.smem_len); | |
838 printf(FBDEV "type: %lu\n", (unsigned long) fb_finfo.type); | |
839 printf(FBDEV "type_aux: %lu\n", (unsigned long) fb_finfo.type_aux); | |
840 printf(FBDEV "visual: %lu\n", (unsigned long) fb_finfo.visual); | |
841 printf(FBDEV "line_length: %lu bytes\n", (unsigned long) fb_finfo.line_length); | |
842 if (verbose > 1) { | |
843 printf(FBDEV "id: %.16s\n", fb_finfo.id); | |
844 printf(FBDEV "smem_start: %p\n", (void *) fb_finfo.smem_start); | |
845 printf(FBDEV "xpanstep: %u\n", fb_finfo.xpanstep); | |
846 printf(FBDEV "ypanstep: %u\n", fb_finfo.ypanstep); | |
847 printf(FBDEV "ywrapstep: %u\n", fb_finfo.ywrapstep); | |
848 printf(FBDEV "mmio_start: %p\n", (void *) fb_finfo.mmio_start); | |
849 printf(FBDEV "mmio_len: %u bytes\n", fb_finfo.mmio_len); | |
850 printf(FBDEV "accel: %u\n", fb_finfo.accel); | |
851 } | |
950 | 852 printf(FBDEV "fb_bpp: %d\n", fb_bpp); |
853 printf(FBDEV "fb_real_bpp: %d\n", fb_real_bpp); | |
854 printf(FBDEV "fb_pixel_size: %d bytes\n", fb_pixel_size); | |
855 printf(FBDEV "other:\n"); | |
856 printf(FBDEV "in_width: %d\n", in_width); | |
857 printf(FBDEV "in_height: %d\n", in_height); | |
858 printf(FBDEV "out_width: %d\n", out_width); | |
859 printf(FBDEV "out_height: %d\n", out_height); | |
860 printf(FBDEV "first_row: %d\n", first_row); | |
861 printf(FBDEV "last_row: %d\n", last_row); | |
862 if (verbose > 1) | |
863 printf(FBDEV "draw_alpha_p:%dbpp = %p\n", fb_bpp, draw_alpha_p); | |
633 | 864 } |
865 } | |
658 | 866 |
950 | 867 static void vt_set_textarea(int u, int l) |
868 { | |
869 /* how can I determine the font height? | |
870 * just use 16 for now | |
871 */ | |
872 int urow = ((u + 15) / 16) + 1; | |
873 int lrow = l / 16; | |
874 | |
875 if (verbose > 1) | |
876 printf(FBDEV "vt_set_textarea(%d,%d): %d,%d\n", u, l, urow, lrow); | |
877 fprintf(vt_fp, "\33[%d;%dr\33[%d;%dH", urow, lrow, lrow, 0); | |
878 fflush(vt_fp); | |
879 } | |
880 | |
393 | 881 static uint32_t init(uint32_t width, uint32_t height, uint32_t d_width, |
882 uint32_t d_height, uint32_t fullscreen, char *title, | |
883 uint32_t format) | |
884 { | |
950 | 885 struct fb_cmap *cmap; |
886 int vm = fullscreen & 0x02; | |
887 int zoom = fullscreen & 0x04; | |
418 | 888 |
950 | 889 fs = fullscreen & 0x01; |
890 flip = fullscreen & 0x08; | |
393 | 891 |
950 | 892 if (!fb_preinit()) |
393 | 893 return 1; |
245
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
894 |
950 | 895 if (zoom) { |
418 | 896 printf(FBDEV "-zoom is not supported\n"); |
897 return 1; | |
898 } | |
950 | 899 if (fb_mode_name && !vm) { |
900 printf(FBDEV "-fbmode can only be used with -vm\n"); | |
418 | 901 return 1; |
902 } | |
950 | 903 if (vm && (parse_fbmode_cfg(fb_mode_cfgfile) < 0)) |
418 | 904 return 1; |
950 | 905 if (d_width && (fs || vm)) { |
418 | 906 out_width = d_width; |
907 out_height = d_height; | |
908 } else { | |
909 out_width = width; | |
910 out_height = height; | |
911 } | |
912 in_width = width; | |
913 in_height = height; | |
914 pixel_format = format; | |
915 | |
393 | 916 if (fb_mode_name) { |
418 | 917 if (!(fb_mode = find_mode_by_name(fb_mode_name))) { |
918 printf(FBDEV "can't find requested video mode\n"); | |
919 return 1; | |
920 } | |
921 fb_mode2fb_vinfo(fb_mode, &fb_vinfo); | |
950 | 922 } else if (vm) { |
418 | 923 monitor_hfreq = str2range(monitor_hfreq_str); |
924 monitor_vfreq = str2range(monitor_vfreq_str); | |
925 monitor_dotclock = str2range(monitor_dotclock_str); | |
926 if (!monitor_hfreq || !monitor_vfreq || !monitor_dotclock) { | |
927 printf(FBDEV "you have to specify the capabilities of" | |
928 " the monitor.\n"); | |
929 return 1; | |
930 } | |
931 if (!(fb_mode = find_best_mode(out_width, out_height, | |
932 monitor_hfreq, monitor_vfreq, | |
933 monitor_dotclock))) { | |
934 printf(FBDEV "can't find best video mode\n"); | |
935 return 1; | |
936 } | |
519 | 937 printf(FBDEV "using mode %dx%d @ %.1fHz\n", fb_mode->xres, |
938 fb_mode->yres, vsf(fb_mode)); | |
418 | 939 fb_mode2fb_vinfo(fb_mode, &fb_vinfo); |
359 | 940 } |
418 | 941 fb_bpp_we_want = fb_bpp; |
942 set_bpp(&fb_vinfo, fb_bpp); | |
359 | 943 fb_vinfo.xres_virtual = fb_vinfo.xres; |
944 fb_vinfo.yres_virtual = fb_vinfo.yres; | |
245
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
945 |
2354
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
946 if (fb_tty_fd >= 0 && ioctl(fb_tty_fd, KDSETMODE, KD_GRAPHICS) < 0) { |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
947 if (verbose > 0) |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
948 printf(FBDEV "Can't set graphics mode: %s\n", strerror(errno)); |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
949 close(fb_tty_fd); |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
950 fb_tty_fd = -1; |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
951 } |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
952 |
359 | 953 if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_vinfo)) { |
393 | 954 printf(FBDEV "Can't put VSCREENINFO: %s\n", strerror(errno)); |
2354
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
955 if (fb_tty_fd >= 0 && ioctl(fb_tty_fd, KDSETMODE, KD_TEXT) < 0) { |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
956 printf(FBDEV "Can't restore text mode: %s\n", strerror(errno)); |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
957 } |
393 | 958 return 1; |
959 } | |
950 | 960 |
961 fb_pixel_size = fb_vinfo.bits_per_pixel / 8; | |
962 fb_real_bpp = fb_vinfo.red.length + fb_vinfo.green.length + | |
963 fb_vinfo.blue.length; | |
964 fb_bpp = (fb_pixel_size == 4) ? 32 : fb_real_bpp; | |
965 if (fb_bpp_we_want != fb_bpp) | |
1076 | 966 printf(FBDEV "requested %d bpp, got %d bpp!!!\n", |
950 | 967 fb_bpp_we_want, fb_bpp); |
968 | |
969 switch (fb_bpp) { | |
970 case 32: | |
971 draw_alpha_p = vo_draw_alpha_rgb32; | |
972 break; | |
973 case 24: | |
974 draw_alpha_p = vo_draw_alpha_rgb24; | |
975 break; | |
976 case 16: | |
977 draw_alpha_p = vo_draw_alpha_rgb16; | |
978 break; | |
979 case 15: | |
980 draw_alpha_p = vo_draw_alpha_rgb15; | |
981 break; | |
982 } | |
983 | |
984 if (flip & ((((pixel_format & 0xff) + 7) / 8) != fb_pixel_size)) { | |
985 printf(FBDEV "Flipped output with depth conversion is not " | |
986 "supported\n"); | |
987 return 1; | |
988 } | |
989 | |
990 fb_xres = fb_vinfo.xres; | |
991 fb_yres = fb_vinfo.yres; | |
992 | |
993 if (vm || fs) { | |
994 out_width = fb_xres; | |
995 out_height = fb_yres; | |
996 } | |
997 if (out_width < in_width || out_height < in_height) { | |
998 printf(FBDEV "screensize is smaller than video size\n"); | |
999 return 1; | |
1000 } | |
1001 | |
1002 first_row = (out_height - in_height) / 2; | |
1003 last_row = (out_height + in_height) / 2; | |
1004 | |
618 | 1005 if (ioctl(fb_dev_fd, FBIOGET_FSCREENINFO, &fb_finfo)) { |
1006 printf(FBDEV "Can't get FSCREENINFO: %s\n", strerror(errno)); | |
1007 return 1; | |
1008 } | |
633 | 1009 |
1010 lots_of_printf(); | |
245
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
1011 |
633 | 1012 if (fb_finfo.type != FB_TYPE_PACKED_PIXELS) { |
1013 printf(FBDEV "type %d not supported\n", fb_finfo.type); | |
1014 return 1; | |
305 | 1015 } |
618 | 1016 |
379 | 1017 switch (fb_finfo.visual) { |
393 | 1018 case FB_VISUAL_TRUECOLOR: |
1019 break; | |
1020 case FB_VISUAL_DIRECTCOLOR: | |
1021 if (verbose > 0) | |
1022 printf(FBDEV "creating cmap for directcolor\n"); | |
481 | 1023 if (ioctl(fb_dev_fd, FBIOGETCMAP, &fb_oldcmap)) { |
393 | 1024 printf(FBDEV "can't get cmap: %s\n", |
1025 strerror(errno)); | |
1026 return 1; | |
1027 } | |
1028 if (!(cmap = make_directcolor_cmap(&fb_vinfo))) | |
1029 return 1; | |
1030 if (ioctl(fb_dev_fd, FBIOPUTCMAP, cmap)) { | |
1031 printf(FBDEV "can't put cmap: %s\n", | |
1032 strerror(errno)); | |
1033 return 1; | |
1034 } | |
481 | 1035 fb_cmap_changed = 1; |
393 | 1036 free(cmap->red); |
1037 free(cmap->green); | |
1038 free(cmap->blue); | |
1039 free(cmap); | |
1040 break; | |
1041 default: | |
1042 printf(FBDEV "visual: %d not yet supported\n", | |
1043 fb_finfo.visual); | |
1044 return 1; | |
245
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
1045 } |
618 | 1046 |
950 | 1047 fb_line_len = fb_finfo.line_length; |
359 | 1048 fb_size = fb_finfo.smem_len; |
225 | 1049 if ((frame_buffer = (uint8_t *) mmap(0, fb_size, PROT_READ | PROT_WRITE, |
1050 MAP_SHARED, fb_dev_fd, 0)) == (uint8_t *) -1) { | |
393 | 1051 printf(FBDEV "Can't mmap %s: %s\n", fb_dev_name, strerror(errno)); |
1052 return 1; | |
225 | 1053 } |
519 | 1054 L123123875 = frame_buffer + (out_width - in_width) * fb_pixel_size / |
950 | 1055 2 + (out_height - in_height) * fb_line_len / 2; |
229 | 1056 |
393 | 1057 if (verbose > 0) { |
519 | 1058 if (verbose > 1) { |
393 | 1059 printf(FBDEV "frame_buffer @ %p\n", frame_buffer); |
519 | 1060 printf(FBDEV "L123123875 @ %p\n", L123123875); |
1061 } | |
950 | 1062 printf(FBDEV "pixel per line: %d\n", fb_line_len / fb_pixel_size); |
379 | 1063 } |
225 | 1064 |
278 | 1065 if (!(next_frame = (uint8_t *) malloc(in_width * in_height * fb_pixel_size))) { |
393 | 1066 printf(FBDEV "Can't malloc next_frame: %s\n", strerror(errno)); |
225 | 1067 return 1; |
1068 } | |
1069 | |
950 | 1070 if (vt_doit && (vt_fd = open("/dev/tty", O_WRONLY)) == -1) { |
1071 printf(FBDEV "can't open /dev/tty: %s\n", strerror(errno)); | |
1072 vt_doit = 0; | |
1073 } | |
1074 if (vt_doit && !(vt_fp = fdopen(vt_fd, "w"))) { | |
1075 printf(FBDEV "can't fdopen /dev/tty: %s\n", strerror(errno)); | |
1076 vt_doit = 0; | |
804 | 1077 } |
950 | 1078 |
1079 if (vt_doit) | |
1080 vt_set_textarea(last_row, fb_yres); | |
1081 | |
1082 if (fs || vm) | |
1083 memset(frame_buffer, '\0', fb_line_len * fb_yres); | |
1084 | |
225 | 1085 if (format == IMGFMT_YV12) |
359 | 1086 yuv2rgb_init(fb_bpp, MODE_RGB); |
950 | 1087 |
225 | 1088 return 0; |
1089 } | |
1090 | |
1091 static uint32_t query_format(uint32_t format) | |
1092 { | |
658 | 1093 int ret = 0x4; /* osd/sub is supported on every bpp */ |
519 | 1094 |
950 | 1095 if (!fb_preinit()) |
305 | 1096 return 0; |
1097 | |
311 | 1098 if ((format & IMGFMT_BGR_MASK) == IMGFMT_BGR) { |
1099 int bpp = format & 0xff; | |
519 | 1100 |
359 | 1101 if (bpp == fb_bpp) |
519 | 1102 return ret|0x2; |
359 | 1103 else if (bpp == 15 && fb_bpp == 16) |
519 | 1104 return ret|0x1; |
359 | 1105 else if (bpp == 24 && fb_bpp == 32) |
519 | 1106 return ret|0x1; |
311 | 1107 } |
1108 if (format == IMGFMT_YV12) | |
658 | 1109 return ret|0x1; |
311 | 1110 return 0; |
225 | 1111 } |
1112 | |
1113 static const vo_info_t *get_info(void) | |
1114 { | |
1115 return &vo_info; | |
1116 } | |
1117 | |
1118 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, | |
1119 unsigned char *srca, int stride) | |
1120 { | |
658 | 1121 unsigned char *dst = next_frame + (in_width * y0 + x0) * fb_pixel_size; |
359 | 1122 int dstride = in_width * fb_pixel_size; |
1123 | |
658 | 1124 (*draw_alpha_p)(w, h, src, srca, stride, dst, dstride); |
225 | 1125 } |
1126 | |
1127 static uint32_t draw_frame(uint8_t *src[]) | |
1128 { | |
1129 if (pixel_format == IMGFMT_YV12) { | |
1130 yuv2rgb(next_frame, src[0], src[1], src[2], in_width, | |
278 | 1131 in_height, in_width * fb_pixel_size, |
225 | 1132 in_width, in_width / 2); |
804 | 1133 } else if (flip) { |
1134 int h = in_height; | |
1135 int len = in_width * fb_pixel_size; | |
1136 char *d = next_frame + (in_height - 1) * len; | |
1137 char *s = src[0]; | |
1138 while (h--) { | |
1139 memcpy(d, s, len); | |
1140 s += len; | |
1141 d -= len; | |
1142 } | |
311 | 1143 } else { |
1144 int sbpp = ((pixel_format & 0xff) + 7) / 8; | |
1145 char *d = next_frame; | |
1146 char *s = src[0]; | |
1147 if (sbpp == fb_pixel_size) { | |
2556 | 1148 if (fb_real_bpp == 16 && pixel_format == (IMGFMT_BGR|15)) |
1149 rgb15to16(s, d, 2 * in_width * in_height); | |
1150 else | |
1151 memcpy(d, s, sbpp * in_width * in_height); | |
311 | 1152 } |
1153 } | |
225 | 1154 return 0; |
1155 } | |
1156 | |
1157 static uint32_t draw_slice(uint8_t *src[], int stride[], int w, int h, int x, | |
1158 int y) | |
1159 { | |
1160 uint8_t *dest; | |
1161 | |
278 | 1162 dest = next_frame + (in_width * y + x) * fb_pixel_size; |
1163 yuv2rgb(dest, src[0], src[1], src[2], w, h, in_width * fb_pixel_size, | |
225 | 1164 stride[0], stride[1]); |
1165 return 0; | |
1166 } | |
1167 | |
1168 static void check_events(void) | |
1169 { | |
1170 } | |
1171 | |
519 | 1172 static void put_frame(void) |
225 | 1173 { |
1174 int i, out_offset = 0, in_offset = 0; | |
1175 | |
1176 for (i = 0; i < in_height; i++) { | |
519 | 1177 memcpy(L123123875 + out_offset, next_frame + in_offset, |
423 | 1178 in_width * fb_pixel_size); |
950 | 1179 out_offset += fb_line_len; |
278 | 1180 in_offset += in_width * fb_pixel_size; |
225 | 1181 } |
1182 } | |
1183 | |
1501
d40f2b686846
changes according to -utf8 option, draw_osd() function added
atlka
parents:
1087
diff
changeset
|
1184 static void draw_osd(void) |
d40f2b686846
changes according to -utf8 option, draw_osd() function added
atlka
parents:
1087
diff
changeset
|
1185 { |
d40f2b686846
changes according to -utf8 option, draw_osd() function added
atlka
parents:
1087
diff
changeset
|
1186 vo_draw_text(in_width, in_height, draw_alpha); |
d40f2b686846
changes according to -utf8 option, draw_osd() function added
atlka
parents:
1087
diff
changeset
|
1187 } |
d40f2b686846
changes according to -utf8 option, draw_osd() function added
atlka
parents:
1087
diff
changeset
|
1188 |
246 | 1189 static void flip_page(void) |
1190 { | |
519 | 1191 put_frame(); |
246 | 1192 } |
1193 | |
225 | 1194 static void uninit(void) |
1195 { | |
379 | 1196 if (verbose > 0) |
393 | 1197 printf(FBDEV "uninit\n"); |
481 | 1198 if (fb_cmap_changed) { |
1199 if (ioctl(fb_dev_fd, FBIOPUTCMAP, &fb_oldcmap)) | |
393 | 1200 printf(FBDEV "Can't restore original cmap\n"); |
481 | 1201 fb_cmap_changed = 0; |
306 | 1202 } |
503 | 1203 free(next_frame); |
1204 if (ioctl(fb_dev_fd, FBIOGET_VSCREENINFO, &fb_vinfo)) | |
1205 printf(FBDEV "ioctl FBIOGET_VSCREENINFO: %s\n", strerror(errno)); | |
1206 fb_orig_vinfo.xoffset = fb_vinfo.xoffset; | |
1207 fb_orig_vinfo.yoffset = fb_vinfo.yoffset; | |
379 | 1208 if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_orig_vinfo)) |
503 | 1209 printf(FBDEV "Can't reset original fb_var_screeninfo: %s\n", strerror(errno)); |
2354
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
1210 if (fb_tty_fd >= 0) { |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
1211 if (ioctl(fb_tty_fd, KDSETMODE, KD_TEXT) < 0) |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
1212 printf(FBDEV "Can't restore text mode: %s\n", strerror(errno)); |
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
1213 } |
950 | 1214 if (vt_doit) |
1215 vt_set_textarea(0, fb_orig_vinfo.yres); | |
2354
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
1216 close(fb_tty_fd); |
359 | 1217 close(fb_dev_fd); |
225 | 1218 munmap(frame_buffer, fb_size); |
1219 } | |
2354
0e2f4c4e55d4
Applied patch to switch to graphics mode with -fs by achurch@achurch.org (Andrew Church)
atmos4
parents:
1561
diff
changeset
|
1220 |