2 MPlayer video driver for DirectFB / Matrox G200/G400/G450/G550
4 Copyright (C) 2002-2005 Ville Syrjala <syrjala@sci.fi>
6 Originally based on vo_directfb.c by
7 Jiri Svoboda <Jiri.Svoboda@seznam.cz>
9 This library 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 of the License, or (at your option) any later version.
14 This library 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
20 License along with this library; if not, write to the
21 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301 USA.
25 /* directfb includes */
28 #define DFB_VERSION(a,b,c) (((a)<<16)|((b)<<8)|(c))
36 #include "video_out.h"
37 #include "video_out_internal.h"
38 #include "fastmemcpy.h"
44 static const vo_info_t info
= {
45 "DirectFB / Matrox G200/G400/G450/G550",
47 "Ville Syrjala <syrjala@sci.fi>",
51 const LIBVO_EXTERN(dfbmga
)
53 /******************************
55 ******************************/
60 static IDirectFB
*dfb
;
62 static IDirectFBDisplayLayer
*primary
;
63 static IDirectFBDisplayLayer
*bes
;
64 static IDirectFBDisplayLayer
*crtc2
;
65 static IDirectFBDisplayLayer
*spic
;
68 static int current_buf
;
69 static int current_ip_buf
;
70 static IDirectFBSurface
*bufs
[3];
72 static IDirectFBSurface
*frame
;
73 static IDirectFBSurface
*subframe
;
75 static IDirectFBSurface
*besframe
;
76 static IDirectFBSurface
*c2frame
;
77 static IDirectFBSurface
*spicframe
;
79 static DFBSurfacePixelFormat frame_format
;
80 static DFBSurfacePixelFormat subframe_format
;
82 static DFBRectangle besrect
;
83 static DFBRectangle c2rect
;
84 static DFBRectangle
*subrect
;
86 static IDirectFBInputDevice
*keyboard
;
87 static IDirectFBInputDevice
*remote
;
88 static IDirectFBEventBuffer
*buffer
;
97 static int use_remote
;
98 static int field_parity
;
100 static DFBDisplayLayerBufferMode buffermode
;
103 static int osd_changed
;
104 static int osd_dirty
;
105 static int osd_current
;
110 /******************************
112 ******************************/
114 #if DIRECTFBVERSION < DFB_VERSION(0,9,18)
115 #define DSPF_ALUT44 DSPF_LUT8
116 #define DLBM_TRIPLE ~0
117 #define DSFLIP_ONSYNC 0
120 #if DIRECTFBVERSION < DFB_VERSION(0,9,16)
121 #define DSPF_ARGB1555 DSPF_RGB15
124 static uint32_t in_width
;
125 static uint32_t in_height
;
126 static uint32_t buf_height
;
127 static uint32_t screen_width
;
128 static uint32_t screen_height
;
129 static uint32_t sub_width
;
130 static uint32_t sub_height
;
133 pixelformat_name( DFBSurfacePixelFormat format
)
156 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
163 return "Unknown pixel format";
167 static DFBSurfacePixelFormat
168 imgfmt_to_pixelformat( uint32_t format
)
178 return DSPF_ARGB1555
;
188 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
202 IDirectFBDisplayLayer
**layer
;
206 static DFBEnumerationResult
207 get_layer_by_name( DFBDisplayLayerID id
,
208 DFBDisplayLayerDescription desc
,
211 struct layer_enum
*l
= (struct layer_enum
*) data
;
213 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
214 /* We have desc.name so use it */
215 if (!strcmp( l
->name
, desc
.name
))
216 if ((l
->res
= dfb
->GetDisplayLayer( dfb
, id
, l
->layer
)) == DFB_OK
)
217 return DFENUM_CANCEL
;
219 /* Fake it according to id */
220 if ((id
== 0 && !strcmp( l
->name
, "FBDev Primary Layer" )) ||
221 (id
== 1 && !strcmp( l
->name
, "Matrox Backend Scaler" )) ||
222 (id
== 2 && !strcmp( l
->name
, "Matrox CRTC2" )) ||
223 (id
== 3 && !strcmp( l
->name
, "Matrox CRTC2 Sub-Picture" )))
224 if ((l
->res
= dfb
->GetDisplayLayer( dfb
, id
, l
->layer
)) == DFB_OK
)
225 return DFENUM_CANCEL
;
232 preinit( const char *arg
)
235 int force_input
= -1;
242 #if DIRECTFBVERSION > DFB_VERSION(0,9,17)
243 buffermode
= DLBM_TRIPLE
;
246 buffermode
= DLBM_BACKVIDEO
;
252 use_input
= !getenv( "DISPLAY" );
257 while (*vo_subdevice
!= '\0') {
258 if (!strncmp(vo_subdevice
, "bes", 3)) {
262 } else if (!strncmp(vo_subdevice
, "crtc2", 5)) {
266 } else if (!strncmp(vo_subdevice
, "spic", 4)) {
270 } else if (!strncmp(vo_subdevice
, "input", 5)) {
271 force_input
= !opt_no
;
274 } else if (!strncmp(vo_subdevice
, "remote", 6)) {
275 use_remote
= !opt_no
;
278 } else if (!strncmp(vo_subdevice
, "buffermode=", 11)) {
284 if (!strncmp(vo_subdevice
, "single", 6)) {
285 buffermode
= DLBM_FRONTONLY
;
289 } else if (!strncmp(vo_subdevice
, "double", 6)) {
290 buffermode
= DLBM_BACKVIDEO
;
294 } else if (!strncmp(vo_subdevice
, "triple", 6)) {
295 buffermode
= DLBM_TRIPLE
;
304 } else if (!strncmp(vo_subdevice
, "fieldparity=", 12)) {
310 if (!strncmp(vo_subdevice
, "top", 3)) {
313 } else if (!strncmp(vo_subdevice
, "bottom", 6)) {
321 } else if (!strncmp(vo_subdevice
, "tvnorm=", 7)) {
327 if (!strncmp(vo_subdevice
, "pal", 3)) {
330 } else if (!strncmp(vo_subdevice
, "ntsc" , 4)) {
333 } else if (!strncmp(vo_subdevice
, "auto" , 4)) {
341 } else if (!strncmp(vo_subdevice
, "no", 2)) {
348 } else if (*vo_subdevice
== ':') {
361 mp_msg( MSGT_VO
, MSGL_ERR
,
362 "\nvo_dfbmga command line help:\n"
363 "Example: mplayer -vo dfbmga:nocrtc2:bes:buffermode=single\n"
364 "\nOptions (use 'no' prefix to disable):\n"
365 " bes Use Backend Scaler\n"
367 " spic Use hardware sub-picture for OSD\n"
368 " input Use DirectFB for keyboard input\n"
369 " remote Use DirectFB for remote control input\n"
371 " buffermode=(single|double|triple)\n"
372 " single Use single buffering\n"
373 " double Use double buffering\n"
374 " triple Use triple buffering\n"
375 " fieldparity=(top|bottom)\n"
376 " top Top field first\n"
377 " bottom Bottom field first\n"
378 " tvnorm=(pal|ntsc|auto)\n"
381 " auto Select according to FPS\n"
386 if (!use_bes
&& !use_crtc2
) {
387 mp_msg( MSGT_VO
, MSGL_ERR
, "vo_dfbmga: No output selected\n" );
391 if ((res
= DirectFBInit( NULL
, NULL
)) != DFB_OK
) {
392 mp_msg( MSGT_VO
, MSGL_ERR
,
393 "vo_dfbmga: DirectFBInit() failed - %s\n",
394 DirectFBErrorString( res
) );
400 DirectFBSetOption( "matrox-tv-standard", "pal" );
401 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Forced TV standard to PAL\n" );
404 DirectFBSetOption( "matrox-tv-standard", "ntsc" );
405 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Forced TV standard to NTSC\n" );
409 DirectFBSetOption( "matrox-tv-standard", "ntsc" );
410 mp_msg( MSGT_VO
, MSGL_INFO
,
411 "vo_dfbmga: Selected TV standard based upon FPS: NTSC\n" );
413 DirectFBSetOption( "matrox-tv-standard", "pal" );
414 mp_msg( MSGT_VO
, MSGL_INFO
,
415 "vo_dfbmga: Selected TV standard based upon FPS: PAL\n" );
420 if ((res
= DirectFBCreate( &dfb
)) != DFB_OK
) {
421 mp_msg( MSGT_VO
, MSGL_ERR
,
422 "vo_dfbmga: DirectFBCreate() failed - %s\n",
423 DirectFBErrorString( res
) );
428 struct layer_enum l
= {
429 "FBDev Primary Layer",
433 dfb
->EnumDisplayLayers( dfb
, get_layer_by_name
, &l
);
434 if (l
.res
!= DFB_OK
) {
435 mp_msg( MSGT_VO
, MSGL_ERR
, "vo_dfbmga: Can't get primary layer - %s\n",
436 DirectFBErrorString( l
.res
) );
440 if ((res
= primary
->SetCooperativeLevel( primary
, DLSCL_EXCLUSIVE
)) != DFB_OK
) {
441 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get exclusive access to primary layer - %s\n",
442 DirectFBErrorString( res
) );
449 if (force_input
!= -1)
450 use_input
= force_input
;
453 DFBDisplayLayerConfig dlc
;
454 DFBDisplayLayerConfigFlags failed
;
455 struct layer_enum l
= {
456 "Matrox Backend Scaler",
461 dfb
->EnumDisplayLayers( dfb
, get_layer_by_name
, &l
);
462 if (l
.res
!= DFB_OK
) {
463 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get BES layer - %s\n",
464 DirectFBErrorString( l
.res
) );
468 if ((res
= bes
->SetCooperativeLevel( bes
, DLSCL_EXCLUSIVE
)) != DFB_OK
) {
469 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get exclusive access to BES - %s\n",
470 DirectFBErrorString( res
) );
474 dlc
.flags
= DLCONF_PIXELFORMAT
;
475 dlc
.pixelformat
= DSPF_RGB16
;
476 if (bes
->TestConfiguration( bes
, &dlc
, &failed
) != DFB_OK
) {
483 struct layer_enum l
= {
484 #if DIRECTFBVERSION > DFB_VERSION(0,9,20)
485 "Matrox CRTC2 Layer",
493 dfb
->EnumDisplayLayers( dfb
, get_layer_by_name
, &l
);
494 if (l
.res
!= DFB_OK
) {
495 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get CRTC2 layer - %s\n",
496 DirectFBErrorString( l
.res
) );
500 if ((res
= crtc2
->SetCooperativeLevel( crtc2
, DLSCL_EXCLUSIVE
)) != DFB_OK
) {
501 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get exclusive access to CRTC2 - %s\n",
502 DirectFBErrorString( res
) );
508 if (use_input
|| use_remote
) {
509 if ((res
= dfb
->CreateEventBuffer( dfb
, &buffer
)) != DFB_OK
) {
510 mp_msg( MSGT_VO
, MSGL_ERR
,
511 "vo_dfbmga: Can't create event buffer - %s\n",
512 DirectFBErrorString( res
) );
519 if ((res
= dfb
->GetInputDevice( dfb
, DIDID_KEYBOARD
, &keyboard
)) != DFB_OK
) {
520 mp_msg( MSGT_VO
, MSGL_ERR
,
521 "vo_dfbmga: Can't get keyboard - %s\n",
522 DirectFBErrorString( res
) );
526 if ((res
= keyboard
->AttachEventBuffer( keyboard
, buffer
)) != DFB_OK
) {
527 mp_msg( MSGT_VO
, MSGL_ERR
,
528 "vo_dfbmga: Can't attach event buffer to keyboard - %s\n",
529 DirectFBErrorString( res
) );
535 if ((res
= dfb
->GetInputDevice( dfb
, DIDID_REMOTE
, &remote
)) != DFB_OK
) {
536 mp_msg( MSGT_VO
, MSGL_ERR
,
537 "vo_dfbmga: Can't get remote control - %s\n",
538 DirectFBErrorString( res
) );
542 if ((res
= remote
->AttachEventBuffer( remote
, buffer
)) != DFB_OK
) {
543 mp_msg( MSGT_VO
, MSGL_ERR
,
544 "vo_dfbmga: Can't attach event buffer to remote control - %s\n",
545 DirectFBErrorString( res
) );
554 static void release_config( void )
557 spicframe
->Release( spicframe
);
559 spic
->Release( spic
);
561 c2frame
->Release( c2frame
);
563 besframe
->Release( besframe
);
565 bufs
[0]->Release( bufs
[0] );
567 bufs
[1]->Release( bufs
[1] );
569 bufs
[2]->Release( bufs
[2] );
581 config( uint32_t width
, uint32_t height
,
582 uint32_t d_width
, uint32_t d_height
,
589 DFBDisplayLayerConfig dlc
;
590 DFBDisplayLayerConfigFlags failed
;
600 aspect_save_orig(width
, height
);
601 aspect_save_prescale(d_width
, d_height
);
603 dlc
.pixelformat
= imgfmt_to_pixelformat( format
);
606 /* Draw to a temporary surface */
607 DFBSurfaceDescription dsc
;
609 dsc
.flags
= DSDESC_WIDTH
| DSDESC_HEIGHT
|
611 dsc
.width
= (in_width
+ 15) & ~15;
612 dsc
.height
= (in_height
+ 15) & ~15;
613 dsc
.pixelformat
= dlc
.pixelformat
;
615 /* Don't waste video memory since we don't need direct stretchblit */
617 dsc
.flags
|= DSDESC_CAPS
;
618 dsc
.caps
= DSCAPS_SYSTEMONLY
;
621 for (num_bufs
= 0; num_bufs
< 3; num_bufs
++) {
622 if ((res
= dfb
->CreateSurface( dfb
, &dsc
, &bufs
[num_bufs
] )) != DFB_OK
) {
624 mp_msg( MSGT_VO
, MSGL_ERR
,
625 "vo_dfbmga: Can't create surfaces - %s!\n",
626 DirectFBErrorString( res
) );
635 buf_height
= dsc
.height
;
637 frame
->GetPixelFormat( frame
, &frame_format
);
638 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Video surface %dx%d %s\n",
640 pixelformat_name( frame_format
) );
647 aspect_save_screenres( 0x10000, 0x10000 );
648 aspect( &out_width
, &out_height
, A_ZOOM
);
649 besrect
.x
= (0x10000 - out_width
) * in_width
/ out_width
/ 2;
650 besrect
.y
= (0x10000 - out_height
) * in_height
/ out_height
/ 2;
651 besrect
.w
= in_width
;
652 besrect
.h
= in_height
;
654 dlc
.flags
= DLCONF_WIDTH
| DLCONF_HEIGHT
| DLCONF_PIXELFORMAT
| DLCONF_BUFFERMODE
;
655 dlc
.width
= besrect
.w
+ besrect
.x
* 2;
656 dlc
.height
= besrect
.h
+ besrect
.y
* 2;
659 dlc
.buffermode
= DLBM_FRONTONLY
;
661 dlc
.buffermode
= buffermode
;
663 if ((res
= bes
->TestConfiguration( bes
, &dlc
, &failed
)) != DFB_OK
) {
664 mp_msg( MSGT_VO
, MSGL_ERR
,
665 "vo_dfbmga: Invalid BES configuration - %s!\n",
666 DirectFBErrorString( res
) );
669 if ((res
= bes
->SetConfiguration( bes
, &dlc
)) != DFB_OK
) {
670 mp_msg( MSGT_VO
, MSGL_ERR
,
671 "vo_dfbmga: BES configuration failed - %s!\n",
672 DirectFBErrorString( res
) );
675 bes
->GetSurface( bes
, &besframe
);
676 besframe
->SetBlittingFlags( besframe
, DSBLIT_NOFX
);
678 bes
->SetScreenLocation( bes
, 0.0, 0.0, 1.0, 1.0 );
680 besframe
->Clear( besframe
, 0, 0, 0, 0xff );
681 besframe
->Flip( besframe
, NULL
, 0 );
682 besframe
->Clear( besframe
, 0, 0, 0, 0xff );
683 besframe
->Flip( besframe
, NULL
, 0 );
684 besframe
->Clear( besframe
, 0, 0, 0, 0xff );
686 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: BES using %s buffering\n",
687 dlc
.buffermode
== DLBM_TRIPLE
? "triple" :
688 dlc
.buffermode
== DLBM_BACKVIDEO
? "double" : "single" );
689 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: BES surface %dx%d %s\n", dlc
.width
, dlc
.height
, pixelformat_name( dlc
.pixelformat
) );
696 dlc
.flags
= DLCONF_PIXELFORMAT
| DLCONF_BUFFERMODE
| DLCONF_OPTIONS
;
697 dlc
.buffermode
= buffermode
;
698 dlc
.options
= DLOP_NONE
;
700 #if DIRECTFBVERSION > DFB_VERSION(0,9,16)
701 if (field_parity
!= -1) {
702 dlc
.options
|= DLOP_FIELD_PARITY
;
705 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Field parity set to: ");
706 switch (field_parity
) {
708 mp_msg( MSGT_VO
, MSGL_INFO
, "Don't care\n");
711 mp_msg( MSGT_VO
, MSGL_INFO
, "Top field first\n");
714 mp_msg( MSGT_VO
, MSGL_INFO
, "Bottom field first\n");
718 switch (dlc
.pixelformat
) {
721 /* sub-picture supported */
726 /* Blit to YUY2/UYVY not supported */
727 dlc
.pixelformat
= DSPF_ARGB
;
731 /* sub-picture not supported */
735 if ((res
= crtc2
->TestConfiguration( crtc2
, &dlc
, &failed
)) != DFB_OK
) {
736 mp_msg( MSGT_VO
, MSGL_ERR
,
737 "vo_dfbmga: Invalid CRTC2 configuration - %s!\n",
738 DirectFBErrorString( res
) );
741 if ((res
= crtc2
->SetConfiguration( crtc2
, &dlc
)) != DFB_OK
) {
742 mp_msg( MSGT_VO
, MSGL_ERR
,
743 "vo_dfbmga: CRTC2 configuration failed - %s!\n",
744 DirectFBErrorString( res
) );
748 #if DIRECTFBVERSION > DFB_VERSION(0,9,16)
749 if (field_parity
!= -1)
750 crtc2
->SetFieldParity( crtc2
, field_parity
);
753 crtc2
->GetSurface( crtc2
, &c2frame
);
754 c2frame
->SetBlittingFlags( c2frame
, DSBLIT_NOFX
);
755 c2frame
->SetColor( c2frame
, 0, 0, 0, 0xff );
757 c2frame
->GetSize( c2frame
, &screen_width
, &screen_height
);
759 /* Don't stretch only slightly smaller videos */
760 if ((in_width
> (0.95 * screen_width
)) &&
761 (in_width
< screen_width
))
762 out_width
= in_width
;
764 out_width
= screen_width
;
765 if ((in_height
> (0.95 * screen_height
)) &&
766 (in_height
< screen_height
))
767 out_height
= in_height
;
769 out_height
= screen_height
;
771 aspect_save_screenres( out_width
, out_height
);
772 aspect( &out_width
, &out_height
, (flags
& VOFLAG_FULLSCREEN
) ? A_ZOOM
: A_NOZOOM
);
774 if (in_width
!= out_width
||
775 in_height
!= out_height
)
780 c2rect
.x
= (screen_width
- out_width
) / 2;
781 c2rect
.y
= (screen_height
- out_height
) / 2;
782 c2rect
.w
= out_width
;
783 c2rect
.h
= out_height
;
785 c2frame
->Clear( c2frame
, 0, 0, 0, 0xff );
786 c2frame
->Flip( c2frame
, NULL
, 0 );
787 c2frame
->Clear( c2frame
, 0, 0, 0, 0xff );
788 c2frame
->Flip( c2frame
, NULL
, 0 );
789 c2frame
->Clear( c2frame
, 0, 0, 0, 0xff );
791 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: CRTC2 using %s buffering\n",
792 dlc
.buffermode
== DLBM_TRIPLE
? "triple" :
793 dlc
.buffermode
== DLBM_BACKVIDEO
? "double" : "single" );
794 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: CRTC2 surface %dx%d %s\n", screen_width
, screen_height
, pixelformat_name( dlc
.pixelformat
) );
803 /* Draw OSD to sub-picture surface */
804 IDirectFBPalette
*palette
;
807 struct layer_enum l
= {
808 "Matrox CRTC2 Sub-Picture",
812 dfb
->EnumDisplayLayers( dfb
, get_layer_by_name
, &l
);
813 if (l
.res
!= DFB_OK
) {
814 mp_msg( MSGT_VO
, MSGL_ERR
, "vo_dfbmga: Can't get sub-picture layer - %s\n",
815 DirectFBErrorString( l
.res
) );
818 if ((res
= spic
->SetCooperativeLevel( spic
, DLSCL_EXCLUSIVE
)) != DFB_OK
) {
819 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get exclusive access to sub-picture - %s\n",
820 DirectFBErrorString( res
) );
824 dlc
.flags
= DLCONF_PIXELFORMAT
| DLCONF_BUFFERMODE
;
825 dlc
.pixelformat
= DSPF_ALUT44
;
826 dlc
.buffermode
= buffermode
;
828 #if DIRECTFBVERSION > DFB_VERSION(0,9,16)
829 dlc
.flags
|= DLCONF_OPTIONS
;
830 dlc
.options
= DLOP_ALPHACHANNEL
;
832 if ((res
= spic
->TestConfiguration( spic
, &dlc
, &failed
)) != DFB_OK
) {
833 mp_msg( MSGT_VO
, MSGL_ERR
,
834 "vo_dfbmga: Invalid sub-picture configuration - %s!\n",
835 DirectFBErrorString( res
) );
838 if ((res
= spic
->SetConfiguration( spic
, &dlc
)) != DFB_OK
) {
839 mp_msg( MSGT_VO
, MSGL_ERR
,
840 "vo_dfbmga: Sub-picture configuration failed - %s!\n",
841 DirectFBErrorString( res
) );
845 spic
->GetSurface( spic
, &spicframe
);
847 spicframe
->GetPalette( spicframe
, &palette
);
849 for (i
= 0; i
< 16; i
++) {
853 palette
->SetEntries( palette
, &color
, 1, i
);
855 palette
->Release( palette
);
857 spicframe
->Clear( spicframe
, 0, 0, 0, 0 );
858 spicframe
->Flip( spicframe
, NULL
, 0 );
859 spicframe
->Clear( spicframe
, 0, 0, 0, 0 );
860 spicframe
->Flip( spicframe
, NULL
, 0 );
861 spicframe
->Clear( spicframe
, 0, 0, 0, 0 );
863 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Sub-picture layer using %s buffering\n",
864 dlc
.buffermode
== DLBM_TRIPLE
? "triple" :
865 dlc
.buffermode
== DLBM_BACKVIDEO
? "double" : "single" );
867 subframe
= spicframe
;
869 } else if (use_crtc2
) {
870 /* Draw OSD to CRTC2 surface */
874 /* Draw OSD to BES surface */
879 subframe
->GetSize( subframe
, &sub_width
, &sub_height
);
880 subframe
->GetPixelFormat( subframe
, &subframe_format
);
881 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Sub-picture surface %dx%d %s (%s)\n",
882 sub_width
, sub_height
,
883 pixelformat_name( subframe_format
),
884 use_crtc2
? (use_spic
? "Sub-picture layer" : "CRTC2") : "BES" );
894 query_format( uint32_t format
)
909 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
912 if (!use_bes
|| use_crtc2
)
920 return (VFCAP_HWSCALE_UP
|
922 VFCAP_CSP_SUPPORTED_BY_HW
|
923 VFCAP_CSP_SUPPORTED
|
928 vo_draw_alpha_alut44( int w
, int h
,
938 for (x
= 0; x
< w
; x
++) {
940 dst
[x
] = ((255 - srca
[x
]) & 0xF0) | (src
[x
] >> 4);
949 clear_alpha( int x0
, int y0
,
952 if (use_spic
&& !flipping
&& vo_osd_changed_flag
)
953 subframe
->FillRectangle( subframe
, x0
, y0
, w
, h
);
957 draw_alpha( int x0
, int y0
,
967 if (!osd_changed
|| (!flipping
&& !vo_osd_changed_flag
))
969 osd_dirty
|= osd_current
;
971 if (x0
< subrect
->x
||
973 x0
+ w
> subrect
->x
+ subrect
->w
||
974 y0
+ h
> subrect
->y
+ subrect
->h
)
975 osd_dirty
|= osd_current
;
978 if (subframe
->Lock( subframe
, DSLF_READ
| DSLF_WRITE
, &dst
, &pitch
) != DFB_OK
)
981 switch (subframe_format
) {
983 vo_draw_alpha_alut44( w
, h
, src
, srca
, stride
,
984 ((uint8_t *) dst
) + pitch
* y0
+ x0
,
989 vo_draw_alpha_rgb32( w
, h
, src
, srca
, stride
,
990 (( uint8_t *) dst
) + pitch
* y0
+ 4 * x0
,
994 vo_draw_alpha_rgb24( w
, h
, src
, srca
, stride
,
995 ((uint8_t *) dst
) + pitch
* y0
+ 3 * x0
,
999 vo_draw_alpha_rgb16( w
, h
, src
, srca
, stride
,
1000 ((uint8_t *) dst
) + pitch
* y0
+ 2 * x0
,
1004 vo_draw_alpha_rgb15( w
, h
, src
, srca
, stride
,
1005 ((uint8_t *) dst
) + pitch
* y0
+ 2 * x0
,
1009 vo_draw_alpha_yuy2( w
, h
, src
, srca
, stride
,
1010 ((uint8_t *) dst
) + pitch
* y0
+ 2 * x0
,
1014 vo_draw_alpha_yuy2( w
, h
, src
, srca
, stride
,
1015 ((uint8_t *) dst
) + pitch
* y0
+ 2 * x0
+ 1,
1018 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
1024 vo_draw_alpha_yv12( w
, h
, src
, srca
, stride
,
1025 ((uint8_t *) dst
) + pitch
* y0
+ x0
,
1030 subframe
->Unlock( subframe
);
1034 draw_frame( uint8_t * src
[] )
1040 draw_slice( uint8_t * src
[], int stride
[], int w
, int h
, int x
, int y
)
1045 if (frame
->Lock( frame
, DSLF_WRITE
, &dst
, &pitch
) != DFB_OK
)
1048 memcpy_pic( dst
+ pitch
* y
+ x
, src
[0],
1049 w
, h
, pitch
, stride
[0] );
1051 dst
+= pitch
* buf_height
;
1056 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
1057 if (frame_format
== DSPF_NV12
|| frame_format
== DSPF_NV21
) {
1058 memcpy_pic( dst
+ pitch
* y
+ x
, src
[1],
1059 w
, h
, pitch
, stride
[1] );
1067 if (frame_format
== DSPF_I420
)
1068 memcpy_pic( dst
+ pitch
* y
+ x
, src
[1],
1069 w
, h
, pitch
, stride
[1] );
1071 memcpy_pic( dst
+ pitch
* y
+ x
, src
[2],
1072 w
, h
, pitch
, stride
[2] );
1074 dst
+= pitch
* buf_height
/ 2;
1076 if (frame_format
== DSPF_I420
)
1077 memcpy_pic( dst
+ pitch
* y
+ x
, src
[2],
1078 w
, h
, pitch
, stride
[2] );
1080 memcpy_pic( dst
+ pitch
* y
+ x
, src
[1],
1081 w
, h
, pitch
, stride
[1] );
1084 frame
->Unlock( frame
);
1090 blit_to_screen( void )
1092 IDirectFBSurface
*blitsrc
= frame
;
1093 DFBRectangle
*srect
= NULL
;
1096 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
1097 if (vo_vsync
&& !flipping
&& !use_crtc2
)
1098 bes
->WaitForSync( bes
);
1101 besframe
->Blit( besframe
, blitsrc
, NULL
, besrect
.x
, besrect
.y
);
1107 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
1108 if (vo_vsync
&& !flipping
)
1109 crtc2
->WaitForSync( crtc2
);
1113 c2frame
->StretchBlit( c2frame
, blitsrc
, srect
, &c2rect
);
1115 c2frame
->Blit( c2frame
, blitsrc
, srect
, c2rect
.x
, c2rect
.y
);
1122 frame
= bufs
[current_buf
];
1123 frame
->Unlock( frame
);
1125 osd_changed
= vo_osd_changed( 0 );
1126 if (osd_dirty
& osd_current
) {
1129 subframe
->Clear( subframe
, 0, 0, 0, 0 );
1131 /* Clear black bars around the picture */
1132 subframe
->FillRectangle( subframe
,
1134 sub_width
, subrect
->y
);
1135 subframe
->FillRectangle( subframe
,
1136 0, subrect
->y
+ subrect
->h
,
1137 sub_width
, subrect
->y
);
1138 subframe
->FillRectangle( subframe
,
1140 subrect
->x
, subrect
->h
);
1141 subframe
->FillRectangle( subframe
,
1142 subrect
->x
+ subrect
->w
, subrect
->y
,
1143 subrect
->x
, subrect
->h
);
1145 osd_dirty
&= ~osd_current
;
1151 vo_remove_text( sub_width
, sub_height
, clear_alpha
);
1152 vo_draw_text( sub_width
, sub_height
, draw_alpha
);
1154 if (use_spic
&& flipping
&& osd_changed
) {
1155 subframe
->Flip( subframe
, NULL
, 0 );
1157 if (osd_current
> osd_max
)
1170 c2frame
->Flip( c2frame
, NULL
, vo_vsync
? DSFLIP_WAITFORSYNC
: DSFLIP_ONSYNC
);
1172 besframe
->Flip( besframe
, NULL
, vo_vsync
? DSFLIP_WAITFORSYNC
: DSFLIP_ONSYNC
);
1176 if (osd_current
> osd_max
)
1191 buffer
->Release( buffer
);
1193 remote
->Release( remote
);
1195 keyboard
->Release( keyboard
);
1197 crtc2
->Release( crtc2
);
1199 bes
->Release( bes
);
1201 primary
->Release( primary
);
1203 dfb
->Release( dfb
);
1215 get_image( mp_image_t
*mpi
)
1217 int buf
= current_buf
;
1221 if (mpi
->flags
& MP_IMGFLAG_READABLE
&&
1222 (mpi
->type
== MP_IMGTYPE_IPB
|| mpi
->type
== MP_IMGTYPE_IP
)) {
1226 current_ip_buf
^= 1;
1228 if (mpi
->type
== MP_IMGTYPE_IPB
&& num_bufs
< 3 && current_ip_buf
)
1231 buf
= current_ip_buf
;
1233 if (mpi
->type
== MP_IMGTYPE_IPB
)
1237 frame
->Unlock( frame
);
1239 /* Always use DSLF_READ to preserve system memory copy */
1240 if (frame
->Lock( frame
, DSLF_WRITE
| DSLF_READ
,
1241 &dst
, &pitch
) != DFB_OK
)
1244 if ((mpi
->width
== pitch
) ||
1245 (mpi
->flags
& (MP_IMGFLAG_ACCEPT_STRIDE
| MP_IMGFLAG_ACCEPT_WIDTH
))) {
1247 mpi
->planes
[0] = dst
;
1248 mpi
->width
= in_width
;
1249 mpi
->stride
[0] = pitch
;
1251 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
1252 if (mpi
->num_planes
> 2) {
1253 mpi
->stride
[1] = mpi
->stride
[2] = pitch
/ 2;
1255 if (mpi
->flags
& MP_IMGFLAG_SWAPPED
) {
1257 mpi
->planes
[1] = dst
+ buf_height
* pitch
;
1258 mpi
->planes
[2] = mpi
->planes
[1] + buf_height
* pitch
/ 4;
1261 mpi
->planes
[2] = dst
+ buf_height
* pitch
;
1262 mpi
->planes
[1] = mpi
->planes
[2] + buf_height
* pitch
/ 4;
1266 mpi
->stride
[1] = pitch
;
1267 mpi
->planes
[1] = dst
+ buf_height
* pitch
;
1271 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
1272 mpi
->priv
= (void *) buf
;
1278 frame
->Unlock( frame
);
1286 draw_image( mp_image_t
*mpi
)
1288 if (mpi
->flags
& MP_IMGFLAG_DIRECT
) {
1289 current_buf
= (int) mpi
->priv
;
1292 if (mpi
->flags
& MP_IMGFLAG_DRAW_CALLBACK
)
1295 if (mpi
->flags
& MP_IMGFLAG_PLANAR
)
1296 return draw_slice( mpi
->planes
, mpi
->stride
,
1297 mpi
->w
, mpi
->h
, 0, 0 );
1302 if (frame
->Lock( frame
, DSLF_WRITE
, &dst
, &pitch
) != DFB_OK
)
1304 memcpy_pic( dst
, mpi
->planes
[0],
1305 mpi
->w
* (mpi
->bpp
/ 8), mpi
->h
,
1306 pitch
, mpi
->stride
[0] );
1307 frame
->Unlock( frame
);
1314 set_equalizer( char *data
, int value
)
1317 DFBColorAdjustment ca
;
1318 float factor
= (float) 0xffff / 200.0;
1320 ca
.flags
= DCAF_NONE
;
1322 if (!strcasecmp( data
, "brightness" )) {
1323 ca
.flags
|= DCAF_BRIGHTNESS
;
1324 ca
.brightness
= value
* factor
+ 0x8000;
1326 if (!strcasecmp( data
, "contrast" )) {
1327 ca
.flags
|= DCAF_CONTRAST
;
1328 ca
.contrast
= value
* factor
+ 0x8000;
1330 if (!strcasecmp( data
, "hue" )) {
1331 ca
.flags
|= DCAF_HUE
;
1332 ca
.hue
= value
* factor
+ 0x8000;
1334 if (!strcasecmp( data
, "saturation" )) {
1335 ca
.flags
|= DCAF_SATURATION
;
1336 ca
.saturation
= value
* factor
+ 0x8000;
1339 /* Prefer CRTC2 over BES */
1341 res
= crtc2
->SetColorAdjustment( crtc2
, &ca
);
1343 res
= bes
->SetColorAdjustment( bes
, &ca
);
1352 get_equalizer( char *data
, int *value
)
1355 DFBColorAdjustment ca
;
1356 float factor
= 200.0 / (float) 0xffff;
1358 /* Prefer CRTC2 over BES */
1360 res
= crtc2
->GetColorAdjustment( crtc2
, &ca
);
1362 res
= bes
->GetColorAdjustment( bes
, &ca
);
1367 if (!strcasecmp( data
, "brightness" ) &&
1368 (ca
.flags
& DCAF_BRIGHTNESS
))
1369 *value
= (ca
.brightness
- 0x8000) * factor
;
1370 if (!strcasecmp( data
, "contrast" ) &&
1371 (ca
.flags
& DCAF_CONTRAST
))
1372 *value
= (ca
.contrast
- 0x8000) * factor
;
1373 if (!strcasecmp( data
, "hue" ) &&
1374 (ca
.flags
& DCAF_HUE
))
1375 *value
= (ca
.hue
- 0x8000) * factor
;
1376 if (!strcasecmp( data
, "saturation" ) &&
1377 (ca
.flags
& DCAF_SATURATION
))
1378 *value
= (ca
.saturation
- 0x8000) * factor
;
1384 control( uint32_t request
, void *data
, ... )
1387 case VOCTRL_GUISUPPORT
:
1388 case VOCTRL_GUI_NOWINDOW
:
1391 case VOCTRL_QUERY_FORMAT
:
1392 return query_format( *((uint32_t *) data
) );
1394 case VOCTRL_GET_IMAGE
:
1395 return get_image( data
);
1397 case VOCTRL_DRAW_IMAGE
:
1398 return draw_image( data
);
1400 case VOCTRL_SET_EQUALIZER
:
1405 va_start( ap
, data
);
1406 value
= va_arg( ap
, int );
1409 return set_equalizer( data
, value
);
1411 case VOCTRL_GET_EQUALIZER
:
1416 va_start( ap
, data
);
1417 value
= va_arg( ap
, int* );
1420 return get_equalizer( data
, value
);
1427 #include "osdep/keycodes.h"
1430 check_events( void )
1432 DFBInputEvent event
;
1437 if (buffer
->GetEvent( buffer
, DFB_EVENT( &event
)) == DFB_OK
) {
1438 if (event
.type
== DIET_KEYPRESS
) {
1439 switch (event
.key_symbol
) {
1441 mplayer_put_key( KEY_ESC
);
1444 mplayer_put_key( KEY_PAGE_UP
);
1446 case DIKS_PAGE_DOWN
:
1447 mplayer_put_key( KEY_PAGE_DOWN
);
1449 case DIKS_CURSOR_UP
:
1450 mplayer_put_key( KEY_UP
);
1452 case DIKS_CURSOR_DOWN
:
1453 mplayer_put_key( KEY_DOWN
);
1455 case DIKS_CURSOR_LEFT
:
1456 mplayer_put_key( KEY_LEFT
);
1458 case DIKS_CURSOR_RIGHT
:
1459 mplayer_put_key( KEY_RIGHT
);
1462 mplayer_put_key( KEY_INSERT
);
1465 mplayer_put_key( KEY_DELETE
);
1468 mplayer_put_key( KEY_HOME
);
1471 mplayer_put_key( KEY_END
);
1475 mplayer_put_key( KEY_POWER
);
1478 mplayer_put_key( KEY_MENU
);
1481 mplayer_put_key( KEY_PLAY
);
1484 mplayer_put_key( KEY_STOP
);
1487 mplayer_put_key( KEY_PAUSE
);
1489 case DIKS_PLAYPAUSE
:
1490 mplayer_put_key( KEY_PLAYPAUSE
);
1493 mplayer_put_key( KEY_FORWARD
);
1496 mplayer_put_key( KEY_NEXT
);
1499 mplayer_put_key( KEY_REWIND
);
1502 mplayer_put_key( KEY_PREV
);
1504 case DIKS_VOLUME_UP
:
1505 mplayer_put_key( KEY_VOLUME_UP
);
1507 case DIKS_VOLUME_DOWN
:
1508 mplayer_put_key( KEY_VOLUME_DOWN
);
1511 mplayer_put_key( KEY_MUTE
);
1515 mplayer_put_key( event
.key_symbol
);
1521 * empty buffer, because of repeating
1522 * keyboard repeat is faster than key handling and this causes problems during seek
1523 * temporary workabout. should be solved in the future
1525 buffer
->Reset( buffer
);