Do _not_ use rbx on x86_64, it will fail to compile with PIC, besides it
[mplayer/glamo.git] / libvo / vo_dfbmga.c
blobfd1a3638db302194953fabf789823b4077a6fd85
1 /*
2 * MPlayer video driver for DirectFB / Matrox G200/G400/G450/G550
4 * copyright (C) 2002-2008 Ville Syrjala <syrjala@sci.fi>
5 * Originally based on vo_directfb.c by Jiri Svoboda <Jiri.Svoboda@seznam.cz>.
7 * This file is part of MPlayer.
9 * MPlayer is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * MPlayer is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with MPlayer; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 /* directfb includes */
25 #include <directfb.h>
27 #define DFB_VERSION(a,b,c) (((a)<<16)|((b)<<8)|(c))
29 /* other things */
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
34 #include "config.h"
35 #include "video_out.h"
36 #include "video_out_internal.h"
37 #include "fastmemcpy.h"
38 #include "sub.h"
39 #include "mp_msg.h"
40 #include "aspect.h"
41 #include "mp_fifo.h"
43 static const vo_info_t info = {
44 "DirectFB / Matrox G200/G400/G450/G550",
45 "dfbmga",
46 "Ville Syrjala <syrjala@sci.fi>",
50 const LIBVO_EXTERN(dfbmga)
52 static IDirectFB *dfb;
54 static IDirectFBDisplayLayer *crtc1;
55 static IDirectFBDisplayLayer *bes;
56 static IDirectFBDisplayLayer *crtc2;
57 static IDirectFBDisplayLayer *spic;
59 static int num_bufs;
60 static int current_buf;
61 static int current_ip_buf;
62 static IDirectFBSurface *bufs[3];
64 static IDirectFBSurface *frame;
65 static IDirectFBSurface *subframe;
67 static IDirectFBSurface *besframe;
68 static IDirectFBSurface *c1frame;
69 static IDirectFBSurface *c2frame;
70 static IDirectFBSurface *spicframe;
72 static DFBSurfacePixelFormat frame_format;
73 static DFBSurfacePixelFormat subframe_format;
75 static DFBRectangle besrect;
76 static DFBRectangle c1rect;
77 static DFBRectangle c2rect;
78 static DFBRectangle *subrect;
80 static IDirectFBInputDevice *keyboard;
81 static IDirectFBInputDevice *remote;
82 static IDirectFBEventBuffer *buffer;
84 static int blit_done;
85 static int c1stretch;
86 static int c2stretch;
88 static int use_bes;
89 static int use_crtc1;
90 static int use_crtc2;
91 static int use_spic;
92 static int use_input;
93 static int use_remote;
94 static int field_parity;
95 static int flipping;
96 static DFBDisplayLayerBufferMode buffermode;
97 static int tvnorm;
99 static int osd_changed;
100 static int osd_dirty;
101 static int osd_current;
102 static int osd_max;
104 static int is_g200;
106 #if DIRECTFBVERSION < DFB_VERSION(0,9,18)
107 #define DSPF_ALUT44 DSPF_LUT8
108 #define DLBM_TRIPLE ~0
109 #define DSFLIP_ONSYNC 0
110 #endif
112 #if DIRECTFBVERSION < DFB_VERSION(0,9,16)
113 #define DSPF_ARGB1555 DSPF_RGB15
114 #endif
116 static uint32_t in_width;
117 static uint32_t in_height;
118 static uint32_t buf_height;
119 static uint32_t screen_width;
120 static uint32_t screen_height;
121 static uint32_t sub_width;
122 static uint32_t sub_height;
124 static char *
125 pixelformat_name( DFBSurfacePixelFormat format )
127 switch(format) {
128 case DSPF_ARGB:
129 return "ARGB";
130 case DSPF_RGB32:
131 return "RGB32";
132 case DSPF_RGB16:
133 return "RGB16";
134 case DSPF_ARGB1555:
135 return "ARGB1555";
136 case DSPF_YUY2:
137 return "YUY2";
138 case DSPF_UYVY:
139 return "UYVY";
140 case DSPF_YV12:
141 return "YV12";
142 case DSPF_I420:
143 return "I420";
144 case DSPF_ALUT44:
145 return "ALUT44";
146 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
147 case DSPF_NV12:
148 return "NV12";
149 case DSPF_NV21:
150 return "NV21";
151 #endif
152 default:
153 return "Unknown pixel format";
157 static DFBSurfacePixelFormat
158 imgfmt_to_pixelformat( uint32_t format )
160 switch (format) {
161 case IMGFMT_BGR32:
162 return DSPF_RGB32;
163 case IMGFMT_BGR16:
164 return DSPF_RGB16;
165 case IMGFMT_BGR15:
166 return DSPF_ARGB1555;
167 case IMGFMT_YUY2:
168 return DSPF_YUY2;
169 case IMGFMT_UYVY:
170 return DSPF_UYVY;
171 case IMGFMT_YV12:
172 return DSPF_YV12;
173 case IMGFMT_I420:
174 case IMGFMT_IYUV:
175 return DSPF_I420;
176 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
177 case IMGFMT_NV12:
178 return DSPF_NV12;
179 case IMGFMT_NV21:
180 return DSPF_NV21;
181 #endif
182 default:
183 return DSPF_UNKNOWN;
187 struct layer_enum
189 const char *name;
190 IDirectFBDisplayLayer **layer;
191 DFBResult res;
194 static DFBEnumerationResult
195 get_layer_by_name( DFBDisplayLayerID id,
196 DFBDisplayLayerDescription desc,
197 void *data )
199 struct layer_enum *l = (struct layer_enum *) data;
201 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
202 /* We have desc.name so use it */
203 if (!strcmp( l->name, desc.name ))
204 if ((l->res = dfb->GetDisplayLayer( dfb, id, l->layer )) == DFB_OK)
205 return DFENUM_CANCEL;
206 #else
207 /* Fake it according to id */
208 if ((id == 0 && !strcmp( l->name, "FBDev Primary Layer" )) ||
209 (id == 1 && !strcmp( l->name, "Matrox Backend Scaler" )) ||
210 (id == 2 && !strcmp( l->name, "Matrox CRTC2" )) ||
211 (id == 3 && !strcmp( l->name, "Matrox CRTC2 Sub-Picture" )))
212 if ((l->res = dfb->GetDisplayLayer( dfb, id, l->layer )) == DFB_OK)
213 return DFENUM_CANCEL;
214 #endif
216 return DFENUM_OK;
219 static int
220 preinit( const char *arg )
222 DFBResult res;
223 int force_input = -1;
225 /* Some defaults */
226 use_bes = 0;
227 use_crtc1 = 0;
228 use_crtc2 = 1;
229 use_spic = 1;
230 field_parity = -1;
231 #if DIRECTFBVERSION > DFB_VERSION(0,9,17)
232 buffermode = DLBM_TRIPLE;
233 osd_max = 4;
234 #else
235 buffermode = DLBM_BACKVIDEO;
236 osd_max = 2;
237 #endif
238 flipping = 1;
239 tvnorm = -1;
241 use_input = !getenv( "DISPLAY" );
243 if (vo_subdevice) {
244 int show_help = 0;
245 int opt_no = 0;
246 while (*vo_subdevice != '\0') {
247 if (!strncmp(vo_subdevice, "bes", 3)) {
248 use_bes = !opt_no;
249 vo_subdevice += 3;
250 opt_no = 0;
251 } else if (!strncmp(vo_subdevice, "crtc1", 5)) {
252 use_crtc1 = !opt_no;
253 vo_subdevice += 5;
254 opt_no = 0;
255 } else if (!strncmp(vo_subdevice, "crtc2", 5)) {
256 use_crtc2 = !opt_no;
257 vo_subdevice += 5;
258 opt_no = 0;
259 } else if (!strncmp(vo_subdevice, "spic", 4)) {
260 use_spic = !opt_no;
261 vo_subdevice += 4;
262 opt_no = 0;
263 } else if (!strncmp(vo_subdevice, "input", 5)) {
264 force_input = !opt_no;
265 vo_subdevice += 5;
266 opt_no = 0;
267 } else if (!strncmp(vo_subdevice, "remote", 6)) {
268 use_remote = !opt_no;
269 vo_subdevice += 6;
270 opt_no = 0;
271 } else if (!strncmp(vo_subdevice, "buffermode=", 11)) {
272 if (opt_no) {
273 show_help = 1;
274 break;
276 vo_subdevice += 11;
277 if (!strncmp(vo_subdevice, "single", 6)) {
278 buffermode = DLBM_FRONTONLY;
279 osd_max = 1;
280 flipping = 0;
281 vo_subdevice += 6;
282 } else if (!strncmp(vo_subdevice, "double", 6)) {
283 buffermode = DLBM_BACKVIDEO;
284 osd_max = 2;
285 flipping = 1;
286 vo_subdevice += 6;
287 } else if (!strncmp(vo_subdevice, "triple", 6)) {
288 buffermode = DLBM_TRIPLE;
289 osd_max = 4;
290 flipping = 1;
291 vo_subdevice += 6;
292 } else {
293 show_help = 1;
294 break;
296 opt_no = 0;
297 } else if (!strncmp(vo_subdevice, "fieldparity=", 12)) {
298 if (opt_no) {
299 show_help = 1;
300 break;
302 vo_subdevice += 12;
303 if (!strncmp(vo_subdevice, "top", 3)) {
304 field_parity = 0;
305 vo_subdevice += 3;
306 } else if (!strncmp(vo_subdevice, "bottom", 6)) {
307 field_parity = 1;
308 vo_subdevice += 6;
309 } else {
310 show_help = 1;
311 break;
313 opt_no = 0;
314 } else if (!strncmp(vo_subdevice, "tvnorm=", 7)) {
315 if (opt_no) {
316 show_help = 1;
317 break;
319 vo_subdevice += 7;
320 if (!strncmp(vo_subdevice, "pal", 3)) {
321 tvnorm = 0;
322 vo_subdevice += 3;
323 } else if (!strncmp(vo_subdevice, "ntsc" , 4)) {
324 tvnorm = 1;
325 vo_subdevice += 4;
326 } else if (!strncmp(vo_subdevice, "auto" , 4)) {
327 tvnorm = 2;
328 vo_subdevice += 4;
329 } else {
330 show_help = 1;
331 break;
333 opt_no = 0;
334 } else if (!strncmp(vo_subdevice, "no", 2)) {
335 if (opt_no) {
336 show_help = 1;
337 break;
339 vo_subdevice += 2;
340 opt_no = 1;
341 } else if (*vo_subdevice == ':') {
342 if (opt_no) {
343 show_help = 1;
344 break;
346 vo_subdevice++;
347 opt_no = 0;
348 } else {
349 show_help = 1;
350 break;
353 if (show_help) {
354 mp_msg( MSGT_VO, MSGL_ERR,
355 "\nvo_dfbmga command line help:\n"
356 "Example: mplayer -vo dfbmga:nocrtc2:bes:buffermode=single\n"
357 "\nOptions (use 'no' prefix to disable):\n"
358 " bes Use Backend Scaler\n"
359 " crtc1 Use CRTC1\n"
360 " crtc2 Use CRTC2\n"
361 " spic Use hardware sub-picture for OSD\n"
362 " input Use DirectFB for keyboard input\n"
363 " remote Use DirectFB for remote control input\n"
364 "\nOther options:\n"
365 " buffermode=(single|double|triple)\n"
366 " single Use single buffering\n"
367 " double Use double buffering\n"
368 " triple Use triple buffering\n"
369 " fieldparity=(top|bottom)\n"
370 " top Top field first\n"
371 " bottom Bottom field first\n"
372 " tvnorm=(pal|ntsc|auto)\n"
373 " pal Force PAL\n"
374 " ntsc Force NTSC\n"
375 " auto Select according to FPS\n"
376 "\n" );
377 return -1;
380 if (!use_bes && !use_crtc1 && !use_crtc2) {
381 mp_msg( MSGT_VO, MSGL_ERR, "vo_dfbmga: No output selected\n" );
382 return -1;
384 if (use_bes && use_crtc1) {
385 mp_msg( MSGT_VO, MSGL_ERR, "vo_dfbmga: Both BES and CRTC1 outputs selected\n" );
386 return -1;
389 if ((res = DirectFBInit( NULL, NULL )) != DFB_OK) {
390 mp_msg( MSGT_VO, MSGL_ERR,
391 "vo_dfbmga: DirectFBInit() failed - %s\n",
392 DirectFBErrorString( res ) );
393 return -1;
396 switch (tvnorm) {
397 case 0:
398 DirectFBSetOption( "matrox-tv-standard", "pal" );
399 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Forced TV standard to PAL\n" );
400 break;
401 case 1:
402 DirectFBSetOption( "matrox-tv-standard", "ntsc" );
403 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Forced TV standard to NTSC\n" );
404 break;
405 case 2:
406 if (vo_fps > 27) {
407 DirectFBSetOption( "matrox-tv-standard", "ntsc" );
408 mp_msg( MSGT_VO, MSGL_INFO,
409 "vo_dfbmga: Selected TV standard based upon FPS: NTSC\n" );
410 } else {
411 DirectFBSetOption( "matrox-tv-standard", "pal" );
412 mp_msg( MSGT_VO, MSGL_INFO,
413 "vo_dfbmga: Selected TV standard based upon FPS: PAL\n" );
415 break;
418 if ((res = DirectFBCreate( &dfb )) != DFB_OK) {
419 mp_msg( MSGT_VO, MSGL_ERR,
420 "vo_dfbmga: DirectFBCreate() failed - %s\n",
421 DirectFBErrorString( res ) );
422 return -1;
425 if (use_crtc1 || use_bes) {
426 struct layer_enum l = {
427 "FBDev Primary Layer",
428 &crtc1,
429 DFB_UNSUPPORTED
431 dfb->EnumDisplayLayers( dfb, get_layer_by_name, &l );
432 if (l.res != DFB_OK) {
433 mp_msg( MSGT_VO, MSGL_ERR, "vo_dfbmga: Can't get CRTC1 layer - %s\n",
434 DirectFBErrorString( l.res ) );
435 uninit();
436 return -1;
438 if ((res = crtc1->SetCooperativeLevel( crtc1, DLSCL_EXCLUSIVE )) != DFB_OK) {
439 mp_msg( MSGT_VO, MSGL_ERR, "Can't get exclusive access to CRTC1 layer - %s\n",
440 DirectFBErrorString( res ) );
441 uninit();
442 return -1;
444 use_input = 1;
447 if (force_input != -1)
448 use_input = force_input;
450 if (use_bes) {
451 DFBDisplayLayerConfig dlc;
452 DFBDisplayLayerConfigFlags failed;
453 struct layer_enum l = {
454 "Matrox Backend Scaler",
455 &bes,
456 DFB_UNSUPPORTED
459 dfb->EnumDisplayLayers( dfb, get_layer_by_name, &l );
460 if (l.res != DFB_OK) {
461 mp_msg( MSGT_VO, MSGL_ERR, "Can't get BES layer - %s\n",
462 DirectFBErrorString( l.res ) );
463 uninit();
464 return -1;
466 if ((res = bes->SetCooperativeLevel( bes, DLSCL_EXCLUSIVE )) != DFB_OK) {
467 mp_msg( MSGT_VO, MSGL_ERR, "Can't get exclusive access to BES - %s\n",
468 DirectFBErrorString( res ) );
469 uninit();
470 return -1;
472 dlc.flags = DLCONF_PIXELFORMAT;
473 dlc.pixelformat = DSPF_RGB16;
474 if (bes->TestConfiguration( bes, &dlc, &failed ) != DFB_OK) {
475 is_g200 = 1;
476 use_crtc2 = 0;
480 if (use_crtc2) {
481 struct layer_enum l = {
482 #if DIRECTFBVERSION > DFB_VERSION(0,9,20)
483 "Matrox CRTC2 Layer",
484 #else
485 "Matrox CRTC2",
486 #endif
487 &crtc2,
488 DFB_UNSUPPORTED
491 dfb->EnumDisplayLayers( dfb, get_layer_by_name, &l );
492 if (l.res != DFB_OK) {
493 mp_msg( MSGT_VO, MSGL_ERR, "Can't get CRTC2 layer - %s\n",
494 DirectFBErrorString( l.res ) );
495 uninit();
496 return -1;
498 if ((res = crtc2->SetCooperativeLevel( crtc2, DLSCL_EXCLUSIVE )) != DFB_OK) {
499 mp_msg( MSGT_VO, MSGL_ERR, "Can't get exclusive access to CRTC2 - %s\n",
500 DirectFBErrorString( res ) );
501 uninit();
502 return -1;
506 if (use_input || use_remote) {
507 if ((res = dfb->CreateEventBuffer( dfb, &buffer )) != DFB_OK) {
508 mp_msg( MSGT_VO, MSGL_ERR,
509 "vo_dfbmga: Can't create event buffer - %s\n",
510 DirectFBErrorString( res ) );
511 uninit();
512 return -1;
516 if (use_input) {
517 if ((res = dfb->GetInputDevice( dfb, DIDID_KEYBOARD, &keyboard )) != DFB_OK) {
518 mp_msg( MSGT_VO, MSGL_ERR,
519 "vo_dfbmga: Can't get keyboard - %s\n",
520 DirectFBErrorString( res ) );
521 uninit();
522 return -1;
524 if ((res = keyboard->AttachEventBuffer( keyboard, buffer )) != DFB_OK) {
525 mp_msg( MSGT_VO, MSGL_ERR,
526 "vo_dfbmga: Can't attach event buffer to keyboard - %s\n",
527 DirectFBErrorString( res ) );
528 uninit();
529 return -1;
532 if (use_remote) {
533 if ((res = dfb->GetInputDevice( dfb, DIDID_REMOTE, &remote )) != DFB_OK) {
534 mp_msg( MSGT_VO, MSGL_ERR,
535 "vo_dfbmga: Can't get remote control - %s\n",
536 DirectFBErrorString( res ) );
537 uninit();
538 return -1;
540 if ((res = remote->AttachEventBuffer( remote, buffer )) != DFB_OK) {
541 mp_msg( MSGT_VO, MSGL_ERR,
542 "vo_dfbmga: Can't attach event buffer to remote control - %s\n",
543 DirectFBErrorString( res ) );
544 uninit();
545 return -1;
549 return 0;
552 static void release_config( void )
554 if (spicframe)
555 spicframe->Release( spicframe );
556 if (spic)
557 spic->Release( spic );
558 if (c2frame)
559 c2frame->Release( c2frame );
560 if (c1frame)
561 c1frame->Release( c1frame );
562 if (besframe)
563 besframe->Release( besframe );
564 if (bufs[0])
565 bufs[0]->Release( bufs[0] );
566 if (bufs[1])
567 bufs[1]->Release( bufs[1] );
568 if (bufs[2])
569 bufs[2]->Release( bufs[2] );
571 spicframe = NULL;
572 spic = NULL;
573 c2frame = NULL;
574 c1frame = NULL;
575 besframe = NULL;
576 bufs[0] = NULL;
577 bufs[1] = NULL;
578 bufs[2] = NULL;
581 static int
582 config( uint32_t width, uint32_t height,
583 uint32_t d_width, uint32_t d_height,
584 uint32_t flags,
585 char *title,
586 uint32_t format )
588 DFBResult res;
590 DFBDisplayLayerConfig dlc;
591 DFBDisplayLayerConfigFlags failed;
593 uint32_t out_width;
594 uint32_t out_height;
596 release_config();
598 in_width = width;
599 in_height = height;
601 aspect_save_orig(width, height);
602 aspect_save_prescale(d_width, d_height);
604 dlc.pixelformat = imgfmt_to_pixelformat( format );
607 /* Draw to a temporary surface */
608 DFBSurfaceDescription dsc;
610 dsc.flags = DSDESC_WIDTH | DSDESC_HEIGHT |
611 DSDESC_PIXELFORMAT;
612 dsc.width = (in_width + 15) & ~15;
613 dsc.height = (in_height + 15) & ~15;
614 dsc.pixelformat = dlc.pixelformat;
616 /* Don't waste video memory since we don't need direct stretchblit */
617 if (use_bes) {
618 dsc.flags |= DSDESC_CAPS;
619 dsc.caps = DSCAPS_SYSTEMONLY;
622 for (num_bufs = 0; num_bufs < 3; num_bufs++) {
623 if ((res = dfb->CreateSurface( dfb, &dsc, &bufs[num_bufs] )) != DFB_OK) {
624 if (num_bufs == 0) {
625 mp_msg( MSGT_VO, MSGL_ERR,
626 "vo_dfbmga: Can't create surfaces - %s!\n",
627 DirectFBErrorString( res ) );
628 return -1;
630 break;
633 frame = bufs[0];
634 current_buf = 0;
635 current_ip_buf = 0;
636 buf_height = dsc.height;
638 frame->GetPixelFormat( frame, &frame_format );
639 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Video surface %dx%d %s\n",
640 in_width, in_height,
641 pixelformat_name( frame_format ) );
645 * BES
647 if (use_bes) {
648 aspect_save_screenres( 0x10000, 0x10000 );
649 aspect( &out_width, &out_height, A_ZOOM );
650 besrect.x = (0x10000 - out_width) * in_width / out_width / 2;
651 besrect.y = (0x10000 - out_height) * in_height / out_height / 2;
652 besrect.w = in_width;
653 besrect.h = in_height;
655 dlc.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;
656 dlc.width = besrect.w + besrect.x * 2;
657 dlc.height = besrect.h + besrect.y * 2;
658 dlc.buffermode = buffermode;
660 if ((res = bes->TestConfiguration( bes, &dlc, &failed )) != DFB_OK) {
661 mp_msg( MSGT_VO, MSGL_ERR,
662 "vo_dfbmga: Invalid BES configuration - %s!\n",
663 DirectFBErrorString( res ) );
664 return -1;
666 if ((res = bes->SetConfiguration( bes, &dlc )) != DFB_OK) {
667 mp_msg( MSGT_VO, MSGL_ERR,
668 "vo_dfbmga: BES configuration failed - %s!\n",
669 DirectFBErrorString( res ) );
670 return -1;
672 bes->GetSurface( bes, &besframe );
673 besframe->SetBlittingFlags( besframe, DSBLIT_NOFX );
675 bes->SetScreenLocation( bes, 0.0, 0.0, 1.0, 1.0 );
677 besframe->Clear( besframe, 0, 0, 0, 0xff );
678 besframe->Flip( besframe, NULL, 0 );
679 besframe->Clear( besframe, 0, 0, 0, 0xff );
680 besframe->Flip( besframe, NULL, 0 );
681 besframe->Clear( besframe, 0, 0, 0, 0xff );
683 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: BES using %s buffering\n",
684 dlc.buffermode == DLBM_TRIPLE ? "triple" :
685 dlc.buffermode == DLBM_BACKVIDEO ? "double" : "single" );
686 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: BES surface %dx%d %s\n", dlc.width, dlc.height, pixelformat_name( dlc.pixelformat ) );
690 * CRTC1
692 if (use_crtc1) {
693 dlc.flags = DLCONF_BUFFERMODE;
694 dlc.buffermode = buffermode;
696 if ((res = crtc1->TestConfiguration( crtc1, &dlc, &failed )) != DFB_OK) {
697 mp_msg( MSGT_VO, MSGL_ERR,
698 "vo_dfbmga: Invalid CRTC1 configuration - %s!\n",
699 DirectFBErrorString( res ) );
700 return -1;
702 if ((res = crtc1->SetConfiguration( crtc1, &dlc )) != DFB_OK) {
703 mp_msg( MSGT_VO, MSGL_ERR,
704 "vo_dfbmga: CRTC1 configuration failed - %s!\n",
705 DirectFBErrorString( res ) );
706 return -1;
708 if ((res = crtc1->GetConfiguration( crtc1, &dlc )) != DFB_OK) {
709 mp_msg( MSGT_VO, MSGL_ERR,
710 "vo_dfbmga: Getting CRTC1 configuration failed - %s!\n",
711 DirectFBErrorString( res ) );
712 return -1;
715 crtc1->GetSurface( crtc1, &c1frame );
716 c1frame->SetBlittingFlags( c1frame, DSBLIT_NOFX );
717 c1frame->SetColor( c1frame, 0, 0, 0, 0xff );
719 c1frame->GetSize( c1frame, &screen_width, &screen_height );
721 aspect_save_screenres( screen_width, screen_height );
722 aspect( &out_width, &out_height, (flags & VOFLAG_FULLSCREEN) ? A_ZOOM : A_NOZOOM );
724 if (in_width != out_width || in_height != out_height)
725 c1stretch = 1;
726 else
727 c1stretch = 0;
729 c1rect.x = (screen_width - out_width) / 2;
730 c1rect.y = (screen_height - out_height) / 2;
731 c1rect.w = out_width;
732 c1rect.h = out_height;
734 c1frame->Clear( c1frame, 0, 0, 0, 0xff );
735 c1frame->Flip( c1frame, NULL, 0 );
736 c1frame->Clear( c1frame, 0, 0, 0, 0xff );
737 c1frame->Flip( c1frame, NULL, 0 );
738 c1frame->Clear( c1frame, 0, 0, 0, 0xff );
740 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: CRTC1 using %s buffering\n",
741 dlc.buffermode == DLBM_TRIPLE ? "triple" :
742 dlc.buffermode == DLBM_BACKVIDEO ? "double" : "single" );
743 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: CRTC1 surface %dx%d %s\n", screen_width, screen_height, pixelformat_name( dlc.pixelformat ) );
747 * CRTC2
749 if (use_crtc2) {
750 dlc.flags = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | DLCONF_OPTIONS;
751 dlc.buffermode = buffermode;
752 dlc.options = DLOP_NONE;
754 #if DIRECTFBVERSION > DFB_VERSION(0,9,16)
755 if (field_parity != -1) {
756 dlc.options |= DLOP_FIELD_PARITY;
758 #endif
759 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Field parity set to: ");
760 switch (field_parity) {
761 case -1:
762 mp_msg( MSGT_VO, MSGL_INFO, "Don't care\n");
763 break;
764 case 0:
765 mp_msg( MSGT_VO, MSGL_INFO, "Top field first\n");
766 break;
767 case 1:
768 mp_msg( MSGT_VO, MSGL_INFO, "Bottom field first\n");
769 break;
772 switch (dlc.pixelformat) {
773 case DSPF_I420:
774 case DSPF_YV12:
775 /* sub-picture supported */
776 break;
778 case DSPF_YUY2:
779 case DSPF_UYVY:
780 /* Blit to YUY2/UYVY not supported */
781 dlc.pixelformat = DSPF_ARGB;
783 /* fall through */
784 default:
785 /* sub-picture not supported */
786 use_spic = 0;
789 if ((res = crtc2->TestConfiguration( crtc2, &dlc, &failed )) != DFB_OK) {
790 mp_msg( MSGT_VO, MSGL_ERR,
791 "vo_dfbmga: Invalid CRTC2 configuration - %s!\n",
792 DirectFBErrorString( res ) );
793 return -1;
795 if ((res = crtc2->SetConfiguration( crtc2, &dlc )) != DFB_OK) {
796 mp_msg( MSGT_VO, MSGL_ERR,
797 "vo_dfbmga: CRTC2 configuration failed - %s!\n",
798 DirectFBErrorString( res ) );
799 return -1;
802 #if DIRECTFBVERSION > DFB_VERSION(0,9,16)
803 if (field_parity != -1)
804 crtc2->SetFieldParity( crtc2, field_parity );
805 #endif
807 crtc2->GetSurface( crtc2, &c2frame );
808 c2frame->SetBlittingFlags( c2frame, DSBLIT_NOFX );
809 c2frame->SetColor( c2frame, 0, 0, 0, 0xff );
811 c2frame->GetSize( c2frame, &screen_width, &screen_height );
813 /* Don't stretch only slightly smaller videos */
814 if ((in_width > (0.95 * screen_width)) &&
815 (in_width < screen_width))
816 out_width = in_width;
817 else
818 out_width = screen_width;
819 if ((in_height > (0.95 * screen_height)) &&
820 (in_height < screen_height))
821 out_height = in_height;
822 else
823 out_height = screen_height;
825 aspect_save_screenres( out_width, out_height );
826 aspect( &out_width, &out_height, (flags & VOFLAG_FULLSCREEN) ? A_ZOOM : A_NOZOOM );
828 if (in_width != out_width ||
829 in_height != out_height)
830 c2stretch = 1;
831 else
832 c2stretch = 0;
834 c2rect.x = (screen_width - out_width) / 2;
835 c2rect.y = (screen_height - out_height) / 2;
836 c2rect.w = out_width;
837 c2rect.h = out_height;
839 c2frame->Clear( c2frame, 0, 0, 0, 0xff );
840 c2frame->Flip( c2frame, NULL, 0 );
841 c2frame->Clear( c2frame, 0, 0, 0, 0xff );
842 c2frame->Flip( c2frame, NULL, 0 );
843 c2frame->Clear( c2frame, 0, 0, 0, 0xff );
845 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: CRTC2 using %s buffering\n",
846 dlc.buffermode == DLBM_TRIPLE ? "triple" :
847 dlc.buffermode == DLBM_BACKVIDEO ? "double" : "single" );
848 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: CRTC2 surface %dx%d %s\n", screen_width, screen_height, pixelformat_name( dlc.pixelformat ) );
849 } else {
850 use_spic = 0;
854 * Sub-picture
856 if (use_spic) {
857 /* Draw OSD to sub-picture surface */
858 IDirectFBPalette *palette;
859 DFBColor color;
860 int i;
861 struct layer_enum l = {
862 "Matrox CRTC2 Sub-Picture",
863 &spic,
864 DFB_UNSUPPORTED
866 dfb->EnumDisplayLayers( dfb, get_layer_by_name, &l );
867 if (l.res != DFB_OK) {
868 mp_msg( MSGT_VO, MSGL_ERR, "vo_dfbmga: Can't get sub-picture layer - %s\n",
869 DirectFBErrorString( l.res ) );
870 return -1;
872 if ((res = spic->SetCooperativeLevel( spic, DLSCL_EXCLUSIVE )) != DFB_OK) {
873 mp_msg( MSGT_VO, MSGL_ERR, "Can't get exclusive access to sub-picture - %s\n",
874 DirectFBErrorString( res ) );
875 return -1;
878 dlc.flags = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;
879 dlc.pixelformat = DSPF_ALUT44;
880 dlc.buffermode = buffermode;
882 #if DIRECTFBVERSION > DFB_VERSION(0,9,16)
883 dlc.flags |= DLCONF_OPTIONS;
884 dlc.options = DLOP_ALPHACHANNEL;
885 #endif
886 if ((res = spic->TestConfiguration( spic, &dlc, &failed )) != DFB_OK) {
887 mp_msg( MSGT_VO, MSGL_ERR,
888 "vo_dfbmga: Invalid sub-picture configuration - %s!\n",
889 DirectFBErrorString( res ) );
890 return -1;
892 if ((res = spic->SetConfiguration( spic, &dlc )) != DFB_OK) {
893 mp_msg( MSGT_VO, MSGL_ERR,
894 "vo_dfbmga: Sub-picture configuration failed - %s!\n",
895 DirectFBErrorString( res ) );
896 return -1;
899 spic->GetSurface( spic, &spicframe );
901 spicframe->GetPalette( spicframe, &palette );
902 color.a = 0xff;
903 for (i = 0; i < 16; i++) {
904 color.r = i * 17;
905 color.g = i * 17;
906 color.b = i * 17;
907 palette->SetEntries( palette, &color, 1, i );
909 palette->Release( palette );
911 spicframe->Clear( spicframe, 0, 0, 0, 0 );
912 spicframe->Flip( spicframe, NULL, 0 );
913 spicframe->Clear( spicframe, 0, 0, 0, 0 );
914 spicframe->Flip( spicframe, NULL, 0 );
915 spicframe->Clear( spicframe, 0, 0, 0, 0 );
917 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Sub-picture layer using %s buffering\n",
918 dlc.buffermode == DLBM_TRIPLE ? "triple" :
919 dlc.buffermode == DLBM_BACKVIDEO ? "double" : "single" );
921 subframe = spicframe;
922 subrect = NULL;
923 } else if (use_crtc2) {
924 /* Draw OSD to CRTC2 surface */
925 subframe = c2frame;
926 subrect = &c2rect;
927 } else if (use_crtc1) {
928 /* Draw OSD to CRTC1 surface */
929 subframe = c1frame;
930 subrect = &c1rect;
931 } else {
932 /* Draw OSD to BES surface */
933 subframe = besframe;
934 subrect = &besrect;
937 subframe->GetSize( subframe, &sub_width, &sub_height );
938 subframe->GetPixelFormat( subframe, &subframe_format );
939 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Sub-picture surface %dx%d %s (%s)\n",
940 sub_width, sub_height,
941 pixelformat_name( subframe_format ),
942 use_crtc2 ? (use_spic ? "Sub-picture layer" : "CRTC2") :
943 use_crtc1 ? "CRTC1" : "BES" );
945 osd_dirty = 0;
946 osd_current = 1;
947 blit_done = 0;
949 return 0;
952 static int
953 query_format( uint32_t format )
955 switch (format) {
956 case IMGFMT_YV12:
957 case IMGFMT_I420:
958 case IMGFMT_IYUV:
959 if (is_g200 || use_crtc1)
960 return 0;
961 break;
962 case IMGFMT_BGR32:
963 case IMGFMT_BGR16:
964 case IMGFMT_BGR15:
965 if (is_g200 && use_bes)
966 return 0;
967 break;
968 case IMGFMT_UYVY:
969 if (is_g200)
970 return 0;
971 break;
972 case IMGFMT_YUY2:
973 break;
974 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
975 case IMGFMT_NV12:
976 case IMGFMT_NV21:
977 if (use_crtc1 || use_crtc2)
978 return 0;
979 break;
980 #endif
981 default:
982 return 0;
985 return VFCAP_HWSCALE_UP |
986 VFCAP_HWSCALE_DOWN |
987 VFCAP_CSP_SUPPORTED_BY_HW |
988 VFCAP_CSP_SUPPORTED |
989 VFCAP_OSD;
992 static void
993 vo_draw_alpha_alut44( int w, int h,
994 unsigned char* src,
995 unsigned char *srca,
996 int srcstride,
997 unsigned char* dst,
998 int dststride )
1000 int x;
1002 while (h--) {
1003 for (x = 0; x < w; x++) {
1004 if (srca[x])
1005 dst[x] = ((255 - srca[x]) & 0xF0) | (src[x] >> 4);
1007 src += srcstride;
1008 srca += srcstride;
1009 dst += dststride;
1013 static void
1014 clear_alpha( int x0, int y0,
1015 int w, int h )
1017 if (use_spic && !flipping && vo_osd_changed_flag)
1018 subframe->FillRectangle( subframe, x0, y0, w, h );
1021 static void
1022 draw_alpha( int x0, int y0,
1023 int w, int h,
1024 unsigned char *src,
1025 unsigned char *srca,
1026 int stride )
1028 uint8_t *dst;
1029 void *ptr;
1030 int pitch;
1032 if (use_spic) {
1033 if (!osd_changed || (!flipping && !vo_osd_changed_flag))
1034 return;
1035 osd_dirty |= osd_current;
1036 } else {
1037 if (x0 < subrect->x ||
1038 y0 < subrect->y ||
1039 x0 + w > subrect->x + subrect->w ||
1040 y0 + h > subrect->y + subrect->h)
1041 osd_dirty |= osd_current;
1044 if (subframe->Lock( subframe, DSLF_READ | DSLF_WRITE, &ptr, &pitch ) != DFB_OK)
1045 return;
1046 dst = ptr;
1048 switch (subframe_format) {
1049 case DSPF_ALUT44:
1050 vo_draw_alpha_alut44( w, h, src, srca, stride,
1051 dst + pitch * y0 + x0,
1052 pitch );
1053 break;
1054 case DSPF_RGB32:
1055 case DSPF_ARGB:
1056 vo_draw_alpha_rgb32( w, h, src, srca, stride,
1057 dst + pitch * y0 + 4 * x0,
1058 pitch );
1059 break;
1060 case DSPF_RGB16:
1061 vo_draw_alpha_rgb16( w, h, src, srca, stride,
1062 dst + pitch * y0 + 2 * x0,
1063 pitch );
1064 break;
1065 case DSPF_ARGB1555:
1066 vo_draw_alpha_rgb15( w, h, src, srca, stride,
1067 dst + pitch * y0 + 2 * x0,
1068 pitch );
1069 break;
1070 case DSPF_YUY2:
1071 vo_draw_alpha_yuy2( w, h, src, srca, stride,
1072 dst + pitch * y0 + 2 * x0,
1073 pitch );
1074 break;
1075 case DSPF_UYVY:
1076 vo_draw_alpha_yuy2( w, h, src, srca, stride,
1077 dst + pitch * y0 + 2 * x0 + 1,
1078 pitch );
1079 break;
1080 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
1081 case DSPF_NV12:
1082 case DSPF_NV21:
1083 #endif
1084 case DSPF_I420:
1085 case DSPF_YV12:
1086 vo_draw_alpha_yv12( w, h, src, srca, stride,
1087 dst + pitch * y0 + x0,
1088 pitch );
1089 break;
1092 subframe->Unlock( subframe );
1095 static int
1096 draw_frame( uint8_t * src[] )
1098 return -1;
1101 static int
1102 draw_slice( uint8_t * src[], int stride[], int w, int h, int x, int y )
1104 uint8_t *dst;
1105 void *ptr;
1106 int pitch;
1108 if (frame->Lock( frame, DSLF_WRITE, &ptr, &pitch ) != DFB_OK)
1109 return VO_FALSE;
1110 dst = ptr;
1112 memcpy_pic( dst + pitch * y + x, src[0],
1113 w, h, pitch, stride[0] );
1115 dst += pitch * buf_height;
1117 y /= 2;
1118 h /= 2;
1120 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
1121 if (frame_format == DSPF_NV12 || frame_format == DSPF_NV21) {
1122 memcpy_pic( dst + pitch * y + x, src[1],
1123 w, h, pitch, stride[1] );
1124 } else
1125 #endif
1127 x /= 2;
1128 w /= 2;
1129 pitch /= 2;
1131 if (frame_format == DSPF_I420 )
1132 memcpy_pic( dst + pitch * y + x, src[1],
1133 w, h, pitch, stride[1] );
1134 else
1135 memcpy_pic( dst + pitch * y + x, src[2],
1136 w, h, pitch, stride[2] );
1138 dst += pitch * buf_height / 2;
1140 if (frame_format == DSPF_I420 )
1141 memcpy_pic( dst + pitch * y + x, src[2],
1142 w, h, pitch, stride[2] );
1143 else
1144 memcpy_pic( dst + pitch * y + x, src[1],
1145 w, h, pitch, stride[1] );
1148 frame->Unlock( frame );
1150 return VO_TRUE;
1153 static void
1154 blit_to_screen( void )
1156 IDirectFBSurface *blitsrc = frame;
1157 DFBRectangle *srect = NULL;
1159 if (use_bes) {
1160 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
1161 if (vo_vsync && !flipping)
1162 bes->WaitForSync( bes );
1163 #endif
1165 besframe->Blit( besframe, blitsrc, NULL, besrect.x, besrect.y );
1166 blitsrc = besframe;
1167 srect = &besrect;
1170 if (use_crtc1) {
1171 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
1172 if (vo_vsync && !flipping)
1173 crtc1->WaitForSync( crtc1 );
1174 #endif
1176 if (c1stretch)
1177 c1frame->StretchBlit( c1frame, blitsrc, srect, &c1rect );
1178 else
1179 c1frame->Blit( c1frame, blitsrc, srect, c1rect.x, c1rect.y );
1182 if (use_crtc2) {
1183 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
1184 if (vo_vsync && !flipping)
1185 crtc2->WaitForSync( crtc2 );
1186 #endif
1188 if (c2stretch)
1189 c2frame->StretchBlit( c2frame, blitsrc, srect, &c2rect );
1190 else
1191 c2frame->Blit( c2frame, blitsrc, srect, c2rect.x, c2rect.y );
1195 static void
1196 draw_osd( void )
1198 frame = bufs[current_buf];
1199 frame->Unlock( frame );
1201 osd_changed = vo_osd_changed( 0 );
1202 if (osd_dirty & osd_current) {
1203 if (use_spic) {
1204 if (flipping)
1205 subframe->Clear( subframe, 0, 0, 0, 0 );
1206 } else {
1207 /* Clear black bars around the picture */
1208 subframe->FillRectangle( subframe,
1209 0, 0,
1210 sub_width, subrect->y );
1211 subframe->FillRectangle( subframe,
1212 0, subrect->y + subrect->h,
1213 sub_width, subrect->y );
1214 subframe->FillRectangle( subframe,
1215 0, subrect->y,
1216 subrect->x, subrect->h );
1217 subframe->FillRectangle( subframe,
1218 subrect->x + subrect->w, subrect->y,
1219 subrect->x, subrect->h );
1221 osd_dirty &= ~osd_current;
1224 blit_to_screen();
1225 blit_done = 1;
1227 vo_remove_text( sub_width, sub_height, clear_alpha );
1228 vo_draw_text( sub_width, sub_height, draw_alpha );
1230 if (use_spic && flipping && osd_changed) {
1231 subframe->Flip( subframe, NULL, 0 );
1232 osd_current <<= 1;
1233 if (osd_current > osd_max)
1234 osd_current = 1;
1238 static void
1239 flip_page( void )
1241 if (!blit_done)
1242 blit_to_screen();
1244 if (flipping) {
1245 if (use_crtc2)
1246 c2frame->Flip( c2frame, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : DSFLIP_ONSYNC );
1247 if (use_crtc1)
1248 c1frame->Flip( c1frame, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : DSFLIP_ONSYNC );
1249 if (use_bes)
1250 besframe->Flip( besframe, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : DSFLIP_ONSYNC );
1252 if (!use_spic) {
1253 osd_current <<= 1;
1254 if (osd_current > osd_max)
1255 osd_current = 1;
1259 blit_done = 0;
1260 current_buf = 0;
1263 static void
1264 uninit( void )
1266 release_config();
1268 if (buffer)
1269 buffer->Release( buffer );
1270 if (remote)
1271 remote->Release( remote );
1272 if (keyboard)
1273 keyboard->Release( keyboard );
1274 if (crtc2)
1275 crtc2->Release( crtc2 );
1276 if (bes)
1277 bes->Release( bes );
1278 if (crtc1)
1279 crtc1->Release( crtc1 );
1280 if (dfb)
1281 dfb->Release( dfb );
1283 buffer = NULL;
1284 remote = NULL;
1285 keyboard = NULL;
1286 crtc2 = NULL;
1287 bes = NULL;
1288 crtc1 = NULL;
1289 dfb = NULL;
1292 static uint32_t
1293 get_image( mp_image_t *mpi )
1295 int buf = current_buf;
1296 uint8_t *dst;
1297 void *ptr;
1298 int pitch;
1300 if (mpi->flags & MP_IMGFLAG_READABLE &&
1301 (mpi->type == MP_IMGTYPE_IPB || mpi->type == MP_IMGTYPE_IP)) {
1302 if (num_bufs < 2)
1303 return VO_FALSE;
1305 current_ip_buf ^= 1;
1307 if (mpi->type == MP_IMGTYPE_IPB && num_bufs < 3 && current_ip_buf)
1308 return VO_FALSE;
1310 buf = current_ip_buf;
1312 if (mpi->type == MP_IMGTYPE_IPB)
1313 buf++;
1315 frame = bufs[buf];
1316 frame->Unlock( frame );
1318 /* Always use DSLF_READ to preserve system memory copy */
1319 if (frame->Lock( frame, DSLF_WRITE | DSLF_READ,
1320 &ptr, &pitch ) != DFB_OK)
1321 return VO_FALSE;
1322 dst = ptr;
1324 if ((mpi->width == pitch) ||
1325 (mpi->flags & (MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_ACCEPT_WIDTH))) {
1327 mpi->planes[0] = dst;
1328 mpi->width = in_width;
1329 mpi->stride[0] = pitch;
1331 if (mpi->flags & MP_IMGFLAG_PLANAR) {
1332 if (mpi->num_planes > 2) {
1333 mpi->stride[1] = mpi->stride[2] = pitch / 2;
1335 if (mpi->flags & MP_IMGFLAG_SWAPPED) {
1336 /* I420 */
1337 mpi->planes[1] = dst + buf_height * pitch;
1338 mpi->planes[2] = mpi->planes[1] + buf_height * pitch / 4;
1339 } else {
1340 /* YV12 */
1341 mpi->planes[2] = dst + buf_height * pitch;
1342 mpi->planes[1] = mpi->planes[2] + buf_height * pitch / 4;
1344 } else {
1345 /* NV12/NV21 */
1346 mpi->stride[1] = pitch;
1347 mpi->planes[1] = dst + buf_height * pitch;
1351 mpi->flags |= MP_IMGFLAG_DIRECT;
1352 mpi->priv = (void *) buf;
1353 current_buf = buf;
1355 return VO_TRUE;
1358 frame->Unlock( frame );
1360 return VO_FALSE;
1365 static uint32_t
1366 draw_image( mp_image_t *mpi )
1368 if (mpi->flags & MP_IMGFLAG_DIRECT) {
1369 current_buf = (int) mpi->priv;
1370 return VO_TRUE;
1372 if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
1373 return VO_TRUE;
1375 if (mpi->flags & MP_IMGFLAG_PLANAR)
1376 return draw_slice( mpi->planes, mpi->stride,
1377 mpi->w, mpi->h, 0, 0 );
1378 else {
1379 void *dst;
1380 int pitch;
1382 if (frame->Lock( frame, DSLF_WRITE, &dst, &pitch ) != DFB_OK)
1383 return VO_FALSE;
1384 memcpy_pic( dst, mpi->planes[0],
1385 mpi->w * (mpi->bpp / 8), mpi->h,
1386 pitch, mpi->stride[0] );
1387 frame->Unlock( frame );
1389 return VO_TRUE;
1393 static int
1394 set_equalizer( char *data, int value )
1396 DFBResult res;
1397 DFBColorAdjustment ca;
1398 float factor = (float) 0xffff / 200.0;
1400 ca.flags = DCAF_NONE;
1402 if (!strcasecmp( data, "brightness" )) {
1403 ca.flags |= DCAF_BRIGHTNESS;
1404 ca.brightness = value * factor + 0x8000;
1406 if (!strcasecmp( data, "contrast" )) {
1407 ca.flags |= DCAF_CONTRAST;
1408 ca.contrast = value * factor + 0x8000;
1410 if (!strcasecmp( data, "hue" )) {
1411 ca.flags |= DCAF_HUE;
1412 ca.hue = value * factor + 0x8000;
1414 if (!strcasecmp( data, "saturation" )) {
1415 ca.flags |= DCAF_SATURATION;
1416 ca.saturation = value * factor + 0x8000;
1419 /* Prefer CRTC2 over BES */
1420 if (use_crtc2)
1421 res = crtc2->SetColorAdjustment( crtc2, &ca );
1422 else if (use_crtc1)
1423 res = crtc1->SetColorAdjustment( crtc1, &ca );
1424 else
1425 res = bes->SetColorAdjustment( bes, &ca );
1427 if (res != DFB_OK)
1428 return VO_FALSE;
1430 return VO_TRUE;
1433 static int
1434 get_equalizer( char *data, int *value )
1436 DFBResult res;
1437 DFBColorAdjustment ca;
1438 float factor = 200.0 / (float) 0xffff;
1440 /* Prefer CRTC2 over BES */
1441 if (use_crtc2)
1442 res = crtc2->GetColorAdjustment( crtc2, &ca );
1443 else if (use_crtc1)
1444 res = crtc1->GetColorAdjustment( crtc1, &ca );
1445 else
1446 res = bes->GetColorAdjustment( bes, &ca );
1448 if (res != DFB_OK)
1449 return VO_FALSE;
1451 if (!strcasecmp( data, "brightness" ) &&
1452 (ca.flags & DCAF_BRIGHTNESS))
1453 *value = (ca.brightness - 0x8000) * factor;
1454 if (!strcasecmp( data, "contrast" ) &&
1455 (ca.flags & DCAF_CONTRAST))
1456 *value = (ca.contrast - 0x8000) * factor;
1457 if (!strcasecmp( data, "hue" ) &&
1458 (ca.flags & DCAF_HUE))
1459 *value = (ca.hue - 0x8000) * factor;
1460 if (!strcasecmp( data, "saturation" ) &&
1461 (ca.flags & DCAF_SATURATION))
1462 *value = (ca.saturation - 0x8000) * factor;
1464 return VO_TRUE;
1467 static int
1468 control( uint32_t request, void *data, ... )
1470 switch (request) {
1471 case VOCTRL_GUISUPPORT:
1472 case VOCTRL_GUI_NOWINDOW:
1473 return VO_TRUE;
1475 case VOCTRL_QUERY_FORMAT:
1476 return query_format( *((uint32_t *) data) );
1478 case VOCTRL_GET_IMAGE:
1479 return get_image( data );
1481 case VOCTRL_DRAW_IMAGE:
1482 return draw_image( data );
1484 case VOCTRL_SET_EQUALIZER:
1486 va_list ap;
1487 int value;
1489 va_start( ap, data );
1490 value = va_arg( ap, int );
1491 va_end( ap );
1493 return set_equalizer( data, value );
1495 case VOCTRL_GET_EQUALIZER:
1497 va_list ap;
1498 int *value;
1500 va_start( ap, data );
1501 value = va_arg( ap, int* );
1502 va_end( ap );
1504 return get_equalizer( data, value );
1508 return VO_NOTIMPL;
1511 #include "osdep/keycodes.h"
1513 static void
1514 check_events( void )
1516 DFBInputEvent event;
1518 if (!buffer)
1519 return;
1521 if (buffer->GetEvent( buffer, DFB_EVENT( &event )) == DFB_OK) {
1522 if (event.type == DIET_KEYPRESS) {
1523 switch (event.key_symbol) {
1524 case DIKS_ESCAPE:
1525 mplayer_put_key( KEY_ESC );
1526 break;
1527 case DIKS_PAGE_UP:
1528 mplayer_put_key( KEY_PAGE_UP );
1529 break;
1530 case DIKS_PAGE_DOWN:
1531 mplayer_put_key( KEY_PAGE_DOWN );
1532 break;
1533 case DIKS_CURSOR_UP:
1534 mplayer_put_key( KEY_UP );
1535 break;
1536 case DIKS_CURSOR_DOWN:
1537 mplayer_put_key( KEY_DOWN );
1538 break;
1539 case DIKS_CURSOR_LEFT:
1540 mplayer_put_key( KEY_LEFT );
1541 break;
1542 case DIKS_CURSOR_RIGHT:
1543 mplayer_put_key( KEY_RIGHT );
1544 break;
1545 case DIKS_INSERT:
1546 mplayer_put_key( KEY_INSERT );
1547 break;
1548 case DIKS_DELETE:
1549 mplayer_put_key( KEY_DELETE );
1550 break;
1551 case DIKS_HOME:
1552 mplayer_put_key( KEY_HOME );
1553 break;
1554 case DIKS_END:
1555 mplayer_put_key( KEY_END );
1556 break;
1558 case DIKS_POWER:
1559 mplayer_put_key( KEY_POWER );
1560 break;
1561 case DIKS_MENU:
1562 mplayer_put_key( KEY_MENU );
1563 break;
1564 case DIKS_PLAY:
1565 mplayer_put_key( KEY_PLAY );
1566 break;
1567 case DIKS_STOP:
1568 mplayer_put_key( KEY_STOP );
1569 break;
1570 case DIKS_PAUSE:
1571 mplayer_put_key( KEY_PAUSE );
1572 break;
1573 case DIKS_PLAYPAUSE:
1574 mplayer_put_key( KEY_PLAYPAUSE );
1575 break;
1576 case DIKS_FORWARD:
1577 mplayer_put_key( KEY_FORWARD );
1578 break;
1579 case DIKS_NEXT:
1580 mplayer_put_key( KEY_NEXT );
1581 break;
1582 case DIKS_REWIND:
1583 mplayer_put_key( KEY_REWIND );
1584 break;
1585 case DIKS_PREVIOUS:
1586 mplayer_put_key( KEY_PREV );
1587 break;
1588 case DIKS_VOLUME_UP:
1589 mplayer_put_key( KEY_VOLUME_UP );
1590 break;
1591 case DIKS_VOLUME_DOWN:
1592 mplayer_put_key( KEY_VOLUME_DOWN );
1593 break;
1594 case DIKS_MUTE:
1595 mplayer_put_key( KEY_MUTE );
1596 break;
1598 default:
1599 mplayer_put_key( event.key_symbol );
1605 * empty buffer, because of repeating
1606 * keyboard repeat is faster than key handling and this causes problems during seek
1607 * temporary workabout. should be solved in the future
1609 buffer->Reset( buffer );