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"
39 static const vo_info_t info
= {
40 "DirectFB / Matrox G200/G400/G450/G550",
42 "Ville Syrjala <syrjala@sci.fi>",
46 const LIBVO_EXTERN(dfbmga
)
48 static IDirectFB
*dfb
;
50 static IDirectFBDisplayLayer
*crtc1
;
51 static IDirectFBDisplayLayer
*bes
;
52 static IDirectFBDisplayLayer
*crtc2
;
53 static IDirectFBDisplayLayer
*spic
;
56 static int current_buf
;
57 static int current_ip_buf
;
58 static IDirectFBSurface
*bufs
[3];
60 static IDirectFBSurface
*frame
;
61 static IDirectFBSurface
*subframe
;
63 static IDirectFBSurface
*besframe
;
64 static IDirectFBSurface
*c1frame
;
65 static IDirectFBSurface
*c2frame
;
66 static IDirectFBSurface
*spicframe
;
68 static DFBSurfacePixelFormat frame_format
;
69 static DFBSurfacePixelFormat subframe_format
;
71 static DFBRectangle besrect
;
72 static DFBRectangle c1rect
;
73 static DFBRectangle c2rect
;
74 static DFBRectangle
*subrect
;
76 static IDirectFBInputDevice
*keyboard
;
77 static IDirectFBInputDevice
*remote
;
78 static IDirectFBEventBuffer
*buffer
;
89 static int use_remote
;
90 static int field_parity
;
92 static DFBDisplayLayerBufferMode buffermode
;
95 static int osd_changed
;
97 static int osd_current
;
102 static uint32_t in_width
;
103 static uint32_t in_height
;
104 static uint32_t buf_height
;
105 static uint32_t screen_width
;
106 static uint32_t screen_height
;
107 static uint32_t sub_width
;
108 static uint32_t sub_height
;
111 pixelformat_name( DFBSurfacePixelFormat format
)
137 return "Unknown pixel format";
141 static DFBSurfacePixelFormat
142 imgfmt_to_pixelformat( uint32_t format
)
150 return DSPF_ARGB1555
;
172 IDirectFBDisplayLayer
**layer
;
176 static DFBEnumerationResult
177 get_layer_by_name( DFBDisplayLayerID id
,
178 DFBDisplayLayerDescription desc
,
181 struct layer_enum
*l
= (struct layer_enum
*) data
;
183 if (!strcmp( l
->name
, desc
.name
))
184 if ((l
->res
= dfb
->GetDisplayLayer( dfb
, id
, l
->layer
)) == DFB_OK
)
185 return DFENUM_CANCEL
;
191 preinit( const char *arg
)
194 int force_input
= -1;
202 buffermode
= DLBM_TRIPLE
;
207 use_input
= !getenv( "DISPLAY" );
212 while (*vo_subdevice
!= '\0') {
213 if (!strncmp(vo_subdevice
, "bes", 3)) {
217 } else if (!strncmp(vo_subdevice
, "crtc1", 5)) {
221 } else if (!strncmp(vo_subdevice
, "crtc2", 5)) {
225 } else if (!strncmp(vo_subdevice
, "spic", 4)) {
229 } else if (!strncmp(vo_subdevice
, "input", 5)) {
230 force_input
= !opt_no
;
233 } else if (!strncmp(vo_subdevice
, "remote", 6)) {
234 use_remote
= !opt_no
;
237 } else if (!strncmp(vo_subdevice
, "buffermode=", 11)) {
243 if (!strncmp(vo_subdevice
, "single", 6)) {
244 buffermode
= DLBM_FRONTONLY
;
248 } else if (!strncmp(vo_subdevice
, "double", 6)) {
249 buffermode
= DLBM_BACKVIDEO
;
253 } else if (!strncmp(vo_subdevice
, "triple", 6)) {
254 buffermode
= DLBM_TRIPLE
;
263 } else if (!strncmp(vo_subdevice
, "fieldparity=", 12)) {
269 if (!strncmp(vo_subdevice
, "top", 3)) {
272 } else if (!strncmp(vo_subdevice
, "bottom", 6)) {
280 } else if (!strncmp(vo_subdevice
, "tvnorm=", 7)) {
286 if (!strncmp(vo_subdevice
, "pal", 3)) {
289 } else if (!strncmp(vo_subdevice
, "ntsc" , 4)) {
292 } else if (!strncmp(vo_subdevice
, "auto" , 4)) {
300 } else if (!strncmp(vo_subdevice
, "no", 2)) {
307 } else if (*vo_subdevice
== ':') {
320 mp_msg( MSGT_VO
, MSGL_ERR
,
321 "\nvo_dfbmga command line help:\n"
322 "Example: mplayer -vo dfbmga:nocrtc2:bes:buffermode=single\n"
323 "\nOptions (use 'no' prefix to disable):\n"
324 " bes Use Backend Scaler\n"
327 " spic Use hardware sub-picture for OSD\n"
328 " input Use DirectFB for keyboard input\n"
329 " remote Use DirectFB for remote control input\n"
331 " buffermode=(single|double|triple)\n"
332 " single Use single buffering\n"
333 " double Use double buffering\n"
334 " triple Use triple buffering\n"
335 " fieldparity=(top|bottom)\n"
336 " top Top field first\n"
337 " bottom Bottom field first\n"
338 " tvnorm=(pal|ntsc|auto)\n"
341 " auto Select according to FPS\n"
346 if (!use_bes
&& !use_crtc1
&& !use_crtc2
) {
347 mp_msg( MSGT_VO
, MSGL_ERR
, "vo_dfbmga: No output selected\n" );
350 if (use_bes
&& use_crtc1
) {
351 mp_msg( MSGT_VO
, MSGL_ERR
, "vo_dfbmga: Both BES and CRTC1 outputs selected\n" );
355 if ((res
= DirectFBInit( NULL
, NULL
)) != DFB_OK
) {
356 mp_msg( MSGT_VO
, MSGL_ERR
,
357 "vo_dfbmga: DirectFBInit() failed - %s\n",
358 DirectFBErrorString( res
) );
364 DirectFBSetOption( "matrox-tv-standard", "pal" );
365 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Forced TV standard to PAL\n" );
368 DirectFBSetOption( "matrox-tv-standard", "ntsc" );
369 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Forced TV standard to NTSC\n" );
373 DirectFBSetOption( "matrox-tv-standard", "ntsc" );
374 mp_msg( MSGT_VO
, MSGL_INFO
,
375 "vo_dfbmga: Selected TV standard based upon FPS: NTSC\n" );
377 DirectFBSetOption( "matrox-tv-standard", "pal" );
378 mp_msg( MSGT_VO
, MSGL_INFO
,
379 "vo_dfbmga: Selected TV standard based upon FPS: PAL\n" );
384 if ((res
= DirectFBCreate( &dfb
)) != DFB_OK
) {
385 mp_msg( MSGT_VO
, MSGL_ERR
,
386 "vo_dfbmga: DirectFBCreate() failed - %s\n",
387 DirectFBErrorString( res
) );
391 if (use_crtc1
|| use_bes
) {
392 struct layer_enum l
= {
393 "FBDev Primary Layer",
397 dfb
->EnumDisplayLayers( dfb
, get_layer_by_name
, &l
);
398 if (l
.res
!= DFB_OK
) {
399 mp_msg( MSGT_VO
, MSGL_ERR
, "vo_dfbmga: Can't get CRTC1 layer - %s\n",
400 DirectFBErrorString( l
.res
) );
404 if ((res
= crtc1
->SetCooperativeLevel( crtc1
, DLSCL_EXCLUSIVE
)) != DFB_OK
) {
405 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get exclusive access to CRTC1 layer - %s\n",
406 DirectFBErrorString( res
) );
413 if (force_input
!= -1)
414 use_input
= force_input
;
417 DFBDisplayLayerConfig dlc
;
418 DFBDisplayLayerConfigFlags failed
;
419 struct layer_enum l
= {
420 "Matrox Backend Scaler",
425 dfb
->EnumDisplayLayers( dfb
, get_layer_by_name
, &l
);
426 if (l
.res
!= DFB_OK
) {
427 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get BES layer - %s\n",
428 DirectFBErrorString( l
.res
) );
432 if ((res
= bes
->SetCooperativeLevel( bes
, DLSCL_EXCLUSIVE
)) != DFB_OK
) {
433 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get exclusive access to BES - %s\n",
434 DirectFBErrorString( res
) );
438 dlc
.flags
= DLCONF_PIXELFORMAT
;
439 dlc
.pixelformat
= DSPF_RGB16
;
440 if (bes
->TestConfiguration( bes
, &dlc
, &failed
) != DFB_OK
) {
447 struct layer_enum l
= {
448 "Matrox CRTC2 Layer",
453 dfb
->EnumDisplayLayers( dfb
, get_layer_by_name
, &l
);
454 if (l
.res
!= DFB_OK
) {
455 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get CRTC2 layer - %s\n",
456 DirectFBErrorString( l
.res
) );
460 if ((res
= crtc2
->SetCooperativeLevel( crtc2
, DLSCL_EXCLUSIVE
)) != DFB_OK
) {
461 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get exclusive access to CRTC2 - %s\n",
462 DirectFBErrorString( res
) );
468 if (use_input
|| use_remote
) {
469 if ((res
= dfb
->CreateEventBuffer( dfb
, &buffer
)) != DFB_OK
) {
470 mp_msg( MSGT_VO
, MSGL_ERR
,
471 "vo_dfbmga: Can't create event buffer - %s\n",
472 DirectFBErrorString( res
) );
479 if ((res
= dfb
->GetInputDevice( dfb
, DIDID_KEYBOARD
, &keyboard
)) != DFB_OK
) {
480 mp_msg( MSGT_VO
, MSGL_ERR
,
481 "vo_dfbmga: Can't get keyboard - %s\n",
482 DirectFBErrorString( res
) );
486 if ((res
= keyboard
->AttachEventBuffer( keyboard
, buffer
)) != DFB_OK
) {
487 mp_msg( MSGT_VO
, MSGL_ERR
,
488 "vo_dfbmga: Can't attach event buffer to keyboard - %s\n",
489 DirectFBErrorString( res
) );
495 if ((res
= dfb
->GetInputDevice( dfb
, DIDID_REMOTE
, &remote
)) != DFB_OK
) {
496 mp_msg( MSGT_VO
, MSGL_ERR
,
497 "vo_dfbmga: Can't get remote control - %s\n",
498 DirectFBErrorString( res
) );
502 if ((res
= remote
->AttachEventBuffer( remote
, buffer
)) != DFB_OK
) {
503 mp_msg( MSGT_VO
, MSGL_ERR
,
504 "vo_dfbmga: Can't attach event buffer to remote control - %s\n",
505 DirectFBErrorString( res
) );
514 static void release_config( void )
517 spicframe
->Release( spicframe
);
519 spic
->Release( spic
);
521 c2frame
->Release( c2frame
);
523 c1frame
->Release( c1frame
);
525 besframe
->Release( besframe
);
527 bufs
[0]->Release( bufs
[0] );
529 bufs
[1]->Release( bufs
[1] );
531 bufs
[2]->Release( bufs
[2] );
544 config( uint32_t width
, uint32_t height
,
545 uint32_t d_width
, uint32_t d_height
,
552 DFBDisplayLayerConfig dlc
;
553 DFBDisplayLayerConfigFlags failed
;
563 aspect_save_orig(width
, height
);
564 aspect_save_prescale(d_width
, d_height
);
566 dlc
.pixelformat
= imgfmt_to_pixelformat( format
);
569 /* Draw to a temporary surface */
570 DFBSurfaceDescription dsc
;
572 dsc
.flags
= DSDESC_WIDTH
| DSDESC_HEIGHT
|
574 dsc
.width
= (in_width
+ 15) & ~15;
575 dsc
.height
= (in_height
+ 15) & ~15;
576 dsc
.pixelformat
= dlc
.pixelformat
;
578 /* Don't waste video memory since we don't need direct stretchblit */
580 dsc
.flags
|= DSDESC_CAPS
;
581 dsc
.caps
= DSCAPS_SYSTEMONLY
;
584 for (num_bufs
= 0; num_bufs
< 3; num_bufs
++) {
585 if ((res
= dfb
->CreateSurface( dfb
, &dsc
, &bufs
[num_bufs
] )) != DFB_OK
) {
587 mp_msg( MSGT_VO
, MSGL_ERR
,
588 "vo_dfbmga: Can't create surfaces - %s!\n",
589 DirectFBErrorString( res
) );
598 buf_height
= dsc
.height
;
600 frame
->GetPixelFormat( frame
, &frame_format
);
601 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Video surface %dx%d %s\n",
603 pixelformat_name( frame_format
) );
610 aspect_save_screenres( 0x10000, 0x10000 );
611 aspect( &out_width
, &out_height
, A_ZOOM
);
612 besrect
.x
= (0x10000 - out_width
) * in_width
/ out_width
/ 2;
613 besrect
.y
= (0x10000 - out_height
) * in_height
/ out_height
/ 2;
614 besrect
.w
= in_width
;
615 besrect
.h
= in_height
;
617 dlc
.flags
= DLCONF_WIDTH
| DLCONF_HEIGHT
| DLCONF_PIXELFORMAT
| DLCONF_BUFFERMODE
;
618 dlc
.width
= besrect
.w
+ besrect
.x
* 2;
619 dlc
.height
= besrect
.h
+ besrect
.y
* 2;
620 dlc
.buffermode
= buffermode
;
622 if ((res
= bes
->TestConfiguration( bes
, &dlc
, &failed
)) != DFB_OK
) {
623 mp_msg( MSGT_VO
, MSGL_ERR
,
624 "vo_dfbmga: Invalid BES configuration - %s!\n",
625 DirectFBErrorString( res
) );
628 if ((res
= bes
->SetConfiguration( bes
, &dlc
)) != DFB_OK
) {
629 mp_msg( MSGT_VO
, MSGL_ERR
,
630 "vo_dfbmga: BES configuration failed - %s!\n",
631 DirectFBErrorString( res
) );
634 bes
->GetSurface( bes
, &besframe
);
635 besframe
->SetBlittingFlags( besframe
, DSBLIT_NOFX
);
637 bes
->SetScreenLocation( bes
, 0.0, 0.0, 1.0, 1.0 );
639 besframe
->Clear( besframe
, 0, 0, 0, 0xff );
640 besframe
->Flip( besframe
, NULL
, 0 );
641 besframe
->Clear( besframe
, 0, 0, 0, 0xff );
642 besframe
->Flip( besframe
, NULL
, 0 );
643 besframe
->Clear( besframe
, 0, 0, 0, 0xff );
645 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: BES using %s buffering\n",
646 dlc
.buffermode
== DLBM_TRIPLE
? "triple" :
647 dlc
.buffermode
== DLBM_BACKVIDEO
? "double" : "single" );
648 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: BES surface %dx%d %s\n", dlc
.width
, dlc
.height
, pixelformat_name( dlc
.pixelformat
) );
655 dlc
.flags
= DLCONF_BUFFERMODE
;
656 dlc
.buffermode
= buffermode
;
658 if ((res
= crtc1
->TestConfiguration( crtc1
, &dlc
, &failed
)) != DFB_OK
) {
659 mp_msg( MSGT_VO
, MSGL_ERR
,
660 "vo_dfbmga: Invalid CRTC1 configuration - %s!\n",
661 DirectFBErrorString( res
) );
664 if ((res
= crtc1
->SetConfiguration( crtc1
, &dlc
)) != DFB_OK
) {
665 mp_msg( MSGT_VO
, MSGL_ERR
,
666 "vo_dfbmga: CRTC1 configuration failed - %s!\n",
667 DirectFBErrorString( res
) );
670 if ((res
= crtc1
->GetConfiguration( crtc1
, &dlc
)) != DFB_OK
) {
671 mp_msg( MSGT_VO
, MSGL_ERR
,
672 "vo_dfbmga: Getting CRTC1 configuration failed - %s!\n",
673 DirectFBErrorString( res
) );
677 crtc1
->GetSurface( crtc1
, &c1frame
);
678 c1frame
->SetBlittingFlags( c1frame
, DSBLIT_NOFX
);
679 c1frame
->SetColor( c1frame
, 0, 0, 0, 0xff );
681 c1frame
->GetSize( c1frame
, &screen_width
, &screen_height
);
683 aspect_save_screenres( screen_width
, screen_height
);
684 aspect( &out_width
, &out_height
, (flags
& VOFLAG_FULLSCREEN
) ? A_ZOOM
: A_NOZOOM
);
686 if (in_width
!= out_width
|| in_height
!= out_height
)
691 c1rect
.x
= (screen_width
- out_width
) / 2;
692 c1rect
.y
= (screen_height
- out_height
) / 2;
693 c1rect
.w
= out_width
;
694 c1rect
.h
= out_height
;
696 c1frame
->Clear( c1frame
, 0, 0, 0, 0xff );
697 c1frame
->Flip( c1frame
, NULL
, 0 );
698 c1frame
->Clear( c1frame
, 0, 0, 0, 0xff );
699 c1frame
->Flip( c1frame
, NULL
, 0 );
700 c1frame
->Clear( c1frame
, 0, 0, 0, 0xff );
702 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: CRTC1 using %s buffering\n",
703 dlc
.buffermode
== DLBM_TRIPLE
? "triple" :
704 dlc
.buffermode
== DLBM_BACKVIDEO
? "double" : "single" );
705 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: CRTC1 surface %dx%d %s\n", screen_width
, screen_height
, pixelformat_name( dlc
.pixelformat
) );
712 dlc
.flags
= DLCONF_PIXELFORMAT
| DLCONF_BUFFERMODE
| DLCONF_OPTIONS
;
713 dlc
.buffermode
= buffermode
;
714 dlc
.options
= DLOP_NONE
;
716 if (field_parity
!= -1) {
717 dlc
.options
|= DLOP_FIELD_PARITY
;
719 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Field parity set to: ");
720 switch (field_parity
) {
722 mp_msg( MSGT_VO
, MSGL_INFO
, "Don't care\n");
725 mp_msg( MSGT_VO
, MSGL_INFO
, "Top field first\n");
728 mp_msg( MSGT_VO
, MSGL_INFO
, "Bottom field first\n");
732 switch (dlc
.pixelformat
) {
735 /* sub-picture supported */
740 /* Blit to YUY2/UYVY not supported */
741 dlc
.pixelformat
= DSPF_ARGB
;
745 /* sub-picture not supported */
749 if ((res
= crtc2
->TestConfiguration( crtc2
, &dlc
, &failed
)) != DFB_OK
) {
750 mp_msg( MSGT_VO
, MSGL_ERR
,
751 "vo_dfbmga: Invalid CRTC2 configuration - %s!\n",
752 DirectFBErrorString( res
) );
755 if ((res
= crtc2
->SetConfiguration( crtc2
, &dlc
)) != DFB_OK
) {
756 mp_msg( MSGT_VO
, MSGL_ERR
,
757 "vo_dfbmga: CRTC2 configuration failed - %s!\n",
758 DirectFBErrorString( res
) );
762 if (field_parity
!= -1)
763 crtc2
->SetFieldParity( crtc2
, field_parity
);
765 crtc2
->GetSurface( crtc2
, &c2frame
);
766 c2frame
->SetBlittingFlags( c2frame
, DSBLIT_NOFX
);
767 c2frame
->SetColor( c2frame
, 0, 0, 0, 0xff );
769 c2frame
->GetSize( c2frame
, &screen_width
, &screen_height
);
771 /* Don't stretch only slightly smaller videos */
772 if ((in_width
> (0.95 * screen_width
)) &&
773 (in_width
< screen_width
))
774 out_width
= in_width
;
776 out_width
= screen_width
;
777 if ((in_height
> (0.95 * screen_height
)) &&
778 (in_height
< screen_height
))
779 out_height
= in_height
;
781 out_height
= screen_height
;
783 aspect_save_screenres( out_width
, out_height
);
784 aspect( &out_width
, &out_height
, (flags
& VOFLAG_FULLSCREEN
) ? A_ZOOM
: A_NOZOOM
);
786 if (in_width
!= out_width
||
787 in_height
!= out_height
)
792 c2rect
.x
= (screen_width
- out_width
) / 2;
793 c2rect
.y
= (screen_height
- out_height
) / 2;
794 c2rect
.w
= out_width
;
795 c2rect
.h
= out_height
;
797 c2frame
->Clear( c2frame
, 0, 0, 0, 0xff );
798 c2frame
->Flip( c2frame
, NULL
, 0 );
799 c2frame
->Clear( c2frame
, 0, 0, 0, 0xff );
800 c2frame
->Flip( c2frame
, NULL
, 0 );
801 c2frame
->Clear( c2frame
, 0, 0, 0, 0xff );
803 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: CRTC2 using %s buffering\n",
804 dlc
.buffermode
== DLBM_TRIPLE
? "triple" :
805 dlc
.buffermode
== DLBM_BACKVIDEO
? "double" : "single" );
806 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: CRTC2 surface %dx%d %s\n", screen_width
, screen_height
, pixelformat_name( dlc
.pixelformat
) );
815 /* Draw OSD to sub-picture surface */
816 IDirectFBPalette
*palette
;
819 struct layer_enum l
= {
820 "Matrox CRTC2 Sub-Picture",
824 dfb
->EnumDisplayLayers( dfb
, get_layer_by_name
, &l
);
825 if (l
.res
!= DFB_OK
) {
826 mp_msg( MSGT_VO
, MSGL_ERR
, "vo_dfbmga: Can't get sub-picture layer - %s\n",
827 DirectFBErrorString( l
.res
) );
830 if ((res
= spic
->SetCooperativeLevel( spic
, DLSCL_EXCLUSIVE
)) != DFB_OK
) {
831 mp_msg( MSGT_VO
, MSGL_ERR
, "Can't get exclusive access to sub-picture - %s\n",
832 DirectFBErrorString( res
) );
836 dlc
.flags
= DLCONF_PIXELFORMAT
| DLCONF_BUFFERMODE
;
837 dlc
.pixelformat
= DSPF_ALUT44
;
838 dlc
.buffermode
= buffermode
;
839 dlc
.flags
|= DLCONF_OPTIONS
;
840 dlc
.options
= DLOP_ALPHACHANNEL
;
842 if ((res
= spic
->TestConfiguration( spic
, &dlc
, &failed
)) != DFB_OK
) {
843 mp_msg( MSGT_VO
, MSGL_ERR
,
844 "vo_dfbmga: Invalid sub-picture configuration - %s!\n",
845 DirectFBErrorString( res
) );
848 if ((res
= spic
->SetConfiguration( spic
, &dlc
)) != DFB_OK
) {
849 mp_msg( MSGT_VO
, MSGL_ERR
,
850 "vo_dfbmga: Sub-picture configuration failed - %s!\n",
851 DirectFBErrorString( res
) );
855 spic
->GetSurface( spic
, &spicframe
);
857 spicframe
->GetPalette( spicframe
, &palette
);
859 for (i
= 0; i
< 16; i
++) {
863 palette
->SetEntries( palette
, &color
, 1, i
);
865 palette
->Release( palette
);
867 spicframe
->Clear( spicframe
, 0, 0, 0, 0 );
868 spicframe
->Flip( spicframe
, NULL
, 0 );
869 spicframe
->Clear( spicframe
, 0, 0, 0, 0 );
870 spicframe
->Flip( spicframe
, NULL
, 0 );
871 spicframe
->Clear( spicframe
, 0, 0, 0, 0 );
873 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Sub-picture layer using %s buffering\n",
874 dlc
.buffermode
== DLBM_TRIPLE
? "triple" :
875 dlc
.buffermode
== DLBM_BACKVIDEO
? "double" : "single" );
877 subframe
= spicframe
;
879 } else if (use_crtc2
) {
880 /* Draw OSD to CRTC2 surface */
883 } else if (use_crtc1
) {
884 /* Draw OSD to CRTC1 surface */
888 /* Draw OSD to BES surface */
893 subframe
->GetSize( subframe
, &sub_width
, &sub_height
);
894 subframe
->GetPixelFormat( subframe
, &subframe_format
);
895 mp_msg( MSGT_VO
, MSGL_INFO
, "vo_dfbmga: Sub-picture surface %dx%d %s (%s)\n",
896 sub_width
, sub_height
,
897 pixelformat_name( subframe_format
),
898 use_crtc2
? (use_spic
? "Sub-picture layer" : "CRTC2") :
899 use_crtc1
? "CRTC1" : "BES" );
909 query_format( uint32_t format
)
915 if (is_g200
|| use_crtc1
)
921 if (is_g200
&& use_bes
)
932 if (use_crtc1
|| use_crtc2
)
939 return VFCAP_HWSCALE_UP
|
941 VFCAP_CSP_SUPPORTED_BY_HW
|
942 VFCAP_CSP_SUPPORTED
|
947 vo_draw_alpha_alut44( int w
, int h
,
957 for (x
= 0; x
< w
; x
++) {
959 dst
[x
] = ((255 - srca
[x
]) & 0xF0) | (src
[x
] >> 4);
968 clear_alpha( int x0
, int y0
,
971 if (use_spic
&& !flipping
&& vo_osd_changed_flag
)
972 subframe
->FillRectangle( subframe
, x0
, y0
, w
, h
);
976 draw_alpha( int x0
, int y0
,
987 if (!osd_changed
|| (!flipping
&& !vo_osd_changed_flag
))
989 osd_dirty
|= osd_current
;
991 if (x0
< subrect
->x
||
993 x0
+ w
> subrect
->x
+ subrect
->w
||
994 y0
+ h
> subrect
->y
+ subrect
->h
)
995 osd_dirty
|= osd_current
;
998 if (subframe
->Lock( subframe
, DSLF_READ
| DSLF_WRITE
, &ptr
, &pitch
) != DFB_OK
)
1002 switch (subframe_format
) {
1004 vo_draw_alpha_alut44( w
, h
, src
, srca
, stride
,
1005 dst
+ pitch
* y0
+ x0
,
1010 vo_draw_alpha_rgb32( w
, h
, src
, srca
, stride
,
1011 dst
+ pitch
* y0
+ 4 * x0
,
1015 vo_draw_alpha_rgb16( w
, h
, src
, srca
, stride
,
1016 dst
+ pitch
* y0
+ 2 * x0
,
1020 vo_draw_alpha_rgb15( w
, h
, src
, srca
, stride
,
1021 dst
+ pitch
* y0
+ 2 * x0
,
1025 vo_draw_alpha_yuy2( w
, h
, src
, srca
, stride
,
1026 dst
+ pitch
* y0
+ 2 * x0
,
1030 vo_draw_alpha_yuy2( w
, h
, src
, srca
, stride
,
1031 dst
+ pitch
* y0
+ 2 * x0
+ 1,
1038 vo_draw_alpha_yv12( w
, h
, src
, srca
, stride
,
1039 dst
+ pitch
* y0
+ x0
,
1044 subframe
->Unlock( subframe
);
1048 draw_frame( uint8_t * src
[] )
1054 draw_slice( uint8_t * src
[], int stride
[], int w
, int h
, int x
, int y
)
1060 if (frame
->Lock( frame
, DSLF_WRITE
, &ptr
, &pitch
) != DFB_OK
)
1064 memcpy_pic( dst
+ pitch
* y
+ x
, src
[0],
1065 w
, h
, pitch
, stride
[0] );
1067 dst
+= pitch
* buf_height
;
1072 if (frame_format
== DSPF_NV12
|| frame_format
== DSPF_NV21
) {
1073 memcpy_pic( dst
+ pitch
* y
+ x
, src
[1],
1074 w
, h
, pitch
, stride
[1] );
1080 if (frame_format
== DSPF_I420
)
1081 memcpy_pic( dst
+ pitch
* y
+ x
, src
[1],
1082 w
, h
, pitch
, stride
[1] );
1084 memcpy_pic( dst
+ pitch
* y
+ x
, src
[2],
1085 w
, h
, pitch
, stride
[2] );
1087 dst
+= pitch
* buf_height
/ 2;
1089 if (frame_format
== DSPF_I420
)
1090 memcpy_pic( dst
+ pitch
* y
+ x
, src
[2],
1091 w
, h
, pitch
, stride
[2] );
1093 memcpy_pic( dst
+ pitch
* y
+ x
, src
[1],
1094 w
, h
, pitch
, stride
[1] );
1097 frame
->Unlock( frame
);
1103 blit_to_screen( void )
1105 IDirectFBSurface
*blitsrc
= frame
;
1106 DFBRectangle
*srect
= NULL
;
1109 if (vo_vsync
&& !flipping
)
1110 bes
->WaitForSync( bes
);
1112 besframe
->Blit( besframe
, blitsrc
, NULL
, besrect
.x
, besrect
.y
);
1118 if (vo_vsync
&& !flipping
)
1119 crtc1
->WaitForSync( crtc1
);
1122 c1frame
->StretchBlit( c1frame
, blitsrc
, srect
, &c1rect
);
1124 c1frame
->Blit( c1frame
, blitsrc
, srect
, c1rect
.x
, c1rect
.y
);
1128 if (vo_vsync
&& !flipping
)
1129 crtc2
->WaitForSync( crtc2
);
1132 c2frame
->StretchBlit( c2frame
, blitsrc
, srect
, &c2rect
);
1134 c2frame
->Blit( c2frame
, blitsrc
, srect
, c2rect
.x
, c2rect
.y
);
1141 frame
= bufs
[current_buf
];
1142 frame
->Unlock( frame
);
1144 osd_changed
= vo_osd_changed( 0 );
1145 if (osd_dirty
& osd_current
) {
1148 subframe
->Clear( subframe
, 0, 0, 0, 0 );
1150 /* Clear black bars around the picture */
1151 subframe
->FillRectangle( subframe
,
1153 sub_width
, subrect
->y
);
1154 subframe
->FillRectangle( subframe
,
1155 0, subrect
->y
+ subrect
->h
,
1156 sub_width
, subrect
->y
);
1157 subframe
->FillRectangle( subframe
,
1159 subrect
->x
, subrect
->h
);
1160 subframe
->FillRectangle( subframe
,
1161 subrect
->x
+ subrect
->w
, subrect
->y
,
1162 subrect
->x
, subrect
->h
);
1164 osd_dirty
&= ~osd_current
;
1170 vo_remove_text( sub_width
, sub_height
, clear_alpha
);
1171 vo_draw_text( sub_width
, sub_height
, draw_alpha
);
1173 if (use_spic
&& flipping
&& osd_changed
) {
1174 subframe
->Flip( subframe
, NULL
, 0 );
1176 if (osd_current
> osd_max
)
1189 c2frame
->Flip( c2frame
, NULL
, vo_vsync
? DSFLIP_WAITFORSYNC
: DSFLIP_ONSYNC
);
1191 c1frame
->Flip( c1frame
, NULL
, vo_vsync
? DSFLIP_WAITFORSYNC
: DSFLIP_ONSYNC
);
1193 besframe
->Flip( besframe
, NULL
, vo_vsync
? DSFLIP_WAITFORSYNC
: DSFLIP_ONSYNC
);
1197 if (osd_current
> osd_max
)
1212 buffer
->Release( buffer
);
1214 remote
->Release( remote
);
1216 keyboard
->Release( keyboard
);
1218 crtc2
->Release( crtc2
);
1220 bes
->Release( bes
);
1222 crtc1
->Release( crtc1
);
1224 dfb
->Release( dfb
);
1236 get_image( mp_image_t
*mpi
)
1238 int buf
= current_buf
;
1243 if (mpi
->flags
& MP_IMGFLAG_READABLE
&&
1244 (mpi
->type
== MP_IMGTYPE_IPB
|| mpi
->type
== MP_IMGTYPE_IP
)) {
1248 current_ip_buf
^= 1;
1250 if (mpi
->type
== MP_IMGTYPE_IPB
&& num_bufs
< 3 && current_ip_buf
)
1253 buf
= current_ip_buf
;
1255 if (mpi
->type
== MP_IMGTYPE_IPB
)
1259 frame
->Unlock( frame
);
1261 /* Always use DSLF_READ to preserve system memory copy */
1262 if (frame
->Lock( frame
, DSLF_WRITE
| DSLF_READ
,
1263 &ptr
, &pitch
) != DFB_OK
)
1267 if ((mpi
->width
== pitch
) ||
1268 (mpi
->flags
& (MP_IMGFLAG_ACCEPT_STRIDE
| MP_IMGFLAG_ACCEPT_WIDTH
))) {
1270 mpi
->planes
[0] = dst
;
1271 mpi
->width
= in_width
;
1272 mpi
->stride
[0] = pitch
;
1274 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
1275 if (mpi
->num_planes
> 2) {
1276 mpi
->stride
[1] = mpi
->stride
[2] = pitch
/ 2;
1278 if (mpi
->flags
& MP_IMGFLAG_SWAPPED
) {
1280 mpi
->planes
[1] = dst
+ buf_height
* pitch
;
1281 mpi
->planes
[2] = mpi
->planes
[1] + buf_height
* pitch
/ 4;
1284 mpi
->planes
[2] = dst
+ buf_height
* pitch
;
1285 mpi
->planes
[1] = mpi
->planes
[2] + buf_height
* pitch
/ 4;
1289 mpi
->stride
[1] = pitch
;
1290 mpi
->planes
[1] = dst
+ buf_height
* pitch
;
1294 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
1295 mpi
->priv
= (void *) buf
;
1301 frame
->Unlock( frame
);
1309 draw_image( mp_image_t
*mpi
)
1311 if (mpi
->flags
& MP_IMGFLAG_DIRECT
) {
1312 current_buf
= (int) mpi
->priv
;
1315 if (mpi
->flags
& MP_IMGFLAG_DRAW_CALLBACK
)
1318 if (mpi
->flags
& MP_IMGFLAG_PLANAR
)
1319 return draw_slice( mpi
->planes
, mpi
->stride
,
1320 mpi
->w
, mpi
->h
, 0, 0 );
1325 if (frame
->Lock( frame
, DSLF_WRITE
, &dst
, &pitch
) != DFB_OK
)
1327 memcpy_pic( dst
, mpi
->planes
[0],
1328 mpi
->w
* (mpi
->bpp
/ 8), mpi
->h
,
1329 pitch
, mpi
->stride
[0] );
1330 frame
->Unlock( frame
);
1337 set_equalizer( char *data
, int value
)
1340 DFBColorAdjustment ca
;
1341 float factor
= (float) 0xffff / 200.0;
1343 ca
.flags
= DCAF_NONE
;
1345 if (!strcasecmp( data
, "brightness" )) {
1346 ca
.flags
|= DCAF_BRIGHTNESS
;
1347 ca
.brightness
= value
* factor
+ 0x8000;
1349 if (!strcasecmp( data
, "contrast" )) {
1350 ca
.flags
|= DCAF_CONTRAST
;
1351 ca
.contrast
= value
* factor
+ 0x8000;
1353 if (!strcasecmp( data
, "hue" )) {
1354 ca
.flags
|= DCAF_HUE
;
1355 ca
.hue
= value
* factor
+ 0x8000;
1357 if (!strcasecmp( data
, "saturation" )) {
1358 ca
.flags
|= DCAF_SATURATION
;
1359 ca
.saturation
= value
* factor
+ 0x8000;
1362 /* Prefer CRTC2 over BES */
1364 res
= crtc2
->SetColorAdjustment( crtc2
, &ca
);
1366 res
= crtc1
->SetColorAdjustment( crtc1
, &ca
);
1368 res
= bes
->SetColorAdjustment( bes
, &ca
);
1377 get_equalizer( char *data
, int *value
)
1380 DFBColorAdjustment ca
;
1381 float factor
= 200.0 / (float) 0xffff;
1383 /* Prefer CRTC2 over BES */
1385 res
= crtc2
->GetColorAdjustment( crtc2
, &ca
);
1387 res
= crtc1
->GetColorAdjustment( crtc1
, &ca
);
1389 res
= bes
->GetColorAdjustment( bes
, &ca
);
1394 if (!strcasecmp( data
, "brightness" ) &&
1395 (ca
.flags
& DCAF_BRIGHTNESS
))
1396 *value
= (ca
.brightness
- 0x8000) * factor
;
1397 if (!strcasecmp( data
, "contrast" ) &&
1398 (ca
.flags
& DCAF_CONTRAST
))
1399 *value
= (ca
.contrast
- 0x8000) * factor
;
1400 if (!strcasecmp( data
, "hue" ) &&
1401 (ca
.flags
& DCAF_HUE
))
1402 *value
= (ca
.hue
- 0x8000) * factor
;
1403 if (!strcasecmp( data
, "saturation" ) &&
1404 (ca
.flags
& DCAF_SATURATION
))
1405 *value
= (ca
.saturation
- 0x8000) * factor
;
1411 control( uint32_t request
, void *data
)
1414 case VOCTRL_QUERY_FORMAT
:
1415 return query_format( *((uint32_t *) data
) );
1417 case VOCTRL_GET_IMAGE
:
1418 return get_image( data
);
1420 case VOCTRL_DRAW_IMAGE
:
1421 return draw_image( data
);
1423 case VOCTRL_SET_EQUALIZER
:
1425 struct voctrl_set_equalizer_args
*args
= data
;
1426 return set_equalizer(args
->name
, args
->value
);
1428 case VOCTRL_GET_EQUALIZER
:
1430 struct voctrl_get_equalizer_args
*args
= data
;
1431 return get_equalizer(args
->name
, args
->valueptr
);
1438 #include "osdep/keycodes.h"
1441 check_events( void )
1443 DFBInputEvent event
;
1448 if (buffer
->GetEvent( buffer
, DFB_EVENT( &event
)) == DFB_OK
) {
1449 if (event
.type
== DIET_KEYPRESS
) {
1450 switch (event
.key_symbol
) {
1452 mplayer_put_key( KEY_ESC
);
1455 mplayer_put_key( KEY_PAGE_UP
);
1457 case DIKS_PAGE_DOWN
:
1458 mplayer_put_key( KEY_PAGE_DOWN
);
1460 case DIKS_CURSOR_UP
:
1461 mplayer_put_key( KEY_UP
);
1463 case DIKS_CURSOR_DOWN
:
1464 mplayer_put_key( KEY_DOWN
);
1466 case DIKS_CURSOR_LEFT
:
1467 mplayer_put_key( KEY_LEFT
);
1469 case DIKS_CURSOR_RIGHT
:
1470 mplayer_put_key( KEY_RIGHT
);
1473 mplayer_put_key( KEY_INSERT
);
1476 mplayer_put_key( KEY_DELETE
);
1479 mplayer_put_key( KEY_HOME
);
1482 mplayer_put_key( KEY_END
);
1486 mplayer_put_key( KEY_POWER
);
1489 mplayer_put_key( KEY_MENU
);
1492 mplayer_put_key( KEY_PLAY
);
1495 mplayer_put_key( KEY_STOP
);
1498 mplayer_put_key( KEY_PAUSE
);
1500 case DIKS_PLAYPAUSE
:
1501 mplayer_put_key( KEY_PLAYPAUSE
);
1504 mplayer_put_key( KEY_FORWARD
);
1507 mplayer_put_key( KEY_NEXT
);
1510 mplayer_put_key( KEY_REWIND
);
1513 mplayer_put_key( KEY_PREV
);
1515 case DIKS_VOLUME_UP
:
1516 mplayer_put_key( KEY_VOLUME_UP
);
1518 case DIKS_VOLUME_DOWN
:
1519 mplayer_put_key( KEY_VOLUME_DOWN
);
1522 mplayer_put_key( KEY_MUTE
);
1526 mplayer_put_key( event
.key_symbol
);
1532 * empty buffer, because of repeating
1533 * keyboard repeat is faster than key handling and this causes problems during seek
1534 * temporary workabout. should be solved in the future
1536 buffer
->Reset( buffer
);