2 * XOver a general x11 vo for MPlayer overlay drivers based on:
3 * VIDIX-accelerated overlay in an X window
5 * copyright (C) Alex Beregszaszi & Zoltan Ponekker & Nick Kurshev
7 * WS window manager by Pontscho/Fresh!
9 * based on vo_gl.c and vo_vesa.c and vo_xmga.c (.so mastah! ;))
11 * This file is part of MPlayer.
13 * MPlayer is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * MPlayer is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License along
24 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
36 #include "video_out.h"
37 #include "video_out_internal.h"
40 #include <X11/Xutil.h>
41 //#include <X11/keysym.h>
43 #ifdef CONFIG_XINERAMA
44 #include <X11/extensions/Xinerama.h>
47 #include "x11_common.h"
52 #include "gui/interface.h"
56 static const vo_info_t info
=
58 "General X11 driver for overlay capable video output drivers",
66 #define UNUSED(x) ((void)(x)) /* Removes warning about unused arguments */
68 /* X11 related variables */
69 /* Colorkey handling */
72 /* Image parameters */
73 static uint32_t image_width
;
74 static uint32_t image_height
;
75 static uint32_t image_format
;
77 /* Window parameters */
78 static uint32_t window_x
, window_y
;
79 static uint32_t window_width
, window_height
;
81 /* used by XGetGeometry & XTranslateCoordinates for moving/resizing window */
82 static uint32_t drwX
, drwY
, drwWidth
, drwHeight
, drwBorderWidth
,
83 drwDepth
, drwcX
, drwcY
, dwidth
, dheight
;
85 static const vo_functions_t
* sub_vo
= NULL
;
88 static void set_window(int force_update
)
93 XGetGeometry(mDisplay
, vo_window
, &mRoot
, &drwX
, &drwY
, &drwWidth
,
94 &drwHeight
, &drwBorderWidth
, &drwDepth
);
97 XTranslateCoordinates(mDisplay
, vo_window
, mRoot
, 0, 0,
98 &drwcX
, &drwcY
, &mRoot
);
99 aspect(&dwidth
,&dheight
,A_NOZOOM
);
101 mp_msg(MSGT_VO
, MSGL_V
, "[xvidix] dcx: %d dcy: %d dx: %d dy: %d dw: %d dh: %d\n",
102 drwcX
, drwcY
, drwX
, drwY
, drwWidth
, drwHeight
);
104 /* following stuff copied from vo_xmga.c */
108 aspect(&dwidth
,&dheight
,A_NOZOOM
);
109 drwcX
=drwX
=vo_dx
; drwcY
=drwY
=vo_dy
; drwWidth
=vo_dwidth
; drwHeight
=vo_dheight
;
115 aspect(&dwidth
,&dheight
,A_ZOOM
);
116 drwX
= (vo_screenwidth
- ((int)dwidth
> vo_screenwidth
? vo_screenwidth
: dwidth
)) / 2;
118 drwY
= (vo_screenheight
- ((int)dheight
> vo_screenheight
? vo_screenheight
: dheight
)) / 2;
120 drwWidth
= ((int)dwidth
> vo_screenwidth
? vo_screenwidth
: dwidth
);
121 drwHeight
= ((int)dheight
> vo_screenheight
? vo_screenheight
: dheight
);
122 mp_msg(MSGT_VO
, MSGL_V
, "[xvidix-fs] dcx: %d dcy: %d dx: %d dy: %d dw: %d dh: %d\n",
123 drwcX
, drwcY
, drwX
, drwY
, drwWidth
, drwHeight
);
127 vo_dwidth
=drwWidth
; vo_dheight
=drwHeight
;
129 #ifdef CONFIG_XINERAMA
130 if (XineramaIsActive(mDisplay
))
132 XineramaScreenInfo
*screens
;
136 screens
= XineramaQueryScreens(mDisplay
, &num_screens
);
138 /* find the screen we are on */
139 while (i
<num_screens
&&
140 ((screens
[i
].x_org
< (int)drwcX
) ||
141 (screens
[i
].y_org
< (int)drwcY
) ||
142 (screens
[i
].x_org
+ screens
[i
].width
>= (int)drwcX
) ||
143 (screens
[i
].y_org
+ screens
[i
].height
>= (int)drwcY
)))
150 /* save the screen we are on */
153 /* oops.. couldnt find the screen we are on
154 * because the upper left corner left the
155 * visual range. assume we are still on the
161 /* set drwcX and drwcY to the right values */
162 drwcX
= drwcX
- screens
[i
].x_org
;
163 drwcY
= drwcY
- screens
[i
].y_org
;
168 if ( vo_panscan
> 0.0f
&& vo_fs
)
170 drwcX
-=vo_panscan_x
>> 1;
171 drwcY
-=vo_panscan_y
>> 1;
172 drwX
-=vo_panscan_x
>> 1;
173 drwY
-=vo_panscan_y
>> 1;
174 drwWidth
+=vo_panscan_x
;
175 drwHeight
+=vo_panscan_y
;
178 /* set new values in VIDIX */
179 if (force_update
|| (window_x
!= drwcX
) || (window_y
!= drwcY
) ||
180 (window_width
!= drwWidth
) || (window_height
!= drwHeight
))
183 // do a backup of window coordinates
184 w
.x
= window_x
= drwcX
;
185 w
.y
= window_y
= drwcY
;
188 w
.w
= window_width
= drwWidth
;
189 w
.h
= window_height
= drwHeight
;
191 if(sub_vo
->control(VOCTRL_XOVERLAY_SET_WIN
,&w
) != VO_TRUE
)
192 mp_msg(MSGT_VO
, MSGL_ERR
, "xvidx: set_overlay failed\n");
194 mp_msg(MSGT_VO
, MSGL_V
, "[xvidix] window properties: pos: %dx%d, size: %dx%d\n", vo_dx
, vo_dy
, window_width
, window_height
);
199 /* fill drawable with specified color */
200 XSetBackground(mDisplay
, vo_gc
, 0L);
201 XClearWindow( mDisplay
,vo_window
);
202 XSetForeground(mDisplay
, vo_gc
, colorkey
);
203 XFillRectangle(mDisplay
, vo_window
, vo_gc
, drwX
, drwY
, drwWidth
,
204 (vo_fs
? drwHeight
- 1 : drwHeight
));
206 /* flush, update drawable */
212 /* connect to server, create and map window,
213 * allocate colors and (shared) memory
215 static int config(uint32_t width
, uint32_t height
, uint32_t d_width
,
216 uint32_t d_height
, uint32_t flags
, char *title
, uint32_t format
)
220 XSetWindowAttributes xswa
;
221 unsigned long xswamask
;
222 XWindowAttributes attribs
;
223 int window_depth
, r
, g
, b
;
224 mp_colorkey_t colork
;
227 sprintf(_title
,"MPlayer %s X11 Overlay",sub_vo
->info
->name
);
232 image_height
= height
;
234 image_format
= format
;
236 aspect_save_orig(width
, height
);
237 aspect_save_prescale(d_width
, d_height
);
238 update_xinerama_info();
240 window_width
= d_width
;
241 window_height
= d_height
;
243 r
= (vo_colorkey
& 0x00ff0000) >> 16;
244 g
= (vo_colorkey
& 0x0000ff00) >> 8;
245 b
= vo_colorkey
& 0x000000ff;
246 switch(vo_depthonscreen
)
249 colorkey
= vo_colorkey
;
252 colorkey
= vo_colorkey
& 0x00ffffff;
255 colorkey
= ((r
>> 3) << 11) | ((g
>> 2) << 5) | (b
>> 3);
258 colorkey
= ((r
>> 3) << 10) | ((g
>> 3) << 5) | (b
>> 3);
261 mp_msg(MSGT_VO
, MSGL_ERR
, "Sorry, this (%d) color depth is not supported\n",
264 mp_msg(MSGT_VO
, MSGL_V
, "Using colorkey: %x\n", colorkey
);
266 aspect(&d_width
, &d_height
, A_NOZOOM
);
268 vo_dx
=( vo_screenwidth
- d_width
) / 2; vo_dy
=( vo_screenheight
- d_height
) / 2;
271 vo_dwidth
=d_width
; vo_dheight
=d_height
;
274 if(use_gui
) guiGetEvent( guiSetShVideo
,0 ); // the GUI will set up / resize the window
279 #ifdef X11_FULLSCREEN
280 if ( ( flags
&VOFLAG_FULLSCREEN
)||(flags
& VOFLAG_SWSCALE
) ) aspect(&d_width
, &d_height
, A_ZOOM
);
284 /* Make the window */
285 XGetWindowAttributes(mDisplay
, DefaultRootWindow(mDisplay
), &attribs
);
288 window_depth
= attribs
.depth
;
289 if ((window_depth
!= 15) && (window_depth
!= 16) && (window_depth
!= 24)
290 && (window_depth
!= 32))
292 XMatchVisualInfo(mDisplay
, mScreen
, window_depth
, TrueColor
, &vinfo
);
294 xswa
.background_pixel
= BlackPixel(mDisplay
, mScreen
);
295 xswa
.border_pixel
= 0;
296 xswa
.colormap
= XCreateColormap(mDisplay
, RootWindow(mDisplay
, mScreen
),
297 vinfo
.visual
, AllocNone
);
298 xswamask
= CWBackPixel
| CWBorderPixel
| CWColormap
;
300 vo_x11_create_vo_window(&vinfo
, vo_dx
, vo_dy
,
301 window_width
, window_height
, flags
,
302 xswa
.colormap
, "xvidix", title
);
303 XChangeWindowAttributes(mDisplay
, vo_window
, xswamask
, &xswa
);
309 if ( ( !WinID
)&&( flags
&VOFLAG_FULLSCREEN
) ) { vo_dx
=0; vo_dy
=0; vo_dwidth
=vo_screenwidth
; vo_dheight
=vo_screenheight
; vo_fs
=1; }
311 if(sub_vo
->config(image_width
,image_height
,vo_dwidth
,vo_dheight
,
312 flags
| VOFLAG_XOVERLAY_SUB_VO
,NULL
,format
)) {
313 mp_msg(MSGT_VO
, MSGL_ERR
, "xover: sub vo config failed\n");
316 colork
.x11
= colorkey
;
320 if(sub_vo
->control(VOCTRL_XOVERLAY_SET_COLORKEY
,&colork
) != VO_TRUE
)
321 mp_msg(MSGT_VO
, MSGL_WARN
, "xover: set_colorkey failed\n");
325 XSync(mDisplay
, False
);
332 static void check_events(void)
334 const int event
= vo_x11_check_events(mDisplay
);
336 if ((event
& VO_EVENT_RESIZE
) || (event
& VO_EVENT_EXPOSE
))
338 sub_vo
->check_events();
342 /* draw_osd, flip_page, draw_slice, draw_frame should be
343 overwritten with vidix functions (vosub_vidix.c) */
344 static void draw_osd(void)
346 mp_msg(MSGT_VO
, MSGL_FATAL
, "xover error: didn't used sub vo draw_osd!\n");
349 static void flip_page(void)
351 mp_msg(MSGT_VO
, MSGL_FATAL
, "xover error: didn't used sub vo flip_page!\n");
354 static int draw_slice(uint8_t *src
[], int stride
[],
355 int w
, int h
, int x
, int y
)
363 mp_msg(MSGT_VO
, MSGL_FATAL
, "xover error: didn't used sub vo draw_slice!\n");
367 static int draw_frame(uint8_t *src
[])
370 mp_msg(MSGT_VO
, MSGL_FATAL
, "xover error: didn't used sub vo draw_frame!\n");
374 static void uninit(void)
376 if(!vo_config_count
) return;
377 if(sub_vo
) sub_vo
->uninit();
380 // Restore our callbacks
381 video_out_xover
.draw_frame
= draw_frame
;
382 video_out_xover
.draw_slice
= draw_slice
;
383 video_out_xover
.flip_page
= flip_page
;
384 video_out_xover
.draw_osd
= draw_osd
;
387 static int preinit(const char *arg
)
392 mp_msg(MSGT_VO
, MSGL_ERR
, "VO XOverlay need a subdriver\n");
396 for(i
= 0 ; video_out_drivers
[i
] != NULL
; i
++) {
397 if(!strcmp(video_out_drivers
[i
]->info
->short_name
,arg
) &&
398 strcmp(video_out_drivers
[i
]->info
->short_name
,"xover"))
401 if(!video_out_drivers
[i
]) {
402 mp_msg(MSGT_VO
, MSGL_ERR
, "VO XOverlay: Subdriver %s not found\n", arg
);
405 if(video_out_drivers
[i
]->control(VOCTRL_XOVERLAY_SUPPORT
,NULL
) != VO_TRUE
) {
406 mp_msg(MSGT_VO
, MSGL_ERR
, "VO XOverlay: %s doesn't support XOverlay\n", arg
);
410 if (!vo_init()) return VO_FALSE
;
411 if(video_out_drivers
[i
]->preinit(NULL
)) {
412 mp_msg(MSGT_VO
, MSGL_ERR
, "VO XOverlay: Subvo init failed\n");
415 sub_vo
= video_out_drivers
[i
];
416 // Setup the sub vo callbacks
417 video_out_xover
.draw_frame
= sub_vo
->draw_frame
;
418 video_out_xover
.draw_slice
= sub_vo
->draw_slice
;
419 video_out_xover
.flip_page
= sub_vo
->flip_page
;
420 video_out_xover
.draw_osd
= sub_vo
->draw_osd
;
424 static int control(uint32_t request
, void *data
, ...)
426 if(!sub_vo
) return VO_ERROR
;
428 case VOCTRL_GUISUPPORT
:
430 case VOCTRL_GET_PANSCAN
:
431 if ( !vo_config_count
|| !vo_fs
) return VO_FALSE
;
436 case VOCTRL_FULLSCREEN
:
438 case VOCTRL_SET_PANSCAN
:
439 if ( vo_fs
&& ( vo_panscan
!= vo_panscan_amount
) )
446 // Safe atm bcs nothing use more than 1 arg
447 return sub_vo
->control(request
,data
);