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 */
27 #define DFB_VERSION(a,b,c) (((a)<<16)|((b)<<8)|(c))
35 #include "video_out.h"
36 #include "video_out_internal.h"
37 #include "fastmemcpy.h"
43 static const vo_info_t info
= {
44 "DirectFB / Matrox G200/G400/G450/G550",
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
;
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
;
93 static int use_remote
;
94 static int field_parity
;
96 static DFBDisplayLayerBufferMode buffermode
;
99 static int osd_changed
;
100 static int osd_dirty
;
101 static int osd_current
;
106 #if DIRECTFBVERSION < DFB_VERSION(0,9,18)
107 #define DSPF_ALUT44 DSPF_LUT8
108 #define DLBM_TRIPLE ~0
109 #define DSFLIP_ONSYNC 0
112 #if DIRECTFBVERSION < DFB_VERSION(0,9,16)
113 #define DSPF_ARGB1555 DSPF_RGB15
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
;
125 pixelformat_name( DFBSurfacePixelFormat format
)
146 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
153 return "Unknown pixel format";
157 static DFBSurfacePixelFormat
158 imgfmt_to_pixelformat( uint32_t format
)
166 return DSPF_ARGB1555
;
176 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
190 IDirectFBDisplayLayer
**layer
;
194 static DFBEnumerationResult
195 get_layer_by_name( DFBDisplayLayerID id
,
196 DFBDisplayLayerDescription desc
,
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
;
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
;
220 preinit( const char *arg
)
223 int force_input
= -1;
231 #if DIRECTFBVERSION > DFB_VERSION(0,9,17)
232 buffermode
= DLBM_TRIPLE
;
235 buffermode
= DLBM_BACKVIDEO
;
241 use_input
= !getenv( "DISPLAY" );
246 while (*vo_subdevice
!= '\0') {
247 if (!strncmp(vo_subdevice
, "bes", 3)) {
251 } else if (!strncmp(vo_subdevice
, "crtc1", 5)) {
255 } else if (!strncmp(vo_subdevice
, "crtc2", 5)) {
259 } else if (!strncmp(vo_subdevice
, "spic", 4)) {
263 } else if (!strncmp(vo_subdevice
, "input", 5)) {
264 force_input
= !opt_no
;
267 } else if (!strncmp(vo_subdevice
, "remote", 6)) {
268 use_remote
= !opt_no
;
271 } else if (!strncmp(vo_subdevice
, "buffermode=", 11)) {
277 if (!strncmp(vo_subdevice
, "single", 6)) {
278 buffermode
= DLBM_FRONTONLY
;
282 } else if (!strncmp(vo_subdevice
, "double", 6)) {
283 buffermode
= DLBM_BACKVIDEO
;
287 } else if (!strncmp(vo_subdevice
, "triple", 6)) {
288 buffermode
= DLBM_TRIPLE
;
297 } else if (!strncmp(vo_subdevice
, "fieldparity=", 12)) {
303 if (!strncmp(vo_subdevice
, "top", 3)) {
306 } else if (!strncmp(vo_subdevice
, "bottom", 6)) {
314 } else if (!strncmp(vo_subdevice
, "tvnorm=", 7)) {
320 if (!strncmp(vo_subdevice
, "pal", 3)) {
323 } else if (!strncmp(vo_subdevice
, "ntsc" , 4)) {
326 } else if (!strncmp(vo_subdevice
, "auto" , 4)) {
334 } else if (!strncmp(vo_subdevice
, "no", 2)) {
341 } else if (*vo_subdevice
== ':') {
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"
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"
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"
375 " auto Select according to FPS\n"
380 if (!use_bes
&& !use_crtc1
&& !use_crtc2
) {
381 mp_msg( MSGT_VO
, MSGL_ERR
, "vo_dfbmga: No output selected\n" );
384 if (use_bes
&& use_crtc1
) {
385 mp_msg( MSGT_VO
, MSGL_ERR
, "vo_dfbmga: Both BES and CRTC1 outputs selected\n" );
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
) );
398 DirectFBSetOption( "matrox-tv-standard", "pal" );
399 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Forced TV standard to PAL\n" );
402 DirectFBSetOption( "matrox-tv-standard", "ntsc" );
403 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Forced TV standard to NTSC\n" );
407 DirectFBSetOption( "matrox-tv-standard", "ntsc" );
408 mp_msg( MSGT_VO
, MSGL_INFO
,
409 "vo_dfbmga: Selected TV standard based upon FPS: NTSC\n" );
411 DirectFBSetOption( "matrox-tv-standard", "pal" );
412 mp_msg( MSGT_VO
, MSGL_INFO
,
413 "vo_dfbmga: Selected TV standard based upon FPS: PAL\n" );
418 if ((res
= DirectFBCreate( &dfb
)) != DFB_OK
) {
419 mp_msg( MSGT_VO
, MSGL_ERR
,
420 "vo_dfbmga: DirectFBCreate() failed - %s\n",
421 DirectFBErrorString( res
) );
425 if (use_crtc1
|| use_bes
) {
426 struct layer_enum l
= {
427 "FBDev Primary Layer",
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
) );
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
) );
447 if (force_input
!= -1)
448 use_input
= force_input
;
451 DFBDisplayLayerConfig dlc
;
452 DFBDisplayLayerConfigFlags failed
;
453 struct layer_enum l
= {
454 "Matrox Backend Scaler",
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
) );
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
) );
472 dlc
.flags
= DLCONF_PIXELFORMAT
;
473 dlc
.pixelformat
= DSPF_RGB16
;
474 if (bes
->TestConfiguration( bes
, &dlc
, &failed
) != DFB_OK
) {
481 struct layer_enum l
= {
482 #if DIRECTFBVERSION > DFB_VERSION(0,9,20)
483 "Matrox CRTC2 Layer",
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
) );
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
) );
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
) );
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
) );
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
) );
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
) );
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
) );
552 static void release_config( void )
555 spicframe
->Release( spicframe
);
557 spic
->Release( spic
);
559 c2frame
->Release( c2frame
);
561 c1frame
->Release( c1frame
);
563 besframe
->Release( besframe
);
565 bufs
[0]->Release( bufs
[0] );
567 bufs
[1]->Release( bufs
[1] );
569 bufs
[2]->Release( bufs
[2] );
582 config( uint32_t width
, uint32_t height
,
583 uint32_t d_width
, uint32_t d_height
,
590 DFBDisplayLayerConfig dlc
;
591 DFBDisplayLayerConfigFlags failed
;
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
|
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 */
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
) {
625 mp_msg( MSGT_VO
, MSGL_ERR
,
626 "vo_dfbmga: Can't create surfaces - %s!\n",
627 DirectFBErrorString( res
) );
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",
641 pixelformat_name( frame_format
) );
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
) );
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
) );
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
) );
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
) );
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
) );
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
) );
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
)
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
) );
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
;
759 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Field parity set to: ");
760 switch (field_parity
) {
762 mp_msg( MSGT_VO
, MSGL_INFO
, "Don't care\n");
765 mp_msg( MSGT_VO
, MSGL_INFO
, "Top field first\n");
768 mp_msg( MSGT_VO
, MSGL_INFO
, "Bottom field first\n");
772 switch (dlc
.pixelformat
) {
775 /* sub-picture supported */
780 /* Blit to YUY2/UYVY not supported */
781 dlc
.pixelformat
= DSPF_ARGB
;
785 /* sub-picture not supported */
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
) );
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
) );
802 #if DIRECTFBVERSION > DFB_VERSION(0,9,16)
803 if (field_parity
!= -1)
804 crtc2
->SetFieldParity( crtc2
, field_parity
);
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
;
818 out_width
= screen_width
;
819 if ((in_height
> (0.95 * screen_height
)) &&
820 (in_height
< screen_height
))
821 out_height
= in_height
;
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
)
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
) );
857 /* Draw OSD to sub-picture surface */
858 IDirectFBPalette
*palette
;
861 struct layer_enum l
= {
862 "Matrox CRTC2 Sub-Picture",
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
) );
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
) );
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
;
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
) );
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
) );
899 spic
->GetSurface( spic
, &spicframe
);
901 spicframe
->GetPalette( spicframe
, &palette
);
903 for (i
= 0; i
< 16; i
++) {
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
;
923 } else if (use_crtc2
) {
924 /* Draw OSD to CRTC2 surface */
927 } else if (use_crtc1
) {
928 /* Draw OSD to CRTC1 surface */
932 /* Draw OSD to BES surface */
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" );
953 query_format( uint32_t format
)
959 if (is_g200
|| use_crtc1
)
965 if (is_g200
&& use_bes
)
974 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
977 if (use_crtc1
|| use_crtc2
)
985 return VFCAP_HWSCALE_UP
|
987 VFCAP_CSP_SUPPORTED_BY_HW
|
988 VFCAP_CSP_SUPPORTED
|
993 vo_draw_alpha_alut44( int w
, int h
,
1003 for (x
= 0; x
< w
; x
++) {
1005 dst
[x
] = ((255 - srca
[x
]) & 0xF0) | (src
[x
] >> 4);
1014 clear_alpha( int x0
, int y0
,
1017 if (use_spic
&& !flipping
&& vo_osd_changed_flag
)
1018 subframe
->FillRectangle( subframe
, x0
, y0
, w
, h
);
1022 draw_alpha( int x0
, int y0
,
1025 unsigned char *srca
,
1033 if (!osd_changed
|| (!flipping
&& !vo_osd_changed_flag
))
1035 osd_dirty
|= osd_current
;
1037 if (x0
< subrect
->x
||
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
)
1048 switch (subframe_format
) {
1050 vo_draw_alpha_alut44( w
, h
, src
, srca
, stride
,
1051 dst
+ pitch
* y0
+ x0
,
1056 vo_draw_alpha_rgb32( w
, h
, src
, srca
, stride
,
1057 dst
+ pitch
* y0
+ 4 * x0
,
1061 vo_draw_alpha_rgb16( w
, h
, src
, srca
, stride
,
1062 dst
+ pitch
* y0
+ 2 * x0
,
1066 vo_draw_alpha_rgb15( w
, h
, src
, srca
, stride
,
1067 dst
+ pitch
* y0
+ 2 * x0
,
1071 vo_draw_alpha_yuy2( w
, h
, src
, srca
, stride
,
1072 dst
+ pitch
* y0
+ 2 * x0
,
1076 vo_draw_alpha_yuy2( w
, h
, src
, srca
, stride
,
1077 dst
+ pitch
* y0
+ 2 * x0
+ 1,
1080 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
1086 vo_draw_alpha_yv12( w
, h
, src
, srca
, stride
,
1087 dst
+ pitch
* y0
+ x0
,
1092 subframe
->Unlock( subframe
);
1096 draw_frame( uint8_t * src
[] )
1102 draw_slice( uint8_t * src
[], int stride
[], int w
, int h
, int x
, int y
)
1108 if (frame
->Lock( frame
, DSLF_WRITE
, &ptr
, &pitch
) != DFB_OK
)
1112 memcpy_pic( dst
+ pitch
* y
+ x
, src
[0],
1113 w
, h
, pitch
, stride
[0] );
1115 dst
+= pitch
* buf_height
;
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] );
1131 if (frame_format
== DSPF_I420
)
1132 memcpy_pic( dst
+ pitch
* y
+ x
, src
[1],
1133 w
, h
, pitch
, stride
[1] );
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] );
1144 memcpy_pic( dst
+ pitch
* y
+ x
, src
[1],
1145 w
, h
, pitch
, stride
[1] );
1148 frame
->Unlock( frame
);
1154 blit_to_screen( void )
1156 IDirectFBSurface
*blitsrc
= frame
;
1157 DFBRectangle
*srect
= NULL
;
1160 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
1161 if (vo_vsync
&& !flipping
)
1162 bes
->WaitForSync( bes
);
1165 besframe
->Blit( besframe
, blitsrc
, NULL
, besrect
.x
, besrect
.y
);
1171 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
1172 if (vo_vsync
&& !flipping
)
1173 crtc1
->WaitForSync( crtc1
);
1177 c1frame
->StretchBlit( c1frame
, blitsrc
, srect
, &c1rect
);
1179 c1frame
->Blit( c1frame
, blitsrc
, srect
, c1rect
.x
, c1rect
.y
);
1183 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
1184 if (vo_vsync
&& !flipping
)
1185 crtc2
->WaitForSync( crtc2
);
1189 c2frame
->StretchBlit( c2frame
, blitsrc
, srect
, &c2rect
);
1191 c2frame
->Blit( c2frame
, blitsrc
, srect
, c2rect
.x
, c2rect
.y
);
1198 frame
= bufs
[current_buf
];
1199 frame
->Unlock( frame
);
1201 osd_changed
= vo_osd_changed( 0 );
1202 if (osd_dirty
& osd_current
) {
1205 subframe
->Clear( subframe
, 0, 0, 0, 0 );
1207 /* Clear black bars around the picture */
1208 subframe
->FillRectangle( subframe
,
1210 sub_width
, subrect
->y
);
1211 subframe
->FillRectangle( subframe
,
1212 0, subrect
->y
+ subrect
->h
,
1213 sub_width
, subrect
->y
);
1214 subframe
->FillRectangle( subframe
,
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
;
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 );
1233 if (osd_current
> osd_max
)
1246 c2frame
->Flip( c2frame
, NULL
, vo_vsync
? DSFLIP_WAITFORSYNC
: DSFLIP_ONSYNC
);
1248 c1frame
->Flip( c1frame
, NULL
, vo_vsync
? DSFLIP_WAITFORSYNC
: DSFLIP_ONSYNC
);
1250 besframe
->Flip( besframe
, NULL
, vo_vsync
? DSFLIP_WAITFORSYNC
: DSFLIP_ONSYNC
);
1254 if (osd_current
> osd_max
)
1269 buffer
->Release( buffer
);
1271 remote
->Release( remote
);
1273 keyboard
->Release( keyboard
);
1275 crtc2
->Release( crtc2
);
1277 bes
->Release( bes
);
1279 crtc1
->Release( crtc1
);
1281 dfb
->Release( dfb
);
1293 get_image( mp_image_t
*mpi
)
1295 int buf
= current_buf
;
1300 if (mpi
->flags
& MP_IMGFLAG_READABLE
&&
1301 (mpi
->type
== MP_IMGTYPE_IPB
|| mpi
->type
== MP_IMGTYPE_IP
)) {
1305 current_ip_buf
^= 1;
1307 if (mpi
->type
== MP_IMGTYPE_IPB
&& num_bufs
< 3 && current_ip_buf
)
1310 buf
= current_ip_buf
;
1312 if (mpi
->type
== MP_IMGTYPE_IPB
)
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
)
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
) {
1337 mpi
->planes
[1] = dst
+ buf_height
* pitch
;
1338 mpi
->planes
[2] = mpi
->planes
[1] + buf_height
* pitch
/ 4;
1341 mpi
->planes
[2] = dst
+ buf_height
* pitch
;
1342 mpi
->planes
[1] = mpi
->planes
[2] + buf_height
* pitch
/ 4;
1346 mpi
->stride
[1] = pitch
;
1347 mpi
->planes
[1] = dst
+ buf_height
* pitch
;
1351 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
1352 mpi
->priv
= (void *) buf
;
1358 frame
->Unlock( frame
);
1366 draw_image( mp_image_t
*mpi
)
1368 if (mpi
->flags
& MP_IMGFLAG_DIRECT
) {
1369 current_buf
= (int) mpi
->priv
;
1372 if (mpi
->flags
& MP_IMGFLAG_DRAW_CALLBACK
)
1375 if (mpi
->flags
& MP_IMGFLAG_PLANAR
)
1376 return draw_slice( mpi
->planes
, mpi
->stride
,
1377 mpi
->w
, mpi
->h
, 0, 0 );
1382 if (frame
->Lock( frame
, DSLF_WRITE
, &dst
, &pitch
) != DFB_OK
)
1384 memcpy_pic( dst
, mpi
->planes
[0],
1385 mpi
->w
* (mpi
->bpp
/ 8), mpi
->h
,
1386 pitch
, mpi
->stride
[0] );
1387 frame
->Unlock( frame
);
1394 set_equalizer( char *data
, int value
)
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 */
1421 res
= crtc2
->SetColorAdjustment( crtc2
, &ca
);
1423 res
= crtc1
->SetColorAdjustment( crtc1
, &ca
);
1425 res
= bes
->SetColorAdjustment( bes
, &ca
);
1434 get_equalizer( char *data
, int *value
)
1437 DFBColorAdjustment ca
;
1438 float factor
= 200.0 / (float) 0xffff;
1440 /* Prefer CRTC2 over BES */
1442 res
= crtc2
->GetColorAdjustment( crtc2
, &ca
);
1444 res
= crtc1
->GetColorAdjustment( crtc1
, &ca
);
1446 res
= bes
->GetColorAdjustment( bes
, &ca
);
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
;
1468 control( uint32_t request
, void *data
, ... )
1471 case VOCTRL_GUISUPPORT
:
1472 case VOCTRL_GUI_NOWINDOW
:
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
:
1489 va_start( ap
, data
);
1490 value
= va_arg( ap
, int );
1493 return set_equalizer( data
, value
);
1495 case VOCTRL_GET_EQUALIZER
:
1500 va_start( ap
, data
);
1501 value
= va_arg( ap
, int* );
1504 return get_equalizer( data
, value
);
1511 #include "osdep/keycodes.h"
1514 check_events( void )
1516 DFBInputEvent event
;
1521 if (buffer
->GetEvent( buffer
, DFB_EVENT( &event
)) == DFB_OK
) {
1522 if (event
.type
== DIET_KEYPRESS
) {
1523 switch (event
.key_symbol
) {
1525 mplayer_put_key( KEY_ESC
);
1528 mplayer_put_key( KEY_PAGE_UP
);
1530 case DIKS_PAGE_DOWN
:
1531 mplayer_put_key( KEY_PAGE_DOWN
);
1533 case DIKS_CURSOR_UP
:
1534 mplayer_put_key( KEY_UP
);
1536 case DIKS_CURSOR_DOWN
:
1537 mplayer_put_key( KEY_DOWN
);
1539 case DIKS_CURSOR_LEFT
:
1540 mplayer_put_key( KEY_LEFT
);
1542 case DIKS_CURSOR_RIGHT
:
1543 mplayer_put_key( KEY_RIGHT
);
1546 mplayer_put_key( KEY_INSERT
);
1549 mplayer_put_key( KEY_DELETE
);
1552 mplayer_put_key( KEY_HOME
);
1555 mplayer_put_key( KEY_END
);
1559 mplayer_put_key( KEY_POWER
);
1562 mplayer_put_key( KEY_MENU
);
1565 mplayer_put_key( KEY_PLAY
);
1568 mplayer_put_key( KEY_STOP
);
1571 mplayer_put_key( KEY_PAUSE
);
1573 case DIKS_PLAYPAUSE
:
1574 mplayer_put_key( KEY_PLAYPAUSE
);
1577 mplayer_put_key( KEY_FORWARD
);
1580 mplayer_put_key( KEY_NEXT
);
1583 mplayer_put_key( KEY_REWIND
);
1586 mplayer_put_key( KEY_PREV
);
1588 case DIKS_VOLUME_UP
:
1589 mplayer_put_key( KEY_VOLUME_UP
);
1591 case DIKS_VOLUME_DOWN
:
1592 mplayer_put_key( KEY_VOLUME_DOWN
);
1595 mplayer_put_key( KEY_MUTE
);
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
);