2 * MPlayer video driver for DirectFramebuffer device
4 * copyright (C) 2002 Jiri Svoboda <Jiri.Svoboda@seznam.cz>
6 * based on vo_directfb2.c
8 * This file is part of MPlayer.
10 * MPlayer is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * MPlayer is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with MPlayer; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #define DFB_VERSION(a,b,c) (((a)<<16)|((b)<<8)|(c))
38 #include "video_out.h"
39 #include "video_out_internal.h"
40 #include "fastmemcpy.h"
44 #include "subopt-helper.h"
48 #define min(x,y) (((x)<(y))?(x):(y))
51 #if DIRECTFBVERSION > DFB_VERSION(0,9,17)
56 static const vo_info_t info
= {
57 "Direct Framebuffer Device",
59 "Jiri Svoboda Jiri.Svoboda@seznam.cz",
60 "v 2.0 (for DirectFB version >=0.9.13)"
63 const LIBVO_EXTERN(directfb
)
65 /******************************
66 * vo_directfb globals *
67 ******************************/
69 #define DFBCHECK(x...) \
75 fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
76 DirectFBErrorFatal( #x, err ); \
84 // main DirectFB handle
85 static IDirectFB
*dfb
= NULL
;
87 static IDirectFBInputDevice
*keyboard
= NULL
;
88 // A buffer for input events.
89 static IDirectFBEventBuffer
*buffer
= NULL
;
92 * filled during config
95 // handle of used layer
96 static IDirectFBDisplayLayer
*layer
= NULL
;
97 // surface of used layer
98 static IDirectFBSurface
*primary
= NULL
;
99 static int primarylocked
= 0;
100 // handle of temporary surface (if used)
101 static IDirectFBSurface
*frame
= NULL
;
102 static int framelocked
= 0;
103 // flipping mode flag (layer/surface)
104 static int flipping
= 0;
106 static int stretch
= 0;
108 static int xoffset
=0,yoffset
=0;
110 static int out_width
=0,out_height
=0;
111 // frame/primary size
112 static int width
=0,height
=0;
113 // frame primary format
114 DFBSurfacePixelFormat pixel_format
;
116 static void (*draw_alpha_p)(int w, int h, unsigned char *src,
117 unsigned char *srca, int stride, unsigned char *dst,
121 /******************************
122 * cmd line parameteres *
123 ******************************/
125 /* command line/config file options */
126 static int layer_id
= -1;
127 static int buffer_mode
= 1;
128 static int use_input
= 1;
129 static int field_parity
= -1;
131 /******************************
133 ******************************/
136 if (frame
&& framelocked
) frame
->Unlock(frame
);
137 if (primary
&& primarylocked
) primary
->Unlock(primary
);
140 static int get_parity(strarg_t
*arg
) {
141 if (strargcmp(arg
, "top") == 0)
143 if (strargcmp(arg
, "bottom") == 0)
148 static int check_parity(void *arg
) {
149 return get_parity(arg
) != -1;
152 static int get_mode(strarg_t
*arg
) {
153 if (strargcmp(arg
, "single") == 0)
155 if (strargcmp(arg
, "double") == 0)
157 if (strargcmp(arg
, "triple") == 0)
162 static int check_mode(void *arg
) {
163 return get_mode(arg
) != 0;
166 static int preinit(const char *arg
)
169 strarg_t mode_str
= {0, NULL
};
170 strarg_t par_str
= {0, NULL
};
171 strarg_t dfb_params
= {0, NULL
};
172 const opt_t subopts
[] = {
173 {"input", OPT_ARG_BOOL
, &use_input
, NULL
},
174 {"buffermode", OPT_ARG_STR
, &mode_str
, check_mode
},
175 {"fieldparity", OPT_ARG_STR
, &par_str
, check_parity
},
176 {"layer", OPT_ARG_INT
, &layer_id
, NULL
},
177 {"dfbopts", OPT_ARG_STR
, &dfb_params
, NULL
},
181 //mp_msg(MSGT_VO, MSGL_INFO,"DirectFB: Preinit entered\n");
183 if (dfb
) return 0; // we are already initialized!
186 buffer_mode
= 1 + vo_doublebuffering
; // honor -double switch
190 if (subopt_parse(arg
, subopts
) != 0) {
191 mp_msg( MSGT_VO
, MSGL_ERR
,
192 "\n-vo directfb command line help:\n"
193 "Example: mplayer -vo directfb:layer=1:buffermode=single\n"
194 "\nOptions (use 'no' prefix to disable):\n"
195 " input Use DirectFB for keyboard input\n"
198 " n=0..xx Use layer with id n for output (0=primary)\n"
199 " buffermode=(single|double|triple)\n"
200 " single Use single buffering\n"
201 " double Use double buffering\n"
202 " triple Use triple buffering\n"
203 " fieldparity=(top|bottom)\n"
204 " top Top field first\n"
205 " bottom Bottom field first\n"
207 " Specify a parameter list for DirectFB\n"
212 buffer_mode
= get_mode(&mode_str
);
214 field_parity
= get_parity(&par_str
);
217 if (dfb_params
.len
> 0)
220 char arg0
[10] = "mplayer";
221 char *arg1
= malloc(dfb_params
.len
+ 7);
227 strcpy(arg1
, "--dfb:");
228 strncat(arg1
, dfb_params
.str
, dfb_params
.len
);
234 DFBCHECK (DirectFBInit (&argc
,&a
));
239 DFBCHECK (DirectFBInit (NULL
,NULL
));
242 if (((directfb_major_version
<= 0) &&
243 (directfb_minor_version
<= 9) &&
244 (directfb_micro_version
< 13)))
246 mp_msg(MSGT_VO
, MSGL_ERR
,"DirectFB: Unsupported DirectFB version\n");
254 // uncomment this if you do not wish to create a new VT for DirectFB
255 // DFBCHECK (DirectFBSetOption ("no-vt-switch",""));
257 // uncomment this if you want to allow VT switching
258 // DFBCHECK (DirectFBSetOption ("vt-switching",""));
260 // uncomment this if you want to hide gfx cursor (req dfb >=0.9.9)
261 DFBCHECK (DirectFBSetOption ("no-cursor",""));
264 DFBCHECK (DirectFBSetOption ("bg-color","00000000"));
270 DFBCHECK (DirectFBCreate (&dfb
));
272 #if DIRECTFBVERSION < DFB_VERSION(0,9,17)
273 if (DFB_OK
!= dfb
->SetCooperativeLevel (dfb
, DFSCL_FULLSCREEN
)) {
274 mp_msg(MSGT_VO
, MSGL_WARN
,"DirectFB: Warning - cannot switch to fullscreen mode");
283 ret
= dfb
->GetInputDevice (dfb
, DIDID_KEYBOARD
, &keyboard
);
285 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Keyboard init OK\n");
288 mp_msg(MSGT_VO
, MSGL_ERR
,"DirectFB: Keyboard init FAILED\n");
294 * Create an input buffer for the keyboard.
296 if (keyboard
) DFBCHECK (keyboard
->CreateEventBuffer (keyboard
, &buffer
));
298 // just to start clean ...
299 if (buffer
) buffer
->Reset(buffer
);
301 //mp_msg(MSGT_VO, MSGL_INFO,"DirectFB: Preinit OK\n");
307 DFBSurfacePixelFormat
convformat(uint32_t format
)
309 // add more formats !!!
311 case IMGFMT_RGB32
: return DSPF_RGB32
; break;
312 case IMGFMT_BGR32
: return DSPF_RGB32
; break;
313 case IMGFMT_RGB24
: return DSPF_RGB24
; break;
314 case IMGFMT_BGR24
: return DSPF_RGB24
; break;
315 case IMGFMT_RGB16
: return DSPF_RGB16
; break;
316 case IMGFMT_BGR16
: return DSPF_RGB16
; break;
317 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
318 case IMGFMT_RGB15
: return DSPF_ARGB1555
; break;
319 case IMGFMT_BGR15
: return DSPF_ARGB1555
; break;
320 case IMGFMT_RGB12
: return DSPF_ARGB4444
; break;
321 case IMGFMT_BGR12
: return DSPF_ARGB4444
; break;
323 case IMGFMT_RGB15
: return DSPF_RGB15
; break;
324 case IMGFMT_BGR15
: return DSPF_RGB15
; break;
325 case IMGFMT_RGB12
: return DSPF_RGB12
; break;
326 case IMGFMT_BGR12
: return DSPF_RGB12
; break;
328 case IMGFMT_YUY2
: return DSPF_YUY2
; break;
329 case IMGFMT_UYVY
: return DSPF_UYVY
; break;
330 case IMGFMT_YV12
: return DSPF_YV12
; break;
331 case IMGFMT_I420
: return DSPF_I420
; break;
332 // case IMGFMT_IYUV: return DSPF_IYUV; break;
333 case IMGFMT_RGB8
: return DSPF_RGB332
; break;
334 case IMGFMT_BGR8
: return DSPF_RGB332
; break;
341 typedef struct enum1_s
{
351 DFBEnumerationResult
test_format_callback( unsigned int id
,
352 DFBDisplayLayerDescription desc
,
355 enum1_t
*params
=(enum1_t
*)data
;
356 IDirectFBDisplayLayer
*layer
;
359 if ((layer_id
== -1 )||(layer_id
== id
)) {
361 ret
= dfb
->GetDisplayLayer( dfb
, id
, &layer
);
363 DirectFBError( "dfb->GetDisplayLayer failed", ret
);
366 DFBDisplayLayerConfig dlc
;
368 if (params
->setsize
) {
369 dlc
.flags
= DLCONF_WIDTH
|DLCONF_HEIGHT
;
370 dlc
.width
= params
->width
;
371 dlc
.height
= params
->height
;
372 layer
->SetConfiguration(layer
,&dlc
);
376 dlc
.flags
= DLCONF_PIXELFORMAT
;
377 dlc
.pixelformat
= convformat(params
->format
);
379 layer
->SetOpacity(layer
,0);
381 ret
= layer
->TestConfiguration(layer
,&dlc
,NULL
);
383 layer
->Release(layer
);
385 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Test format - layer %i scale/pos %i\n",id
,(desc
.caps
& DLCAPS_SCREEN_LOCATION
));
388 // printf("Test OK\n");
389 if (params
->result
) {
390 if ((!params
->scale
) && (desc
.caps
& DLCAPS_SCREEN_LOCATION
)) {
393 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Test format - added layer %i scale/pos %i\n",id
,(desc
.caps
& DLCAPS_SCREEN_LOCATION
));
398 if (desc
.caps
& DLCAPS_SCREEN_LOCATION
) params
->scale
=1;
399 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Test format - added layer %i scale/pos %i\n",id
,(desc
.caps
& DLCAPS_SCREEN_LOCATION
));
409 static int query_format(uint32_t format
)
411 int ret
= VFCAP_CSP_SUPPORTED
|VFCAP_CSP_SUPPORTED_BY_HW
|VFCAP_OSD
; // osd should be removed the in future -> will be handled outside...
415 if (!convformat(format
)) return 0;
416 // temporarily disable YV12
417 // if (format == IMGFMT_YV12) return 0;
418 // if (format == IMGFMT_I420) return 0;
419 if (format
== IMGFMT_IYUV
) return 0;
421 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Format query: %s\n",vo_format_name(format
));
423 params
.format
=format
;
428 DFBCHECK (dfb
->EnumDisplayLayers(dfb
,test_format_callback
,¶ms
));
431 if (params
.scale
) ret
|=VFCAP_HWSCALE_UP
|VFCAP_HWSCALE_DOWN
;
438 typedef struct videomode_s
{
449 DFBEnumerationResult
video_modes_callback( int width
,int height
,int bpp
, void *data
)
451 videomode_t
*params
=(videomode_t
*)data
;
453 int overx
=0,overy
=0,closer
=0,over
=0;
456 //mp_msg(MSGT_VO, MSGL_INFO,"DirectFB: Validator entered %i %i %i\n",width,height,bpp);
458 overx
=width
-params
->out_width
;
459 overy
=height
-params
->out_height
;
461 if (!params
->width
) {
463 params
->height
=height
;
466 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Mode added %i %i %i\n",width
,height
,bpp
);
469 if ((params
->overy
<0)||(params
->overx
<0)) we_are_under
=1; // stored mode is smaller than req mode
470 if (abs(overx
*overy
)<abs(params
->overx
* params
->overy
)) closer
=1; // current mode is closer to desired res
471 if ((overx
>=0)&&(overy
>=0)) over
=1; // current mode is bigger or equaul to desired res
472 if ((closer
&& (over
|| we_are_under
)) || (we_are_under
&& over
)) {
474 params
->height
=height
;
477 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Better mode added %i %i %i\n",width
,height
,bpp
);
483 #define CONFIG_ERROR -1
485 static int config(uint32_t s_width
, uint32_t s_height
, uint32_t d_width
,
486 uint32_t d_height
, uint32_t flags
, char *title
,
495 int fs
= flags
& VOFLAG_FULLSCREEN
;
496 int vm
= flags
& VOFLAG_MODESWITCHING
;
498 DFBSurfaceDescription dsc
;
500 DFBDisplayLayerConfig dlc
;
501 DFBSurfaceCapabilities caps
;
505 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Config entered [%ix%i]\n",s_width
,s_height
);
506 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: With requested format: %s\n",vo_format_name(format
));
510 frame
->Release(frame
);
515 primary
->Release(primary
);
520 layer
->Release(layer
);
529 params
.out_width
=d_width
;
530 params
.out_height
=d_height
;
550 default: params
.bpp
=0;
553 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Config - trying to change videomode\n");
554 DFBCHECK (dfb
->EnumVideoModes(dfb
,video_modes_callback
,¶ms
));
555 ret
=dfb
->SetVideoMode(dfb
,params
.width
,params
.height
,params
.bpp
);
557 ret
=dfb
->SetVideoMode(dfb
,params
.width
,params
.height
,24);
559 ret
=dfb
->SetVideoMode(dfb
,params
.width
,params
.height
,32);
561 ret
=dfb
->SetVideoMode(dfb
,params
.width
,params
.height
,16);
563 ret
=dfb
->SetVideoMode(dfb
,params
.width
,params
.height
,8);
570 // just to be sure clear primary layer
571 #if DIRECTFBVERSION > DFB_VERSION(0,9,13)
572 ret
= dfb
->GetDisplayLayer( dfb
, DLID_PRIMARY
, &layer
);
574 ret
= layer
->GetSurface(layer
,&primary
);
576 primary
->Clear(primary
,0,0,0,0xff);
577 ret
= primary
->Flip(primary
,NULL
,0);
579 primary
->Clear(primary
,0,0,0,0xff);
581 primary
->Release(primary
);
584 layer
->Release(layer
);
591 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Config - looking for suitable layer\n");
592 params
.format
=format
;
595 params
.width
=s_width
;
596 params
.height
=s_height
;
599 DFBCHECK (dfb
->EnumDisplayLayers(dfb
,test_format_callback
,¶ms
));
601 if (!params
.result
) {
602 mp_msg(MSGT_VO
, MSGL_ERR
,"DirectFB: ConfigError - no suitable layer found\n");
603 params
.id
= DLID_PRIMARY
;
606 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Config - layer %i\n",params
.id
);
610 DFBCHECK (dfb
->GetDisplayLayer( dfb
, params
.id
, &layer
));
612 #if DIRECTFBVERSION > DFB_VERSION(0,9,16)
613 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Config - switching layer to exclusive mode\n");
614 ret
= layer
->SetCooperativeLevel (layer
, DLSCL_EXCLUSIVE
);
617 mp_msg(MSGT_VO
, MSGL_WARN
,"DirectFB: Warning - cannot switch layer to exclusive mode. This could cause\nproblems. You may need to select correct pixel format manually!\n");
618 DirectFBError("MPlayer - Switch layer to exlusive mode.",ret
);
622 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Config - changing layer configuration (size)\n");
623 dlc
.flags
= DLCONF_WIDTH
| DLCONF_HEIGHT
;
625 dlc
.height
= s_height
;
627 ret
= layer
->SetConfiguration(layer
,&dlc
);
630 mp_msg(MSGT_VO
, MSGL_ERR
,"DirectFB: ConfigError in layer configuration (size)\n");
631 DirectFBError("MPlayer - Layer size change.",ret
);
635 // look if we need to change the pixel format of the layer
636 // and just to be sure also fetch all layer properties
637 dlc
.flags
= DLCONF_PIXELFORMAT
| DLCONF_WIDTH
| DLCONF_HEIGHT
| DLCONF_OPTIONS
| DLCONF_BUFFERMODE
;
639 ret
= layer
->GetConfiguration(layer
,&dlc
);
641 dlc
.flags
= DLCONF_PIXELFORMAT
| DLCONF_WIDTH
| DLCONF_HEIGHT
;
644 mp_msg(MSGT_VO
, MSGL_WARN
,"DirectFB: Warning - could not get layer properties!\n");
646 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Layer reports format:%x\n",dlc
.pixelformat
);
649 if ((dlc
.pixelformat
!= convformat(params
.format
)) || (ret
!= DFB_OK
)) {
651 dlc
.flags
= DLCONF_PIXELFORMAT
;
652 dlc
.pixelformat
= convformat(params
.format
);
654 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Desired pixelformat: %x\n",dlc
.pixelformat
);
656 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Config - changing layer configuration (format)\n");
657 ret
= layer
->SetConfiguration(layer
,&dlc
);
661 mp_msg(MSGT_VO
, MSGL_ERR
,"DirectFB: ConfigError in layer configuration (format, flags=%x)\n",dlc
.flags
);
662 DirectFBError("MPlayer - layer pixelformat change",ret
);
664 // ugly fbdev workaround - try to switch pixelformat via videomode change
665 switch (dlc
.pixelformat
) {
667 case DSPF_RGB32
: bpp
=32;break;
668 case DSPF_RGB24
: bpp
=24;break;
669 case DSPF_RGB16
: bpp
=16;break;
670 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
671 case DSPF_ARGB1555
: bpp
=15;break;
672 case DSPF_ARGB4444
: bpp
=12; break;
674 case DSPF_RGB15
: bpp
=15;break;
675 case DSPF_RGB12
: bpp
=12; break;
677 case DSPF_RGB332
: bpp
=8;break;
680 switch (dlc
.pixelformat
) {
685 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
693 mp_msg(MSGT_VO
, MSGL_V
,"DirectFB: Trying to recover via videomode change (VM).\n");
695 dlc
.flags
= DLCONF_WIDTH
| DLCONF_HEIGHT
;
696 if (DFB_OK
==layer
->GetConfiguration(layer
,&dlc
)) {
697 // try to set videomode
698 mp_msg(MSGT_VO
, MSGL_V
,"DirectFB: Videomode %ix%i BPP %i\n",dlc
.width
,dlc
.height
,bpp
);
699 ret
= dfb
->SetVideoMode(dfb
,dlc
.width
,dlc
.height
,bpp
);
700 if (ret
) DirectFBError("MPlayer - VM - pixelformat change",ret
);
704 //get current pixel format
705 dlc
.flags
= DLCONF_PIXELFORMAT
;
706 ret
= layer
->GetConfiguration(layer
,&dlc
);
708 DirectFBError("MPlayer - VM - Layer->GetConfiguration",ret
);
710 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Layer now has pixelformat [%x]\n",dlc
.pixelformat
);
713 // check if we were succesful
714 if ((dlc
.pixelformat
!= convformat(params
.format
)) || (ret
!= DFB_OK
)) {
715 mp_msg(MSGT_VO
, MSGL_INFO
,"DirectFB: Recovery failed!.\n");
721 default: return CONFIG_ERROR
;
728 // try triple, double... buffering
730 dlc
.flags
= DLCONF_BUFFERMODE
;
732 if (buffer_mode
> 2) {
733 dlc
.buffermode
= DLBM_TRIPLE
;
734 ret
= layer
->SetConfiguration( layer
, &dlc
);
741 if (buffer_mode
> 1) {
742 dlc
.buffermode
= DLBM_BACKVIDEO
;
743 ret
= layer
->SetConfiguration( layer
, &dlc
);
745 dlc
.buffermode
= DLBM_BACKSYSTEM
;
746 ret
= layer
->SetConfiguration( layer
, &dlc
);
750 mp_msg(MSGT_VO
, MSGL_V
,"DirectFB: Double buffering is active\n");
754 mp_msg(MSGT_VO
, MSGL_V
,"DirectFB: Triple buffering is active\n");
758 #if DIRECTFBVERSION > DFB_VERSION(0,9,16)
759 if (field_parity
!= -1) {
760 dlc
.flags
= DLCONF_OPTIONS
;
761 ret
= layer
->GetConfiguration( layer
, &dlc
);
763 dlc
.options
|= DLOP_FIELD_PARITY
;
764 ret
= layer
->SetConfiguration( layer
, &dlc
);
766 layer
->SetFieldParity( layer
, field_parity
);
770 mp_msg( MSGT_VO
, MSGL_DBG2
, "DirectFB: Requested field parity: ");
771 switch (field_parity
) {
773 mp_msg( MSGT_VO
, MSGL_DBG2
, "Don't care\n");
776 mp_msg( MSGT_VO
, MSGL_DBG2
, "Top field first\n");
779 mp_msg( MSGT_VO
, MSGL_DBG2
, "Bottom field first\n");
788 ret
= layer
->GetSurface(layer
,&primary
);
791 mp_msg(MSGT_VO
, MSGL_ERR
,"DirectFB: ConfigError - could not get surface\n");
792 return CONFIG_ERROR
; // what shall we report on failure?
795 // test surface for flipping
796 DFBCHECK(primary
->GetCapabilities(primary
,&caps
));
797 #if DIRECTFBVERSION > DFB_VERSION(0,9,13)
798 primary
->Clear(primary
,0,0,0,0xff);
801 if (caps
& (DSCAPS_FLIPPING
806 ret
= primary
->Flip(primary
,NULL
,0);
809 #if DIRECTFBVERSION > DFB_VERSION(0,9,13)
810 primary
->Clear(primary
,0,0,0,0xff);
812 // if we have 3 buffers clean once more
813 if (caps
& DSCAPS_TRIPLE
) {
814 primary
->Flip(primary
,NULL
,0);
815 primary
->Clear(primary
,0,0,0,0xff);
823 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Config - flipping = %i\n",flipping
);
825 // is scale needed ? Aspect ratio and layer pos/size
829 DFBCHECK(primary
->GetSize(primary
,&width
,&height
));
831 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Config - surface size = %ix%i\n",width
,height
);
833 aspect_save_orig(s_width
,s_height
);
834 aspect_save_prescale(d_width
,d_height
);
836 aspect_save_screenres(10000,10000);
837 aspect(&out_width
,&out_height
,A_ZOOM
);
839 ret
= layer
->SetScreenLocation(layer
,(1-(float)out_width
/10000)/2,(1-(float)out_height
/10000)/2,((float)out_width
/10000),((float)out_height
/10000));
841 if (ret
) mp_msg(MSGT_VO
, MSGL_ERR
,"DirectFB: ConfigError in layer configuration (position)\n");
848 aspect_save_screenres(width
,height
);
851 aspect(&out_width
,&out_height
,A_ZOOM
);
853 aspect(&out_width
,&out_height
,A_NOZOOM
);
856 xoffset
= (width
- out_width
) / 2;
857 yoffset
= (height
- out_height
) / 2;
860 if (((s_width
==out_width
)&&(s_height
==out_height
)) || (params
.scale
)) {
867 // temporary buffer in case of not flipping or scaling
868 if ((!flipping
) || stretch
) {
870 DFBCHECK (primary
->GetPixelFormat (primary
, &dsc
.pixelformat
));
872 dsc
.flags
= DSDESC_HEIGHT
| DSDESC_PIXELFORMAT
| DSDESC_WIDTH
;
875 dsc
.height
= s_height
;
877 DFBCHECK (dfb
->CreateSurface( dfb
, &dsc
, &frame
));
878 DFBCHECK(frame
->GetSize(frame
,&width
,&height
));
879 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Frame is active.\n");
882 // get format for draw_alpha - should be removed soon - osd will be rendered outside vo driver
884 DFBCHECK (frame
->GetPixelFormat(frame
,&pixel_format
));
886 DFBCHECK (primary
->GetPixelFormat(primary
,&pixel_format
));
889 // finally turn on layer
890 layer
->SetOpacity(layer
,255);
892 //mp_msg(MSGT_VO, MSGL_INFO,"DirectFB: Config finished [%ix%i] - [%ix%i]\n",out_width,out_height,width,height);
897 #include "osdep/keycodes.h"
899 static void check_events(void)
906 //if ( mp_msg_test(MSGT_VO,MSGL_V) ) printf ("DirectFB: Check events entered\n");
907 if (buffer
->GetEvent(buffer
, DFB_EVENT (&event
)) == DFB_OK
) {
909 if (event
.type
== DIET_KEYPRESS
) {
910 switch (event
.key_symbol
) {
912 mplayer_put_key(KEY_ESC
);
914 case DIKS_PAGE_UP
: mplayer_put_key(KEY_PAGE_UP
);break;
915 case DIKS_PAGE_DOWN
: mplayer_put_key(KEY_PAGE_DOWN
);break;
916 case DIKS_CURSOR_UP
: mplayer_put_key(KEY_UP
);break;
917 case DIKS_CURSOR_DOWN
: mplayer_put_key(KEY_DOWN
);break;
918 case DIKS_CURSOR_LEFT
: mplayer_put_key(KEY_LEFT
);break;
919 case DIKS_CURSOR_RIGHT
: mplayer_put_key(KEY_RIGHT
);break;
920 case DIKS_INSERT
: mplayer_put_key(KEY_INSERT
);break;
921 case DIKS_DELETE
: mplayer_put_key(KEY_DELETE
);break;
922 case DIKS_HOME
: mplayer_put_key(KEY_HOME
);break;
923 case DIKS_END
: mplayer_put_key(KEY_END
);break;
925 default:mplayer_put_key(event
.key_symbol
);
929 // empty buffer, because of repeating (keyboard repeat is faster than key handling
930 // and this causes problems during seek)
931 // temporary workaround should be solved in the future
932 buffer
->Reset(buffer
);
935 //if ( mp_msg_test(MSGT_VO,MSGL_V) ) printf ("DirectFB: Check events finished\n");
938 static void flip_page(void)
940 DFBSurfaceBlittingFlags flags
=DSBLIT_NOFX
;
942 unlock(); // unlock frame & primary
944 // if ( mp_msg_test(MSGT_VO,MSGL_V) ) printf("DirectFB: Flip page entered");
946 DFBCHECK (primary
->SetBlittingFlags(primary
,flags
));
956 DFBCHECK (primary
->StretchBlit(primary
,frame
,NULL
,&rect
));
960 DFBCHECK (primary
->Blit(primary
,frame
,NULL
,xoffset
,yoffset
));
968 case 1: DFBCHECK (primary
->Flip (primary
, NULL
, DSFLIP_WAIT
));
970 case 2: DFBCHECK (primary
->Flip (primary
, NULL
, DSFLIP_ONSYNC
));
972 default:; // should never be reached
976 DFBCHECK (primary
->Flip (primary
, NULL
, DSFLIP_WAITFORSYNC
));
984 static void uninit(void)
987 //mp_msg(MSGT_VO, MSGL_INFO,"DirectFB: Uninit entered\n");
995 mp_msg(MSGT_VO, MSGL_INFO,"DirectFB: Releasing buffer\n");
996 if (buffer) buffer->Release (buffer);
997 mp_msg(MSGT_VO, MSGL_INFO,"DirectFB: Releasing keyboard\n");
998 if (keyboard) keyboard->Release (keyboard);
1001 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Releasing frame\n");
1002 frame
->Release (frame
);
1007 // if (layer) layer->SetOpacity(layer,0);
1010 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Releasing layer\n");
1011 layer
->Release(layer
);
1016 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: Releasing primary\n");
1017 primary
->Release (primary
);
1022 /* mp_msg(MSGT_VO, MSGL_INFO,"DirectFB: Releasing DirectFB library\n");
1026 //mp_msg(MSGT_VO, MSGL_INFO,"DirectFB: Uninit done.\n");
1030 static uint32_t directfb_set_video_eq(char *data
, int value
) //data==name
1033 DFBColorAdjustment ca
;
1034 float factor
= (float)0xffff / 200.0;
1036 DFBDisplayLayerDescription desc
;
1042 layer
->GetDescription(layer
,&desc
);
1046 if (! strcmp( data
,"brightness" )) {
1047 if (desc
.caps
& DLCAPS_BRIGHTNESS
) {
1048 ca
.brightness
= value
* factor
+0x8000;
1049 ca
.flags
|= DCAF_BRIGHTNESS
;
1050 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: SetVEq Brightness 0x%X %i\n",ca
.brightness
,value
);
1051 } else return VO_FALSE
;
1054 if (! strcmp( data
,"contrast" )) {
1055 if ((desc
.caps
& DLCAPS_CONTRAST
)) {
1056 ca
.contrast
= value
* factor
+ 0x8000;
1057 ca
.flags
|= DCAF_CONTRAST
;
1058 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: SetVEq Contrast 0x%X %i\n",ca
.contrast
,value
);
1059 } else return VO_FALSE
;
1062 if (! strcmp( data
,"hue" )) {
1063 if ((desc
.caps
& DLCAPS_HUE
)) {
1064 ca
.hue
= value
* factor
+ 0x8000;
1065 ca
.flags
|= DCAF_HUE
;
1066 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: SetVEq Hue 0x%X %i\n",ca
.hue
,value
);
1067 } else return VO_FALSE
;
1070 if (! strcmp( data
,"saturation" )) {
1071 if ((desc
.caps
& DLCAPS_SATURATION
)) {
1072 ca
.saturation
= value
* factor
+ 0x8000;
1073 ca
.flags
|= DCAF_SATURATION
;
1074 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: SetVEq Saturation 0x%X %i\n",ca
.saturation
,value
);
1075 } else return VO_FALSE
;
1078 if (ca
.flags
!= DCAF_NONE
) {
1079 layer
->SetColorAdjustment(layer
,&ca
);
1088 static uint32_t directfb_get_video_eq(char *data
, int *value
) // data==name
1091 DFBColorAdjustment ca
;
1092 float factor
= 200.0 / (float)0xffff;
1094 DFBDisplayLayerDescription desc
;
1100 layer
->GetDescription(layer
,&desc
);
1102 layer
->GetColorAdjustment(layer
,&ca
);
1104 if (! strcmp( data
,"brightness" )) {
1105 if (desc
.caps
& DLCAPS_BRIGHTNESS
) {
1106 *value
= (int) ((ca
.brightness
-0x8000) * factor
);
1107 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: GetVEq Brightness 0x%X %i\n",ca
.brightness
,*value
);
1109 } else return VO_FALSE
;
1112 if (! strcmp( data
,"contrast" )) {
1113 if ((desc
.caps
& DLCAPS_CONTRAST
)) {
1114 *value
= (int) ((ca
.contrast
-0x8000) * factor
);
1115 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: GetVEq Contrast 0x%X %i\n",ca
.contrast
,*value
);
1117 } else return VO_FALSE
;
1120 if (! strcmp( data
,"hue" )) {
1121 if ((desc
.caps
& DLCAPS_HUE
)) {
1122 *value
= (int) ((ca
.hue
-0x8000) * factor
);
1123 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: GetVEq Hue 0x%X %i\n",ca
.hue
,*value
);
1125 } else return VO_FALSE
;
1128 if (! strcmp( data
,"saturation" )) {
1129 if ((desc
.caps
& DLCAPS_SATURATION
)) {
1130 *value
= (int) ((ca
.saturation
-0x8000) * factor
);
1131 mp_msg(MSGT_VO
, MSGL_DBG2
,"DirectFB: GetVEq Saturation 0x%X %i\n",ca
.saturation
,*value
);
1133 } else return VO_FALSE
;
1139 static uint32_t get_image(mp_image_t
*mpi
)
1146 // if ( mp_msg_test(MSGT_VO,MSGL_V) ) printf("DirectFB: get_image() called\n");
1147 if(mpi
->flags
&MP_IMGFLAG_READABLE
) return VO_FALSE
; // slow video ram
1148 if(mpi
->type
==MP_IMGTYPE_STATIC
) return VO_FALSE
; // it is not static
1150 // printf("width=%d vs. pitch=%d, flags=0x%X \n",mpi->width,pitch,mpi->flags);
1152 if(mpi
->flags
&(MP_IMGFLAG_ACCEPT_STRIDE
|MP_IMGFLAG_ACCEPT_WIDTH
)){
1153 // we're lucky or codec accepts stride => ok, let's go!
1156 err
= frame
->Lock(frame
,DSLF_WRITE
|DSLF_READ
,(void *)&dst
,&pitch
);
1159 err
= primary
->Lock(primary
,DSLF_WRITE
,(void *)&dst
,&pitch
);
1164 mp_msg(MSGT_VO
, MSGL_ERR
,"DirectFB: DR lock failed!");
1168 if(mpi
->flags
&MP_IMGFLAG_PLANAR
){
1171 if(mpi
->flags
&MP_IMGFLAG_SWAPPED
){
1172 mpi
->planes
[1]=dst
+ pitch
*height
;
1173 mpi
->planes
[2]=mpi
->planes
[1] + pitch
*height
/4;
1175 mpi
->planes
[2]=dst
+ pitch
*height
;
1176 mpi
->planes
[1]=mpi
->planes
[2] + pitch
*height
/4;
1179 mpi
->stride
[0]=pitch
;
1180 mpi
->stride
[1]=mpi
->stride
[2]=pitch
/2;
1182 //YUY2 and RGB formats
1185 mpi
->stride
[0]=pitch
;
1191 if(mpi
->flags
&MP_IMGFLAG_PLANAR
){
1192 mpi
->planes
[0]= dst
+ yoffset
* pitch
+ xoffset
;
1193 mpi
->planes
[1]+= ((yoffset
* pitch
) >> 2) + (xoffset
>> 1);
1194 mpi
->planes
[2]+= ((yoffset
* pitch
) >> 2) + (xoffset
>> 1);
1196 mpi
->planes
[0]=dst
+ yoffset
* pitch
+ xoffset
* (mpi
->bpp
>> 3);
1200 mpi
->flags
|=MP_IMGFLAG_DIRECT
;
1201 // if ( mp_msg_test(MSGT_VO,MSGL_V) ) printf("DirectFB: get_image() SUCCESS -> Direct Rendering ENABLED\n");
1208 static int draw_slice(uint8_t *src
[], int stride
[], int w
, int h
, int x
, int y
)
1217 // if ( mp_msg_test(MSGT_VO,MSGL_V) ) printf("DirectFB: draw_slice entered\n");
1222 DFBCHECK (frame
->Lock(frame
,DSLF_WRITE
|DSLF_READ
,(void *)&dst
,&pitch
));
1225 DFBCHECK (primary
->Lock(primary
,DSLF_WRITE
,(void *)&dst
,&pitch
));
1232 dst2
= dst
+ pitch
*height
- y
*pitch
+ y
*pitch
/4 - x
/2;
1236 fast_memcpy(dst
,srcp
,p
);
1241 if (pixel_format
== DSPF_YV12
) {
1247 for (i
=0;i
<h
/2;i
++) {
1248 fast_memcpy(dst
,srcp
,p
);
1253 dst
= dst2
+ pitch
*height
/4;
1256 for (i
=0;i
<h
/2;i
++) {
1257 fast_memcpy(dst
,srcp
,p
);
1268 for (i
=0;i
<h
/2;i
++) {
1269 fast_memcpy(dst
,srcp
,p
);
1274 dst
= dst2
+ pitch
*height
/4;
1277 for (i
=0;i
<h
/2;i
++) {
1278 fast_memcpy(dst
,srcp
,p
);
1291 static uint32_t put_image(mp_image_t
*mpi
){
1294 // static IDirectFBSurface *tmp = NULL;
1295 // DFBSurfaceDescription dsc;
1296 // DFBRectangle rect;
1298 // if ( mp_msg_test(MSGT_VO,MSGL_V) ) printf("DirectFB: Put_image entered %i %i %i %i %i %i\n",mpi->x,mpi->y,mpi->w,mpi->h,mpi->width,mpi->height);
1303 if((mpi
->flags
&(MP_IMGFLAG_DIRECT
|MP_IMGFLAG_DRAW_CALLBACK
))) {
1304 // if ( mp_msg_test(MSGT_VO,MSGL_V) ) printf("DirectFB: Put_image - nothing to do\n");
1308 if (mpi
->flags
&MP_IMGFLAG_PLANAR
) {
1309 // memcpy all planes - sad but necessary
1316 // if ( mp_msg_test(MSGT_VO,MSGL_V) ) printf("DirectFB: Put_image - planar branch\n");
1318 DFBCHECK (frame
->Lock(frame
,DSLF_WRITE
|DSLF_READ
,(void *)&dst
,&pitch
));
1321 DFBCHECK (primary
->Lock(primary
,DSLF_WRITE
,(void *)&dst
,&pitch
));
1325 p
=min(mpi
->w
,pitch
);
1327 src
= mpi
->planes
[0]+mpi
->y
*mpi
->stride
[0]+mpi
->x
;
1329 for (i
=0;i
<mpi
->h
;i
++) {
1330 fast_memcpy(dst
+i
*pitch
,src
+i
*mpi
->stride
[0],p
);
1334 if (pixel_format
== DSPF_YV12
) {
1336 dst
+= pitch
*height
;
1338 src
= mpi
->planes
[2]+mpi
->y
*mpi
->stride
[2]+mpi
->x
/2;
1340 for (i
=0;i
<mpi
->h
/2;i
++) {
1341 fast_memcpy(dst
+i
*pitch
/2,src
+i
*mpi
->stride
[2],p
);
1344 dst
+= pitch
*height
/4;
1345 src
= mpi
->planes
[1]+mpi
->y
*mpi
->stride
[1]+mpi
->x
/2;
1347 for (i
=0;i
<mpi
->h
/2;i
++) {
1348 fast_memcpy(dst
+i
*pitch
/2,src
+i
*mpi
->stride
[1],p
);
1353 dst
+= pitch
*height
;
1355 src
= mpi
->planes
[1]+mpi
->y
*mpi
->stride
[1]+mpi
->x
/2;
1357 for (i
=0;i
<mpi
->h
/2;i
++) {
1358 fast_memcpy(dst
+i
*pitch
/2,src
+i
*mpi
->stride
[1],p
);
1361 dst
+= pitch
*height
/4;
1362 src
= mpi
->planes
[2]+mpi
->y
*mpi
->stride
[2]+mpi
->x
/2;
1364 for (i
=0;i
<mpi
->h
/2;i
++) {
1365 fast_memcpy(dst
+i
*pitch
/2,src
+i
*mpi
->stride
[2],p
);
1372 // I had to disable native directfb blit because it wasn't working under some conditions :-(
1375 dsc.flags = DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_WIDTH | DSDESC_PREALLOCATED;
1376 dsc.preallocated[0].data = mpi->planes[0];
1377 dsc.preallocated[0].pitch = mpi->stride[0];
1378 dsc.width = mpi->width;
1379 dsc.height = mpi->height;
1380 dsc.pixelformat = convformat(mpi->imgfmt);
1382 DFBCHECK (dfb->CreateSurface( dfb, &dsc, &tmp));
1390 DFBCHECK (tmp->Blit(tmp,frame,&rect,0,0));
1392 DFBCHECK (tmp->Blit(tmp,primary,&rect,xoffset,yoffset));
1400 // if ( mp_msg_test(MSGT_VO,MSGL_V) ) printf("DirectFB: Put_image - non-planar branch\n");
1402 DFBCHECK (frame
->Lock(frame
,DSLF_WRITE
,(void *)&dst
,&pitch
));
1404 mem2agpcpy_pic(dst
,mpi
->planes
[0] + mpi
->y
* mpi
->stride
[0] + mpi
->x
* (mpi
->bpp
>> 3) ,mpi
->w
* (mpi
->bpp
>> 3),mpi
->h
,pitch
,mpi
->stride
[0]);
1406 DFBCHECK (primary
->Lock(primary
,DSLF_WRITE
,(void *)&dst
,&pitch
));
1408 mem2agpcpy_pic(dst
+ yoffset
* pitch
+ xoffset
* (mpi
->bpp
>> 3),mpi
->planes
[0] + mpi
->y
* mpi
->stride
[0] + mpi
->x
* (mpi
->bpp
>> 3) ,mpi
->w
* (mpi
->bpp
>> 3),mpi
->h
,pitch
,mpi
->stride
[0]);
1418 static int control(uint32_t request
, void *data
)
1421 case VOCTRL_QUERY_FORMAT
:
1422 return query_format(*((uint32_t*)data
));
1423 case VOCTRL_GET_IMAGE
:
1424 return get_image(data
);
1425 case VOCTRL_DRAW_IMAGE
:
1426 return put_image(data
);
1427 case VOCTRL_SET_EQUALIZER
:
1429 struct voctrl_set_equalizer_args
*args
= data
;
1430 return directfb_set_video_eq(args
->name
, args
->value
);
1432 case VOCTRL_GET_EQUALIZER
:
1434 struct voctrl_get_equalizer_args
*args
= data
;
1435 return directfb_get_video_eq(args
->name
, args
->valueptr
);
1443 static int draw_frame(uint8_t *src
[])
1448 // hopefully will be removed soon
1450 static void draw_alpha(int x0
, int y0
, int w
, int h
, unsigned char *src
,
1451 unsigned char *srca
, int stride
)
1456 unlock(); // isn't it silly I have to unlock surface and then lock it again :-)
1459 DFBCHECK (frame
->Lock(frame
,DSLF_WRITE
|DSLF_READ
,&dst
,&pitch
));
1462 DFBCHECK (primary
->Lock(primary
,DSLF_WRITE
,&dst
,&pitch
));
1466 switch(pixel_format
) {
1469 vo_draw_alpha_rgb32(w
,h
,src
,srca
,stride
,((uint8_t *) dst
)+pitch
*y0
+ 4*x0
,pitch
);
1473 vo_draw_alpha_rgb24(w
,h
,src
,srca
,stride
,((uint8_t *) dst
)+pitch
*y0
+ 3*x0
,pitch
);
1477 vo_draw_alpha_rgb16(w
,h
,src
,srca
,stride
,((uint8_t *) dst
)+pitch
*y0
+ 2*x0
,pitch
);
1479 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
1484 vo_draw_alpha_rgb15(w
,h
,src
,srca
,stride
,((uint8_t *) dst
)+pitch
*y0
+ 2*x0
,pitch
);
1486 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
1491 vo_draw_alpha_rgb12(w
, h
, src
, srca
, stride
,
1492 ((uint8_t *) dst
) + pitch
* y0
+ 2 * x0
,
1497 vo_draw_alpha_yuy2(w
,h
,src
,srca
,stride
,((uint8_t *) dst
) + pitch
*y0
+ 2*x0
,pitch
);
1501 vo_draw_alpha_yuy2(w
,h
,src
,srca
,stride
,((uint8_t *) dst
) + pitch
*y0
+ 2*x0
+ 1,pitch
);
1506 vo_draw_alpha_yv12(w
,h
,src
,srca
,stride
,((uint8_t *) dst
) + pitch
*y0
+ 1*x0
,pitch
);
1513 static void draw_osd(void)
1515 vo_draw_text(width
,height
,draw_alpha
);