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.
25 #include <directfb_version.h>
31 #include "video_out.h"
32 #include "video_out_internal.h"
33 #include "fastmemcpy.h"
38 #include "input/keycodes.h"
40 static const vo_info_t info
= {
41 "DirectFB / Matrox G200/G400/G450/G550",
43 "Ville Syrjala <syrjala@sci.fi>",
47 const LIBVO_EXTERN(dfbmga
)
49 static IDirectFB
*dfb
;
51 static IDirectFBDisplayLayer
*crtc1
;
52 static IDirectFBDisplayLayer
*bes
;
53 static IDirectFBDisplayLayer
*crtc2
;
54 static IDirectFBDisplayLayer
*spic
;
57 static int current_buf
;
58 static int current_ip_buf
;
59 static IDirectFBSurface
*bufs
[3];
61 static IDirectFBSurface
*frame
;
62 static IDirectFBSurface
*subframe
;
64 static IDirectFBSurface
*besframe
;
65 static IDirectFBSurface
*c1frame
;
66 static IDirectFBSurface
*c2frame
;
67 static IDirectFBSurface
*spicframe
;
69 static DFBSurfacePixelFormat frame_format
;
70 static DFBSurfacePixelFormat subframe_format
;
72 static DFBRectangle besrect
;
73 static DFBRectangle c1rect
;
74 static DFBRectangle c2rect
;
75 static DFBRectangle
*subrect
;
77 static IDirectFBInputDevice
*keyboard
;
78 static IDirectFBInputDevice
*remote
;
79 static IDirectFBEventBuffer
*buffer
;
90 static int use_remote
;
91 static int field_parity
;
93 static DFBDisplayLayerBufferMode buffermode
;
96 static int osd_changed
;
98 static int osd_current
;
103 static uint32_t in_width
;
104 static uint32_t in_height
;
105 static uint32_t buf_height
;
106 static uint32_t screen_width
;
107 static uint32_t screen_height
;
108 static uint32_t sub_width
;
109 static uint32_t sub_height
;
112 pixelformat_name( DFBSurfacePixelFormat format
)
138 return "Unknown pixel format";
142 static DFBSurfacePixelFormat
143 imgfmt_to_pixelformat( uint32_t format
)
151 return DSPF_ARGB1555
;
173 IDirectFBDisplayLayer
**layer
;
177 static DFBEnumerationResult
178 get_layer_by_name( DFBDisplayLayerID id
,
179 DFBDisplayLayerDescription desc
,
182 struct layer_enum
*l
= (struct layer_enum
*) data
;
184 if (!strcmp( l
->name
, desc
.name
))
185 if ((l
->res
= dfb
->GetDisplayLayer( dfb
, id
, l
->layer
)) == DFB_OK
)
186 return DFENUM_CANCEL
;
192 preinit( const char *arg
)
195 int force_input
= -1;
203 buffermode
= DLBM_TRIPLE
;
208 use_input
= !getenv( "DISPLAY" );
213 while (*vo_subdevice
!= '\0') {
214 if (!strncmp(vo_subdevice
, "bes", 3)) {
218 } else if (!strncmp(vo_subdevice
, "crtc1", 5)) {
222 } else if (!strncmp(vo_subdevice
, "crtc2", 5)) {
226 } else if (!strncmp(vo_subdevice
, "spic", 4)) {
230 } else if (!strncmp(vo_subdevice
, "input", 5)) {
231 force_input
= !opt_no
;
234 } else if (!strncmp(vo_subdevice
, "remote", 6)) {
235 use_remote
= !opt_no
;
238 } else if (!strncmp(vo_subdevice
, "buffermode=", 11)) {
244 if (!strncmp(vo_subdevice
, "single", 6)) {
245 buffermode
= DLBM_FRONTONLY
;
249 } else if (!strncmp(vo_subdevice
, "double", 6)) {
250 buffermode
= DLBM_BACKVIDEO
;
254 } else if (!strncmp(vo_subdevice
, "triple", 6)) {
255 buffermode
= DLBM_TRIPLE
;
264 } else if (!strncmp(vo_subdevice
, "fieldparity=", 12)) {
270 if (!strncmp(vo_subdevice
, "top", 3)) {
273 } else if (!strncmp(vo_subdevice
, "bottom", 6)) {
281 } else if (!strncmp(vo_subdevice
, "tvnorm=", 7)) {
287 if (!strncmp(vo_subdevice
, "pal", 3)) {
290 } else if (!strncmp(vo_subdevice
, "ntsc" , 4)) {
293 } else if (!strncmp(vo_subdevice
, "auto" , 4)) {
301 } else if (!strncmp(vo_subdevice
, "no", 2)) {
308 } else if (*vo_subdevice
== ':') {
321 mp_msg( MSGT_VO
, MSGL_ERR
,
322 "\nvo_dfbmga command line help:\n"
323 "Example: mplayer -vo dfbmga:nocrtc2:bes:buffermode=single\n"
324 "\nOptions (use 'no' prefix to disable):\n"
325 " bes Use Backend Scaler\n"
328 " spic Use hardware sub-picture for OSD\n"
329 " input Use DirectFB for keyboard input\n"
330 " remote Use DirectFB for remote control input\n"
332 " buffermode=(single|double|triple)\n"
333 " single Use single buffering\n"
334 " double Use double buffering\n"
335 " triple Use triple buffering\n"
336 " fieldparity=(top|bottom)\n"
337 " top Top field first\n"
338 " bottom Bottom field first\n"
339 " tvnorm=(pal|ntsc|auto)\n"
342 " auto Select according to FPS\n"
347 if (!use_bes
&& !use_crtc1
&& !use_crtc2
) {
348 mp_msg( MSGT_VO
, MSGL_ERR
, "vo_dfbmga: No output selected\n" );
351 if (use_bes
&& use_crtc1
) {
352 mp_msg( MSGT_VO
, MSGL_ERR
, "vo_dfbmga: Both BES and CRTC1 outputs selected\n" );
356 if ((res
= DirectFBInit( NULL
, NULL
)) != DFB_OK
) {
357 mp_msg( MSGT_VO
, MSGL_ERR
,
358 "vo_dfbmga: DirectFBInit() failed - %s\n",
359 DirectFBErrorString( res
) );
365 DirectFBSetOption( "matrox-tv-standard", "pal" );
366 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Forced TV standard to PAL\n" );
369 DirectFBSetOption( "matrox-tv-standard", "ntsc" );
370 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Forced TV standard to NTSC\n" );
374 DirectFBSetOption( "matrox-tv-standard", "ntsc" );
375 mp_msg( MSGT_VO
, MSGL_INFO
,
376 "vo_dfbmga: Selected TV standard based upon FPS: NTSC\n" );
378 DirectFBSetOption( "matrox-tv-standard", "pal" );
379 mp_msg( MSGT_VO
, MSGL_INFO
,
380 "vo_dfbmga: Selected TV standard based upon FPS: PAL\n" );
385 if ((res
= DirectFBCreate( &dfb
)) != DFB_OK
) {
386 mp_msg( MSGT_VO
, MSGL_ERR
,
387 "vo_dfbmga: DirectFBCreate() failed - %s\n",
388 DirectFBErrorString( res
) );
392 if (use_crtc1
|| use_bes
) {
393 struct layer_enum l
= {
394 "FBDev Primary Layer",
398 dfb
->EnumDisplayLayers( dfb
, get_layer_by_name
, &l
);
399 if (l
.res
!= DFB_OK
) {
400 mp_msg( MSGT_VO
, MSGL_ERR
, "vo_dfbmga: Can't get CRTC1 layer - %s\n",
401 DirectFBErrorString( l
.res
) );
405 if ((res
= crtc1
->SetCooperativeLevel( crtc1
, DLSCL_EXCLUSIVE
)) != DFB_OK
) {
406 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get exclusive access to CRTC1 layer - %s\n",
407 DirectFBErrorString( res
) );
414 if (force_input
!= -1)
415 use_input
= force_input
;
418 DFBDisplayLayerConfig dlc
;
419 DFBDisplayLayerConfigFlags failed
;
420 struct layer_enum l
= {
421 "Matrox Backend Scaler",
426 dfb
->EnumDisplayLayers( dfb
, get_layer_by_name
, &l
);
427 if (l
.res
!= DFB_OK
) {
428 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get BES layer - %s\n",
429 DirectFBErrorString( l
.res
) );
433 if ((res
= bes
->SetCooperativeLevel( bes
, DLSCL_EXCLUSIVE
)) != DFB_OK
) {
434 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get exclusive access to BES - %s\n",
435 DirectFBErrorString( res
) );
439 dlc
.flags
= DLCONF_PIXELFORMAT
;
440 dlc
.pixelformat
= DSPF_RGB16
;
441 if (bes
->TestConfiguration( bes
, &dlc
, &failed
) != DFB_OK
) {
448 struct layer_enum l
= {
449 "Matrox CRTC2 Layer",
454 dfb
->EnumDisplayLayers( dfb
, get_layer_by_name
, &l
);
455 if (l
.res
!= DFB_OK
) {
456 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get CRTC2 layer - %s\n",
457 DirectFBErrorString( l
.res
) );
461 if ((res
= crtc2
->SetCooperativeLevel( crtc2
, DLSCL_EXCLUSIVE
)) != DFB_OK
) {
462 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get exclusive access to CRTC2 - %s\n",
463 DirectFBErrorString( res
) );
469 if (use_input
|| use_remote
) {
470 if ((res
= dfb
->CreateEventBuffer( dfb
, &buffer
)) != DFB_OK
) {
471 mp_msg( MSGT_VO
, MSGL_ERR
,
472 "vo_dfbmga: Can't create event buffer - %s\n",
473 DirectFBErrorString( res
) );
480 if ((res
= dfb
->GetInputDevice( dfb
, DIDID_KEYBOARD
, &keyboard
)) != DFB_OK
) {
481 mp_msg( MSGT_VO
, MSGL_ERR
,
482 "vo_dfbmga: Can't get keyboard - %s\n",
483 DirectFBErrorString( res
) );
487 if ((res
= keyboard
->AttachEventBuffer( keyboard
, buffer
)) != DFB_OK
) {
488 mp_msg( MSGT_VO
, MSGL_ERR
,
489 "vo_dfbmga: Can't attach event buffer to keyboard - %s\n",
490 DirectFBErrorString( res
) );
496 if ((res
= dfb
->GetInputDevice( dfb
, DIDID_REMOTE
, &remote
)) != DFB_OK
) {
497 mp_msg( MSGT_VO
, MSGL_ERR
,
498 "vo_dfbmga: Can't get remote control - %s\n",
499 DirectFBErrorString( res
) );
503 if ((res
= remote
->AttachEventBuffer( remote
, buffer
)) != DFB_OK
) {
504 mp_msg( MSGT_VO
, MSGL_ERR
,
505 "vo_dfbmga: Can't attach event buffer to remote control - %s\n",
506 DirectFBErrorString( res
) );
515 static void release_config( void )
518 spicframe
->Release( spicframe
);
520 spic
->Release( spic
);
522 c2frame
->Release( c2frame
);
524 c1frame
->Release( c1frame
);
526 besframe
->Release( besframe
);
528 bufs
[0]->Release( bufs
[0] );
530 bufs
[1]->Release( bufs
[1] );
532 bufs
[2]->Release( bufs
[2] );
545 config( uint32_t width
, uint32_t height
,
546 uint32_t d_width
, uint32_t d_height
,
553 DFBDisplayLayerConfig dlc
;
554 DFBDisplayLayerConfigFlags failed
;
564 aspect_save_orig(width
, height
);
565 aspect_save_prescale(d_width
, d_height
);
567 dlc
.pixelformat
= imgfmt_to_pixelformat( format
);
570 /* Draw to a temporary surface */
571 DFBSurfaceDescription dsc
;
573 dsc
.flags
= DSDESC_WIDTH
| DSDESC_HEIGHT
|
575 dsc
.width
= (in_width
+ 15) & ~15;
576 dsc
.height
= (in_height
+ 15) & ~15;
577 dsc
.pixelformat
= dlc
.pixelformat
;
579 /* Don't waste video memory since we don't need direct stretchblit */
581 dsc
.flags
|= DSDESC_CAPS
;
582 dsc
.caps
= DSCAPS_SYSTEMONLY
;
585 for (num_bufs
= 0; num_bufs
< 3; num_bufs
++) {
586 if ((res
= dfb
->CreateSurface( dfb
, &dsc
, &bufs
[num_bufs
] )) != DFB_OK
) {
588 mp_msg( MSGT_VO
, MSGL_ERR
,
589 "vo_dfbmga: Can't create surfaces - %s!\n",
590 DirectFBErrorString( res
) );
599 buf_height
= dsc
.height
;
601 frame
->GetPixelFormat( frame
, &frame_format
);
602 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Video surface %dx%d %s\n",
604 pixelformat_name( frame_format
) );
611 aspect_save_screenres( 0x10000, 0x10000 );
612 aspect( &out_width
, &out_height
, A_ZOOM
);
613 besrect
.x
= (0x10000 - out_width
) * in_width
/ out_width
/ 2;
614 besrect
.y
= (0x10000 - out_height
) * in_height
/ out_height
/ 2;
615 besrect
.w
= in_width
;
616 besrect
.h
= in_height
;
618 dlc
.flags
= DLCONF_WIDTH
| DLCONF_HEIGHT
| DLCONF_PIXELFORMAT
| DLCONF_BUFFERMODE
;
619 dlc
.width
= besrect
.w
+ besrect
.x
* 2;
620 dlc
.height
= besrect
.h
+ besrect
.y
* 2;
621 dlc
.buffermode
= buffermode
;
623 if ((res
= bes
->TestConfiguration( bes
, &dlc
, &failed
)) != DFB_OK
) {
624 mp_msg( MSGT_VO
, MSGL_ERR
,
625 "vo_dfbmga: Invalid BES configuration - %s!\n",
626 DirectFBErrorString( res
) );
629 if ((res
= bes
->SetConfiguration( bes
, &dlc
)) != DFB_OK
) {
630 mp_msg( MSGT_VO
, MSGL_ERR
,
631 "vo_dfbmga: BES configuration failed - %s!\n",
632 DirectFBErrorString( res
) );
635 bes
->GetSurface( bes
, &besframe
);
636 besframe
->SetBlittingFlags( besframe
, DSBLIT_NOFX
);
638 bes
->SetScreenLocation( bes
, 0.0, 0.0, 1.0, 1.0 );
640 besframe
->Clear( besframe
, 0, 0, 0, 0xff );
641 besframe
->Flip( besframe
, NULL
, 0 );
642 besframe
->Clear( besframe
, 0, 0, 0, 0xff );
643 besframe
->Flip( besframe
, NULL
, 0 );
644 besframe
->Clear( besframe
, 0, 0, 0, 0xff );
646 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: BES using %s buffering\n",
647 dlc
.buffermode
== DLBM_TRIPLE
? "triple" :
648 dlc
.buffermode
== DLBM_BACKVIDEO
? "double" : "single" );
649 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: BES surface %dx%d %s\n", dlc
.width
, dlc
.height
, pixelformat_name( dlc
.pixelformat
) );
656 dlc
.flags
= DLCONF_BUFFERMODE
;
657 dlc
.buffermode
= buffermode
;
659 if ((res
= crtc1
->TestConfiguration( crtc1
, &dlc
, &failed
)) != DFB_OK
) {
660 mp_msg( MSGT_VO
, MSGL_ERR
,
661 "vo_dfbmga: Invalid CRTC1 configuration - %s!\n",
662 DirectFBErrorString( res
) );
665 if ((res
= crtc1
->SetConfiguration( crtc1
, &dlc
)) != DFB_OK
) {
666 mp_msg( MSGT_VO
, MSGL_ERR
,
667 "vo_dfbmga: CRTC1 configuration failed - %s!\n",
668 DirectFBErrorString( res
) );
671 if ((res
= crtc1
->GetConfiguration( crtc1
, &dlc
)) != DFB_OK
) {
672 mp_msg( MSGT_VO
, MSGL_ERR
,
673 "vo_dfbmga: Getting CRTC1 configuration failed - %s!\n",
674 DirectFBErrorString( res
) );
678 crtc1
->GetSurface( crtc1
, &c1frame
);
679 c1frame
->SetBlittingFlags( c1frame
, DSBLIT_NOFX
);
680 c1frame
->SetColor( c1frame
, 0, 0, 0, 0xff );
682 c1frame
->GetSize( c1frame
, &screen_width
, &screen_height
);
684 aspect_save_screenres( screen_width
, screen_height
);
685 aspect( &out_width
, &out_height
, (flags
& VOFLAG_FULLSCREEN
) ? A_ZOOM
: A_NOZOOM
);
687 if (in_width
!= out_width
|| in_height
!= out_height
)
692 c1rect
.x
= (screen_width
- out_width
) / 2;
693 c1rect
.y
= (screen_height
- out_height
) / 2;
694 c1rect
.w
= out_width
;
695 c1rect
.h
= out_height
;
697 c1frame
->Clear( c1frame
, 0, 0, 0, 0xff );
698 c1frame
->Flip( c1frame
, NULL
, 0 );
699 c1frame
->Clear( c1frame
, 0, 0, 0, 0xff );
700 c1frame
->Flip( c1frame
, NULL
, 0 );
701 c1frame
->Clear( c1frame
, 0, 0, 0, 0xff );
703 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: CRTC1 using %s buffering\n",
704 dlc
.buffermode
== DLBM_TRIPLE
? "triple" :
705 dlc
.buffermode
== DLBM_BACKVIDEO
? "double" : "single" );
706 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: CRTC1 surface %dx%d %s\n", screen_width
, screen_height
, pixelformat_name( dlc
.pixelformat
) );
713 dlc
.flags
= DLCONF_PIXELFORMAT
| DLCONF_BUFFERMODE
| DLCONF_OPTIONS
;
714 dlc
.buffermode
= buffermode
;
715 dlc
.options
= DLOP_NONE
;
717 if (field_parity
!= -1) {
718 dlc
.options
|= DLOP_FIELD_PARITY
;
720 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Field parity set to: ");
721 switch (field_parity
) {
723 mp_msg( MSGT_VO
, MSGL_INFO
, "Don't care\n");
726 mp_msg( MSGT_VO
, MSGL_INFO
, "Top field first\n");
729 mp_msg( MSGT_VO
, MSGL_INFO
, "Bottom field first\n");
733 switch (dlc
.pixelformat
) {
736 /* sub-picture supported */
741 /* Blit to YUY2/UYVY not supported */
742 dlc
.pixelformat
= DSPF_ARGB
;
746 /* sub-picture not supported */
750 if ((res
= crtc2
->TestConfiguration( crtc2
, &dlc
, &failed
)) != DFB_OK
) {
751 mp_msg( MSGT_VO
, MSGL_ERR
,
752 "vo_dfbmga: Invalid CRTC2 configuration - %s!\n",
753 DirectFBErrorString( res
) );
756 if ((res
= crtc2
->SetConfiguration( crtc2
, &dlc
)) != DFB_OK
) {
757 mp_msg( MSGT_VO
, MSGL_ERR
,
758 "vo_dfbmga: CRTC2 configuration failed - %s!\n",
759 DirectFBErrorString( res
) );
763 if (field_parity
!= -1)
764 crtc2
->SetFieldParity( crtc2
, field_parity
);
766 crtc2
->GetSurface( crtc2
, &c2frame
);
767 c2frame
->SetBlittingFlags( c2frame
, DSBLIT_NOFX
);
768 c2frame
->SetColor( c2frame
, 0, 0, 0, 0xff );
770 c2frame
->GetSize( c2frame
, &screen_width
, &screen_height
);
772 /* Don't stretch only slightly smaller videos */
773 if ((in_width
> (0.95 * screen_width
)) &&
774 (in_width
< screen_width
))
775 out_width
= in_width
;
777 out_width
= screen_width
;
778 if ((in_height
> (0.95 * screen_height
)) &&
779 (in_height
< screen_height
))
780 out_height
= in_height
;
782 out_height
= screen_height
;
784 aspect_save_screenres( out_width
, out_height
);
785 aspect( &out_width
, &out_height
, (flags
& VOFLAG_FULLSCREEN
) ? A_ZOOM
: A_NOZOOM
);
787 if (in_width
!= out_width
||
788 in_height
!= out_height
)
793 c2rect
.x
= (screen_width
- out_width
) / 2;
794 c2rect
.y
= (screen_height
- out_height
) / 2;
795 c2rect
.w
= out_width
;
796 c2rect
.h
= out_height
;
798 c2frame
->Clear( c2frame
, 0, 0, 0, 0xff );
799 c2frame
->Flip( c2frame
, NULL
, 0 );
800 c2frame
->Clear( c2frame
, 0, 0, 0, 0xff );
801 c2frame
->Flip( c2frame
, NULL
, 0 );
802 c2frame
->Clear( c2frame
, 0, 0, 0, 0xff );
804 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: CRTC2 using %s buffering\n",
805 dlc
.buffermode
== DLBM_TRIPLE
? "triple" :
806 dlc
.buffermode
== DLBM_BACKVIDEO
? "double" : "single" );
807 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: CRTC2 surface %dx%d %s\n", screen_width
, screen_height
, pixelformat_name( dlc
.pixelformat
) );
816 /* Draw OSD to sub-picture surface */
817 IDirectFBPalette
*palette
;
820 struct layer_enum l
= {
821 "Matrox CRTC2 Sub-Picture",
825 dfb
->EnumDisplayLayers( dfb
, get_layer_by_name
, &l
);
826 if (l
.res
!= DFB_OK
) {
827 mp_msg( MSGT_VO
, MSGL_ERR
, "vo_dfbmga: Can't get sub-picture layer - %s\n",
828 DirectFBErrorString( l
.res
) );
831 if ((res
= spic
->SetCooperativeLevel( spic
, DLSCL_EXCLUSIVE
)) != DFB_OK
) {
832 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get exclusive access to sub-picture - %s\n",
833 DirectFBErrorString( res
) );
837 dlc
.flags
= DLCONF_PIXELFORMAT
| DLCONF_BUFFERMODE
;
838 dlc
.pixelformat
= DSPF_ALUT44
;
839 dlc
.buffermode
= buffermode
;
840 dlc
.flags
|= DLCONF_OPTIONS
;
841 dlc
.options
= DLOP_ALPHACHANNEL
;
843 if ((res
= spic
->TestConfiguration( spic
, &dlc
, &failed
)) != DFB_OK
) {
844 mp_msg( MSGT_VO
, MSGL_ERR
,
845 "vo_dfbmga: Invalid sub-picture configuration - %s!\n",
846 DirectFBErrorString( res
) );
849 if ((res
= spic
->SetConfiguration( spic
, &dlc
)) != DFB_OK
) {
850 mp_msg( MSGT_VO
, MSGL_ERR
,
851 "vo_dfbmga: Sub-picture configuration failed - %s!\n",
852 DirectFBErrorString( res
) );
856 spic
->GetSurface( spic
, &spicframe
);
858 spicframe
->GetPalette( spicframe
, &palette
);
860 for (i
= 0; i
< 16; i
++) {
864 palette
->SetEntries( palette
, &color
, 1, i
);
866 palette
->Release( palette
);
868 spicframe
->Clear( spicframe
, 0, 0, 0, 0 );
869 spicframe
->Flip( spicframe
, NULL
, 0 );
870 spicframe
->Clear( spicframe
, 0, 0, 0, 0 );
871 spicframe
->Flip( spicframe
, NULL
, 0 );
872 spicframe
->Clear( spicframe
, 0, 0, 0, 0 );
874 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Sub-picture layer using %s buffering\n",
875 dlc
.buffermode
== DLBM_TRIPLE
? "triple" :
876 dlc
.buffermode
== DLBM_BACKVIDEO
? "double" : "single" );
878 subframe
= spicframe
;
880 } else if (use_crtc2
) {
881 /* Draw OSD to CRTC2 surface */
884 } else if (use_crtc1
) {
885 /* Draw OSD to CRTC1 surface */
889 /* Draw OSD to BES surface */
894 subframe
->GetSize( subframe
, &sub_width
, &sub_height
);
895 subframe
->GetPixelFormat( subframe
, &subframe_format
);
896 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Sub-picture surface %dx%d %s (%s)\n",
897 sub_width
, sub_height
,
898 pixelformat_name( subframe_format
),
899 use_crtc2
? (use_spic
? "Sub-picture layer" : "CRTC2") :
900 use_crtc1
? "CRTC1" : "BES" );
910 query_format( uint32_t format
)
916 if (is_g200
|| use_crtc1
)
922 if (is_g200
&& use_bes
)
933 if (use_crtc1
|| use_crtc2
)
940 return VFCAP_HWSCALE_UP
|
942 VFCAP_CSP_SUPPORTED_BY_HW
|
943 VFCAP_CSP_SUPPORTED
|
948 vo_draw_alpha_alut44( int w
, int h
,
958 for (x
= 0; x
< w
; x
++) {
960 dst
[x
] = ((255 - srca
[x
]) & 0xF0) | (src
[x
] >> 4);
969 clear_alpha( int x0
, int y0
,
972 if (use_spic
&& !flipping
&& vo_osd_changed_flag
)
973 subframe
->FillRectangle( subframe
, x0
, y0
, w
, h
);
977 draw_alpha( int x0
, int y0
,
988 if (!osd_changed
|| (!flipping
&& !vo_osd_changed_flag
))
990 osd_dirty
|= osd_current
;
992 if (x0
< subrect
->x
||
994 x0
+ w
> subrect
->x
+ subrect
->w
||
995 y0
+ h
> subrect
->y
+ subrect
->h
)
996 osd_dirty
|= osd_current
;
999 if (subframe
->Lock( subframe
, DSLF_READ
| DSLF_WRITE
, &ptr
, &pitch
) != DFB_OK
)
1003 switch (subframe_format
) {
1005 vo_draw_alpha_alut44( w
, h
, src
, srca
, stride
,
1006 dst
+ pitch
* y0
+ x0
,
1011 vo_draw_alpha_rgb32( w
, h
, src
, srca
, stride
,
1012 dst
+ pitch
* y0
+ 4 * x0
,
1016 vo_draw_alpha_rgb16( w
, h
, src
, srca
, stride
,
1017 dst
+ pitch
* y0
+ 2 * x0
,
1021 vo_draw_alpha_rgb15( w
, h
, src
, srca
, stride
,
1022 dst
+ pitch
* y0
+ 2 * x0
,
1026 vo_draw_alpha_yuy2( w
, h
, src
, srca
, stride
,
1027 dst
+ pitch
* y0
+ 2 * x0
,
1031 vo_draw_alpha_yuy2( w
, h
, src
, srca
, stride
,
1032 dst
+ pitch
* y0
+ 2 * x0
+ 1,
1039 vo_draw_alpha_yv12( w
, h
, src
, srca
, stride
,
1040 dst
+ pitch
* y0
+ x0
,
1045 subframe
->Unlock( subframe
);
1049 draw_frame( uint8_t * src
[] )
1055 draw_slice( uint8_t * src
[], int stride
[], int w
, int h
, int x
, int y
)
1061 if (frame
->Lock( frame
, DSLF_WRITE
, &ptr
, &pitch
) != DFB_OK
)
1065 memcpy_pic( dst
+ pitch
* y
+ x
, src
[0],
1066 w
, h
, pitch
, stride
[0] );
1068 dst
+= pitch
* buf_height
;
1073 if (frame_format
== DSPF_NV12
|| frame_format
== DSPF_NV21
) {
1074 memcpy_pic( dst
+ pitch
* y
+ x
, src
[1],
1075 w
, h
, pitch
, stride
[1] );
1081 if (frame_format
== DSPF_I420
)
1082 memcpy_pic( dst
+ pitch
* y
+ x
, src
[1],
1083 w
, h
, pitch
, stride
[1] );
1085 memcpy_pic( dst
+ pitch
* y
+ x
, src
[2],
1086 w
, h
, pitch
, stride
[2] );
1088 dst
+= pitch
* buf_height
/ 2;
1090 if (frame_format
== DSPF_I420
)
1091 memcpy_pic( dst
+ pitch
* y
+ x
, src
[2],
1092 w
, h
, pitch
, stride
[2] );
1094 memcpy_pic( dst
+ pitch
* y
+ x
, src
[1],
1095 w
, h
, pitch
, stride
[1] );
1098 frame
->Unlock( frame
);
1104 blit_to_screen( void )
1106 IDirectFBSurface
*blitsrc
= frame
;
1107 DFBRectangle
*srect
= NULL
;
1110 if (vo_vsync
&& !flipping
)
1111 bes
->WaitForSync( bes
);
1113 besframe
->Blit( besframe
, blitsrc
, NULL
, besrect
.x
, besrect
.y
);
1119 if (vo_vsync
&& !flipping
)
1120 crtc1
->WaitForSync( crtc1
);
1123 c1frame
->StretchBlit( c1frame
, blitsrc
, srect
, &c1rect
);
1125 c1frame
->Blit( c1frame
, blitsrc
, srect
, c1rect
.x
, c1rect
.y
);
1129 if (vo_vsync
&& !flipping
)
1130 crtc2
->WaitForSync( crtc2
);
1133 c2frame
->StretchBlit( c2frame
, blitsrc
, srect
, &c2rect
);
1135 c2frame
->Blit( c2frame
, blitsrc
, srect
, c2rect
.x
, c2rect
.y
);
1142 frame
= bufs
[current_buf
];
1143 frame
->Unlock( frame
);
1145 osd_changed
= vo_osd_changed( 0 );
1146 if (osd_dirty
& osd_current
) {
1149 subframe
->Clear( subframe
, 0, 0, 0, 0 );
1151 /* Clear black bars around the picture */
1152 subframe
->FillRectangle( subframe
,
1154 sub_width
, subrect
->y
);
1155 subframe
->FillRectangle( subframe
,
1156 0, subrect
->y
+ subrect
->h
,
1157 sub_width
, subrect
->y
);
1158 subframe
->FillRectangle( subframe
,
1160 subrect
->x
, subrect
->h
);
1161 subframe
->FillRectangle( subframe
,
1162 subrect
->x
+ subrect
->w
, subrect
->y
,
1163 subrect
->x
, subrect
->h
);
1165 osd_dirty
&= ~osd_current
;
1171 vo_remove_text( sub_width
, sub_height
, clear_alpha
);
1172 vo_draw_text( sub_width
, sub_height
, draw_alpha
);
1174 if (use_spic
&& flipping
&& osd_changed
) {
1175 subframe
->Flip( subframe
, NULL
, 0 );
1177 if (osd_current
> osd_max
)
1190 c2frame
->Flip( c2frame
, NULL
, vo_vsync
? DSFLIP_WAITFORSYNC
: DSFLIP_ONSYNC
);
1192 c1frame
->Flip( c1frame
, NULL
, vo_vsync
? DSFLIP_WAITFORSYNC
: DSFLIP_ONSYNC
);
1194 besframe
->Flip( besframe
, NULL
, vo_vsync
? DSFLIP_WAITFORSYNC
: DSFLIP_ONSYNC
);
1198 if (osd_current
> osd_max
)
1213 buffer
->Release( buffer
);
1215 remote
->Release( remote
);
1217 keyboard
->Release( keyboard
);
1219 crtc2
->Release( crtc2
);
1221 bes
->Release( bes
);
1223 crtc1
->Release( crtc1
);
1225 dfb
->Release( dfb
);
1237 get_image( mp_image_t
*mpi
)
1239 int buf
= current_buf
;
1244 if (mpi
->flags
& MP_IMGFLAG_READABLE
&&
1245 (mpi
->type
== MP_IMGTYPE_IPB
|| mpi
->type
== MP_IMGTYPE_IP
)) {
1249 current_ip_buf
^= 1;
1251 if (mpi
->type
== MP_IMGTYPE_IPB
&& num_bufs
< 3 && current_ip_buf
)
1254 buf
= current_ip_buf
;
1256 if (mpi
->type
== MP_IMGTYPE_IPB
)
1260 frame
->Unlock( frame
);
1262 /* Always use DSLF_READ to preserve system memory copy */
1263 if (frame
->Lock( frame
, DSLF_WRITE
| DSLF_READ
,
1264 &ptr
, &pitch
) != DFB_OK
)
1268 if ((mpi
->width
== pitch
) ||
1269 (mpi
->flags
& (MP_IMGFLAG_ACCEPT_STRIDE
| MP_IMGFLAG_ACCEPT_WIDTH
))) {
1271 mpi
->planes
[0] = dst
;
1272 mpi
->width
= in_width
;
1273 mpi
->stride
[0] = pitch
;
1275 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
1276 if (mpi
->num_planes
> 2) {
1277 mpi
->stride
[1] = mpi
->stride
[2] = pitch
/ 2;
1279 if (mpi
->flags
& MP_IMGFLAG_SWAPPED
) {
1281 mpi
->planes
[1] = dst
+ buf_height
* pitch
;
1282 mpi
->planes
[2] = mpi
->planes
[1] + buf_height
* pitch
/ 4;
1285 mpi
->planes
[2] = dst
+ buf_height
* pitch
;
1286 mpi
->planes
[1] = mpi
->planes
[2] + buf_height
* pitch
/ 4;
1290 mpi
->stride
[1] = pitch
;
1291 mpi
->planes
[1] = dst
+ buf_height
* pitch
;
1295 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
1296 mpi
->priv
= (void *) buf
;
1302 frame
->Unlock( frame
);
1310 draw_image( mp_image_t
*mpi
)
1312 if (mpi
->flags
& MP_IMGFLAG_DIRECT
) {
1313 current_buf
= (int) mpi
->priv
;
1316 if (mpi
->flags
& MP_IMGFLAG_DRAW_CALLBACK
)
1319 if (mpi
->flags
& MP_IMGFLAG_PLANAR
)
1320 return draw_slice( mpi
->planes
, mpi
->stride
,
1321 mpi
->w
, mpi
->h
, 0, 0 );
1326 if (frame
->Lock( frame
, DSLF_WRITE
, &dst
, &pitch
) != DFB_OK
)
1328 memcpy_pic( dst
, mpi
->planes
[0],
1329 mpi
->w
* (mpi
->bpp
/ 8), mpi
->h
,
1330 pitch
, mpi
->stride
[0] );
1331 frame
->Unlock( frame
);
1338 set_equalizer( const char *data
, int value
)
1341 DFBColorAdjustment ca
;
1342 float factor
= (float) 0xffff / 200.0;
1344 ca
.flags
= DCAF_NONE
;
1346 if (!strcasecmp( data
, "brightness" )) {
1347 ca
.flags
|= DCAF_BRIGHTNESS
;
1348 ca
.brightness
= value
* factor
+ 0x8000;
1350 if (!strcasecmp( data
, "contrast" )) {
1351 ca
.flags
|= DCAF_CONTRAST
;
1352 ca
.contrast
= value
* factor
+ 0x8000;
1354 if (!strcasecmp( data
, "hue" )) {
1355 ca
.flags
|= DCAF_HUE
;
1356 ca
.hue
= value
* factor
+ 0x8000;
1358 if (!strcasecmp( data
, "saturation" )) {
1359 ca
.flags
|= DCAF_SATURATION
;
1360 ca
.saturation
= value
* factor
+ 0x8000;
1363 /* Prefer CRTC2 over BES */
1365 res
= crtc2
->SetColorAdjustment( crtc2
, &ca
);
1367 res
= crtc1
->SetColorAdjustment( crtc1
, &ca
);
1369 res
= bes
->SetColorAdjustment( bes
, &ca
);
1378 get_equalizer( const char *data
, int *value
)
1381 DFBColorAdjustment ca
;
1382 float factor
= 200.0 / (float) 0xffff;
1384 /* Prefer CRTC2 over BES */
1386 res
= crtc2
->GetColorAdjustment( crtc2
, &ca
);
1388 res
= crtc1
->GetColorAdjustment( crtc1
, &ca
);
1390 res
= bes
->GetColorAdjustment( bes
, &ca
);
1395 if (!strcasecmp( data
, "brightness" ) &&
1396 (ca
.flags
& DCAF_BRIGHTNESS
))
1397 *value
= (ca
.brightness
- 0x8000) * factor
;
1398 if (!strcasecmp( data
, "contrast" ) &&
1399 (ca
.flags
& DCAF_CONTRAST
))
1400 *value
= (ca
.contrast
- 0x8000) * factor
;
1401 if (!strcasecmp( data
, "hue" ) &&
1402 (ca
.flags
& DCAF_HUE
))
1403 *value
= (ca
.hue
- 0x8000) * factor
;
1404 if (!strcasecmp( data
, "saturation" ) &&
1405 (ca
.flags
& DCAF_SATURATION
))
1406 *value
= (ca
.saturation
- 0x8000) * factor
;
1412 control( uint32_t request
, void *data
)
1415 case VOCTRL_QUERY_FORMAT
:
1416 return query_format( *((uint32_t *) data
) );
1418 case VOCTRL_GET_IMAGE
:
1419 return get_image( data
);
1421 case VOCTRL_DRAW_IMAGE
:
1422 return draw_image( data
);
1424 case VOCTRL_SET_EQUALIZER
:
1426 struct voctrl_set_equalizer_args
*args
= data
;
1427 return set_equalizer(args
->name
, args
->value
);
1429 case VOCTRL_GET_EQUALIZER
:
1431 struct voctrl_get_equalizer_args
*args
= data
;
1432 return get_equalizer(args
->name
, args
->valueptr
);
1440 check_events( void )
1442 DFBInputEvent event
;
1447 if (buffer
->GetEvent( buffer
, DFB_EVENT( &event
)) == DFB_OK
) {
1448 if (event
.type
== DIET_KEYPRESS
) {
1449 switch (event
.key_symbol
) {
1451 mplayer_put_key( KEY_ESC
);
1454 mplayer_put_key( KEY_PAGE_UP
);
1456 case DIKS_PAGE_DOWN
:
1457 mplayer_put_key( KEY_PAGE_DOWN
);
1459 case DIKS_CURSOR_UP
:
1460 mplayer_put_key( KEY_UP
);
1462 case DIKS_CURSOR_DOWN
:
1463 mplayer_put_key( KEY_DOWN
);
1465 case DIKS_CURSOR_LEFT
:
1466 mplayer_put_key( KEY_LEFT
);
1468 case DIKS_CURSOR_RIGHT
:
1469 mplayer_put_key( KEY_RIGHT
);
1472 mplayer_put_key( KEY_INSERT
);
1475 mplayer_put_key( KEY_DELETE
);
1478 mplayer_put_key( KEY_HOME
);
1481 mplayer_put_key( KEY_END
);
1485 mplayer_put_key( KEY_POWER
);
1488 mplayer_put_key( KEY_MENU
);
1491 mplayer_put_key( KEY_PLAY
);
1494 mplayer_put_key( KEY_STOP
);
1497 mplayer_put_key( KEY_PAUSE
);
1499 case DIKS_PLAYPAUSE
:
1500 mplayer_put_key( KEY_PLAYPAUSE
);
1503 mplayer_put_key( KEY_FORWARD
);
1506 mplayer_put_key( KEY_NEXT
);
1509 mplayer_put_key( KEY_REWIND
);
1512 mplayer_put_key( KEY_PREV
);
1514 case DIKS_VOLUME_UP
:
1515 mplayer_put_key( KEY_VOLUME_UP
);
1517 case DIKS_VOLUME_DOWN
:
1518 mplayer_put_key( KEY_VOLUME_DOWN
);
1521 mplayer_put_key( KEY_MUTE
);
1525 mplayer_put_key( event
.key_symbol
);
1531 * empty buffer, because of repeating
1532 * keyboard repeat is faster than key handling and this causes problems during seek
1533 * temporary workabout. should be solved in the future
1535 buffer
->Reset( buffer
);