Mercurial > mplayer.hg
annotate libvo/vo_fbdev.c @ 305:6c3a6322f81c
directcolor support?
author | szabii |
---|---|
date | Sat, 07 Apr 2001 22:03:18 +0000 |
parents | 604b37178b3d |
children | 344d115a285d |
rev | line source |
---|---|
305 | 1 /* |
2 * Video driver for Framebuffer device | |
3 * by Szabolcs Berecz <szabi@inf.elte.hu> | |
4 * | |
5 * Some idea and code borrowed from Chris Lawrence's ppmtofb-0.27 | |
6 */ | |
7 | |
225 | 8 #include <stdio.h> |
9 #include <stdlib.h> | |
10 #include <string.h> | |
11 #include <fcntl.h> | |
12 #include <unistd.h> | |
13 #include <errno.h> | |
14 | |
15 #include <sys/mman.h> | |
16 #include <sys/ioctl.h> | |
17 #include <linux/fb.h> | |
18 #include <linux/vt.h> | |
19 | |
20 #include "config.h" | |
21 #include "video_out.h" | |
22 #include "video_out_internal.h" | |
23 | |
24 #include "yuv2rgb.h" | |
25 | |
26 LIBVO_EXTERN(fbdev) | |
27 | |
28 //#include "yuv2rgb.h" | |
29 | |
30 static vo_info_t vo_info = { | |
31 "Framebuffer Device", | |
32 "fbdev", | |
33 "Szabolcs Berecz <szabi@inf.elte.hu>", | |
34 "" | |
35 }; | |
36 | |
230 | 37 static int vt_active = -1; |
225 | 38 static int vt_fd; |
39 | |
40 char *fb_dev_name = NULL; | |
41 static int fb_dev_fd; | |
42 static size_t fb_size; | |
43 static uint8_t *frame_buffer; | |
278 | 44 static int fb_pixel_size; |
225 | 45 static int fb_bpp; |
229 | 46 struct fb_fix_screeninfo fb_fix_info; |
47 struct fb_var_screeninfo fb_var_info; | |
246 | 48 static uint32_t fb_xres_virtual; |
49 static uint32_t fb_yres_virtual; | |
225 | 50 |
51 static int in_width; | |
52 static int in_height; | |
53 static int out_width; | |
54 static int out_height; | |
55 static uint8_t *next_frame; | |
56 static int screen_width; | |
57 static uint32_t pixel_format; | |
58 | |
229 | 59 static int fb_init_done = 0; |
305 | 60 static int fb_works = 0; |
61 | |
62 /* | |
63 * Note: this function is completely cut'n'pasted from | |
64 * Chris Lawrence's code. | |
65 * (modified to fit in my code :) ) | |
66 */ | |
67 struct fb_cmap *make_directcolor_cmap(struct fb_var_screeninfo *var) | |
68 { | |
69 /* Hopefully any DIRECTCOLOR device will have a big enough palette | |
70 * to handle mapping the full color depth. | |
71 * e.g. 8 bpp -> 256 entry palette | |
72 * | |
73 * We could handle some sort of gamma here | |
74 */ | |
75 int i, cols, rcols, gcols, bcols; | |
76 uint16_t *red, *green, *blue; | |
77 struct fb_cmap *cmap; | |
78 | |
79 rcols = 1 << var->red.length; | |
80 gcols = 1 << var->green.length; | |
81 bcols = 1 << var->blue.length; | |
82 | |
83 /* Make our palette the length of the deepest color */ | |
84 cols = (rcols > gcols ? rcols : gcols); | |
85 cols = (cols > bcols ? cols : bcols); | |
86 | |
87 red = malloc(cols * sizeof(red[0])); | |
88 if(!red) { | |
89 printf("Can't allocate red palette with %d entries.\n", cols); | |
90 return NULL; | |
91 } | |
92 for(i=0; i< rcols; i++) | |
93 red[i] = (65535/(rcols-1)) * i; | |
94 | |
95 green = malloc(cols * sizeof(green[0])); | |
96 if(!green) { | |
97 printf("Can't allocate green palette with %d entries.\n", cols); | |
98 free(red); | |
99 return NULL; | |
100 } | |
101 for(i=0; i< gcols; i++) | |
102 green[i] = (65535/(gcols-1)) * i; | |
103 | |
104 blue = malloc(cols * sizeof(blue[0])); | |
105 if(!blue) { | |
106 printf("Can't allocate blue palette with %d entries.\n", cols); | |
107 free(red); | |
108 free(green); | |
109 return NULL; | |
110 } | |
111 for(i=0; i< bcols; i++) | |
112 blue[i] = (65535/(bcols-1)) * i; | |
113 | |
114 cmap = malloc(sizeof(struct fb_cmap)); | |
115 if(!cmap) { | |
116 printf("Can't allocate color map\n"); | |
117 free(red); | |
118 free(green); | |
119 free(blue); | |
120 return NULL; | |
121 } | |
122 cmap->start = 0; | |
123 cmap->transp = 0; | |
124 cmap->len = cols; | |
125 cmap->red = red; | |
126 cmap->blue = blue; | |
127 cmap->green = green; | |
128 cmap->transp = NULL; | |
129 | |
130 return cmap; | |
131 } | |
225 | 132 |
229 | 133 static int fb_init(void) |
225 | 134 { |
277 | 135 int fd; |
305 | 136 struct fb_cmap *cmap; |
277 | 137 #if 0 |
138 int vt; | |
225 | 139 char vt_name[11]; |
140 struct vt_stat vt_state; | |
141 struct vt_mode vt_mode; | |
142 | |
143 /* get a free vt */ | |
144 if ((fd = open("/dev/tty0", O_WRONLY, 0)) == -1) { | |
145 printf("Can't open /dev/tty0: %s\n", strerror(errno)); | |
146 return 1; | |
147 } | |
148 if (ioctl(fd, VT_OPENQRY, &vt) < 0 || vt == -1) { | |
149 printf("Can't open a free VT: %s\n", strerror(errno)); | |
150 return 1; | |
151 } | |
152 close(fd); | |
277 | 153 |
225 | 154 /* open the vt */ |
155 snprintf(vt_name, 10, "/dev/tty%d", vt); | |
156 if ((vt_fd = open(vt_name, O_RDWR | O_NONBLOCK, 0)) == -1) { | |
157 printf("Can't open %s: %s\n", vt_name, strerror(errno)); | |
158 return 1; | |
159 } | |
160 | |
161 /* save the current vtnum */ | |
162 if (!ioctl(vt_fd, VT_GETSTATE, &vt_state)) | |
163 vt_active = vt_state.v_active; | |
164 | |
165 /* detach the controlling tty */ | |
166 if ((fd = open("/dev/tty", O_RDWR)) >= 0) { | |
167 ioctl(fd, TIOCNOTTY, 0); | |
168 close(fd); | |
169 } | |
277 | 170 |
225 | 171 /* switch to the new vt */ |
172 if (ioctl(vt_fd, VT_ACTIVATE, vt_active)) | |
173 printf("ioctl VT_ACTIVATE: %s\n", strerror(errno)); | |
174 if (ioctl(vt_fd, VT_WAITACTIVE, vt_active)) | |
175 printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno)); | |
176 if (ioctl(vt_fd, VT_GETMODE, &vt_mode) < 0) { | |
177 printf("ioctl VT_GETMODE: %s\n", strerror(errno)); | |
178 return 1; | |
179 } | |
180 signal(SIGUSR1, vt_request); | |
181 vt_mode.mode = VT_PROCESS; | |
182 vt_mode.relsig = SIGUSR1; | |
183 vt_mode.acqsig = SIGUSR1; | |
184 if (ioctl(vt_fd, VT_SETMODE, &vt_mode) < 0) { | |
185 printf("ioctl VT_SETMODE: %s\n", strerror(errno)); | |
186 return 1; | |
187 } | |
188 #endif | |
189 if (!fb_dev_name && !(fb_dev_name = getenv("FRAMEBUFFER"))) | |
190 fb_dev_name = "/dev/fb0"; | |
229 | 191 printf("fb_init: using %s\n", fb_dev_name); |
245
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
192 |
225 | 193 if ((fb_dev_fd = open(fb_dev_name, O_RDWR)) == -1) { |
229 | 194 printf("fb_init: Can't open %s: %s\n", fb_dev_name, strerror(errno)); |
305 | 195 goto err_out; |
225 | 196 } |
245
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
197 |
229 | 198 if (ioctl(fb_dev_fd, FBIOGET_VSCREENINFO, &fb_var_info)) { |
199 printf("fb_init: Can't get VSCREENINFO: %s\n", strerror(errno)); | |
305 | 200 goto err_out_fd; |
225 | 201 } |
245
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
202 |
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
203 /* disable scrolling */ |
246 | 204 fb_xres_virtual = fb_var_info.xres_virtual; |
205 fb_yres_virtual = fb_var_info.yres_virtual; | |
245
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
206 fb_var_info.xres_virtual = fb_var_info.xres; |
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
207 fb_var_info.yres_virtual = fb_var_info.yres; |
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
208 |
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
209 if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_var_info)) { |
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
210 printf("fb_init: Can't put VSCREENINFO: %s\n", strerror(errno)); |
305 | 211 goto err_out_fd; |
245
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
212 } |
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
213 |
229 | 214 if (ioctl(fb_dev_fd, FBIOGET_FSCREENINFO, &fb_fix_info)) { |
215 printf("fb_init: Can't get VSCREENINFO: %s\n", strerror(errno)); | |
305 | 216 goto err_out_fd; |
225 | 217 return 1; |
218 } | |
229 | 219 switch (fb_fix_info.type) { |
225 | 220 case FB_TYPE_VGA_PLANES: |
229 | 221 printf("fb_init: FB_TYPE_VGA_PLANES not supported.\n"); |
305 | 222 goto err_out_fd; |
225 | 223 break; |
224 case FB_TYPE_PLANES: | |
229 | 225 printf("fb_init: FB_TYPE_PLANES not supported.\n"); |
305 | 226 goto err_out_fd; |
225 | 227 break; |
228 case FB_TYPE_INTERLEAVED_PLANES: | |
229 | 229 printf("fb_init: FB_TYPE_INTERLEAVED_PLANES not supported.\n"); |
305 | 230 goto err_out_fd; |
225 | 231 break; |
232 #ifdef FB_TYPE_TEXT | |
233 case FB_TYPE_TEXT: | |
229 | 234 printf("fb_init: FB_TYPE_TEXT not supported.\n"); |
305 | 235 goto err_out_fd; |
225 | 236 break; |
237 #endif | |
238 case FB_TYPE_PACKED_PIXELS: | |
239 /* OK */ | |
229 | 240 printf("fb_init: FB_TYPE_PACKED_PIXELS: OK\n"); |
225 | 241 break; |
242 default: | |
229 | 243 printf("fb_init: unknown FB_TYPE: %d\n", fb_fix_info.type); |
305 | 244 goto err_out_fd; |
245 } | |
246 if (fb_fix_info.visual == FB_VISUAL_DIRECTCOLOR) { | |
247 printf("fb_init: creating cmap for directcolor\n"); | |
248 if (!(cmap = make_directcolor_cmap(&fb_var_info))) | |
249 goto err_out_fd; | |
250 if (ioctl(fb_dev_fd, FBIOPUTCMAP, cmap)) { | |
251 printf("fb_init: can't put cmap: %s\n", | |
252 strerror(errno)); | |
253 goto err_out_fd; | |
254 } | |
255 free(cmap->red); | |
256 free(cmap->green); | |
257 free(cmap->blue); | |
258 free(cmap); | |
245
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
259 } |
cb4c682746c0
disabled scrollback buffer (virtual fb size set to real screen size)
szabii
parents:
231
diff
changeset
|
260 |
278 | 261 fb_pixel_size = fb_var_info.bits_per_pixel / 8; |
262 fb_bpp = fb_var_info.red.length + fb_var_info.green.length + | |
263 fb_var_info.blue.length; | |
229 | 264 screen_width = fb_fix_info.line_length; |
265 fb_size = fb_fix_info.smem_len; | |
225 | 266 if ((frame_buffer = (uint8_t *) mmap(0, fb_size, PROT_READ | PROT_WRITE, |
267 MAP_SHARED, fb_dev_fd, 0)) == (uint8_t *) -1) { | |
229 | 268 printf("fb_init: Can't mmap %s: %s\n", fb_dev_name, strerror(errno)); |
305 | 269 goto err_out_fd; |
225 | 270 } |
229 | 271 |
272 printf("fb_init: framebuffer @ %p\n", frame_buffer); | |
273 printf("fb_init: framebuffer size: %d bytes\n", fb_size); | |
274 printf("fb_init: bpp: %d\n", fb_bpp); | |
278 | 275 printf("fb_init: pixel size: %d\n", fb_pixel_size); |
276 printf("fb_init: pixel per line: %d\n", screen_width / fb_pixel_size); | |
229 | 277 printf("fb_init: visual: %d\n", fb_fix_info.visual); |
277 | 278 printf("fb_init: red: %d %d %d\n", fb_var_info.red.offset, |
279 fb_var_info.red.length, fb_var_info.red.msb_right); | |
280 printf("fb_init: green: %d %d %d\n", fb_var_info.green.offset, | |
281 fb_var_info.green.length, fb_var_info.green.msb_right); | |
282 printf("fb_init: blue: %d %d %d\n", fb_var_info.blue.offset, | |
283 fb_var_info.blue.length, fb_var_info.blue.msb_right); | |
225 | 284 |
229 | 285 fb_init_done = 1; |
305 | 286 fb_works = 1; |
229 | 287 return 0; |
305 | 288 err_out_fd: |
289 close(fb_dev_fd); | |
290 fb_dev_fd = -1; | |
291 err_out: | |
292 fb_init_done = 1; | |
293 return 1; | |
229 | 294 } |
295 | |
296 static uint32_t init(uint32_t width, uint32_t height, uint32_t d_width, | |
297 uint32_t d_height, uint32_t fullscreen, char *title, | |
298 uint32_t format) | |
299 { | |
300 if (!fb_init_done) | |
301 if (fb_init()) | |
302 return 1; | |
305 | 303 if (!fb_works) |
304 return 1; | |
225 | 305 |
306 in_width = width; | |
307 in_height = height; | |
308 out_width = width; | |
309 out_height = height; | |
310 pixel_format = format; | |
278 | 311 if (!(next_frame = (uint8_t *) malloc(in_width * in_height * fb_pixel_size))) { |
225 | 312 printf("Can't malloc next_frame: %s\n", strerror(errno)); |
313 return 1; | |
314 } | |
315 | |
316 if (format == IMGFMT_YV12) | |
278 | 317 // yuv2rgb_init(fb_pixel_size * 8, MODE_RGB); |
318 yuv2rgb_init((fb_pixel_size == 4) ? 32 : fb_bpp, MODE_RGB); | |
225 | 319 return 0; |
320 } | |
321 | |
322 static uint32_t query_format(uint32_t format) | |
323 { | |
229 | 324 if (!fb_init_done) |
325 if (fb_init()) | |
326 return 0; | |
305 | 327 if (!fb_works) |
328 return 0; | |
329 | |
278 | 330 printf("vo_fbdev: query_format(%#x(%.4s)): ", format, &format); |
230 | 331 // if (format & IMGFMT_BGR_MASK == IMGFMT_BGR) |
332 // goto not_supported; | |
225 | 333 switch (format) { |
334 case IMGFMT_YV12: | |
229 | 335 goto supported; |
277 | 336 /* |
225 | 337 case IMGFMT_RGB32: |
338 if (fb_bpp == 32) | |
229 | 339 goto supported; |
225 | 340 break; |
341 case IMGFMT_RGB24: | |
342 if (fb_bpp == 24) | |
229 | 343 goto supported; |
225 | 344 break; |
345 case IMGFMT_RGB16: | |
346 if (fb_bpp == 16) | |
229 | 347 goto supported; |
225 | 348 break; |
349 case IMGFMT_RGB15: | |
350 if (fb_bpp == 15) | |
229 | 351 goto supported; |
352 break; | |
277 | 353 */ |
229 | 354 case IMGFMT_BGR|32: |
278 | 355 if (fb_bpp == 24 && fb_pixel_size == 4) |
229 | 356 goto supported; |
357 break; | |
358 case IMGFMT_BGR|24: | |
278 | 359 if (fb_bpp == 24 && fb_pixel_size == 3) |
229 | 360 goto supported; |
361 break; | |
362 case IMGFMT_BGR|16: | |
363 if (fb_bpp == 16) | |
364 goto supported; | |
365 break; | |
366 case IMGFMT_BGR|15: | |
367 if (fb_bpp == 15) | |
368 goto supported; | |
225 | 369 break; |
370 } | |
229 | 371 not_supported: |
372 printf("not_supported\n"); | |
225 | 373 return 0; |
229 | 374 supported: |
375 printf("supported\n"); | |
376 return 1; | |
225 | 377 } |
378 | |
379 static const vo_info_t *get_info(void) | |
380 { | |
381 return &vo_info; | |
382 } | |
383 | |
384 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, | |
385 unsigned char *srca, int stride) | |
386 { | |
387 int x, y; | |
388 uint8_t *dst; | |
389 | |
390 if (pixel_format == IMGFMT_YV12) { | |
391 for (y = 0; y < h; y++){ | |
278 | 392 dst = next_frame + (in_width * (y0 + y) + x0) * fb_pixel_size; |
225 | 393 for (x = 0; x < w; x++) { |
394 if (srca[x]) { | |
251 | 395 dst[0]=((dst[0]*srca[x])>>8)+src[x]; |
396 dst[1]=((dst[1]*srca[x])>>8)+src[x]; | |
397 dst[2]=((dst[2]*srca[x])>>8)+src[x]; | |
225 | 398 } |
278 | 399 dst += fb_pixel_size; |
225 | 400 } |
401 src += stride; | |
402 srca += stride; | |
403 } | |
404 } | |
405 } | |
406 | |
407 static uint32_t draw_frame(uint8_t *src[]) | |
408 { | |
409 if (pixel_format == IMGFMT_YV12) { | |
410 yuv2rgb(next_frame, src[0], src[1], src[2], in_width, | |
278 | 411 in_height, in_width * fb_pixel_size, |
225 | 412 in_width, in_width / 2); |
230 | 413 } else if ((pixel_format & IMGFMT_BGR_MASK) == IMGFMT_BGR) { |
278 | 414 memcpy(next_frame, src[0], in_width * in_height * fb_pixel_size); |
230 | 415 } else if ((pixel_format & IMGFMT_RGB_MASK) == IMGFMT_RGB) { |
225 | 416 } |
417 return 0; | |
418 } | |
419 | |
420 static uint32_t draw_slice(uint8_t *src[], int stride[], int w, int h, int x, | |
421 int y) | |
422 { | |
423 uint8_t *dest; | |
424 | |
278 | 425 dest = next_frame + (in_width * y + x) * fb_pixel_size; |
426 yuv2rgb(dest, src[0], src[1], src[2], w, h, in_width * fb_pixel_size, | |
225 | 427 stride[0], stride[1]); |
428 return 0; | |
429 } | |
430 | |
431 static void check_events(void) | |
432 { | |
433 } | |
434 | |
246 | 435 static void put_frame(void) |
225 | 436 { |
437 int i, out_offset = 0, in_offset = 0; | |
438 | |
439 for (i = 0; i < in_height; i++) { | |
440 memcpy(frame_buffer + out_offset, next_frame + in_offset, | |
278 | 441 in_width * fb_pixel_size); |
225 | 442 out_offset += screen_width; |
278 | 443 in_offset += in_width * fb_pixel_size; |
225 | 444 } |
445 } | |
446 | |
246 | 447 static void flip_page(void) |
448 { | |
449 vo_draw_text(in_width, in_height, draw_alpha); | |
450 check_events(); | |
451 put_frame(); | |
452 } | |
453 | |
225 | 454 static void uninit(void) |
455 { | |
246 | 456 printf("vo_fbdev: uninit\n"); |
457 fb_var_info.xres_virtual = fb_xres_virtual; | |
458 fb_var_info.yres_virtual = fb_yres_virtual; | |
305 | 459 if (fb_dev_fd != -1) { |
460 if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_var_info)) | |
461 printf("vo_fbdev: Can't set virtual screensize to original value: %s\n", strerror(errno)); | |
462 close(fb_dev_fd); | |
463 } | |
278 | 464 memset(next_frame, '\0', in_height * in_width * fb_pixel_size); |
246 | 465 put_frame(); |
225 | 466 if (vt_active >= 0) |
467 ioctl(vt_fd, VT_ACTIVATE, vt_active); | |
468 free(next_frame); | |
469 munmap(frame_buffer, fb_size); | |
470 } |