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 static const vo_info_t info
=
54 "General X11 driver for overlay capable video output drivers",
62 #define UNUSED(x) ((void)(x)) /* Removes warning about unused arguments */
64 /* X11 related variables */
65 /* Colorkey handling */
68 /* Image parameters */
69 static uint32_t image_width
;
70 static uint32_t image_height
;
71 static uint32_t image_format
;
73 /* Window parameters */
74 static uint32_t window_x
, window_y
;
75 static uint32_t window_width
, window_height
;
77 /* used by XGetGeometry & XTranslateCoordinates for moving/resizing window */
78 static uint32_t drwX
, drwY
, drwWidth
, drwHeight
, drwBorderWidth
,
79 drwDepth
, drwcX
, drwcY
, dwidth
, dheight
;
81 static const struct vo_old_functions
*sub_vo
= NULL
;
82 static const struct vo_info_s
*sub_info
;
84 static void set_window(int force_update
)
89 XGetGeometry(mDisplay
, vo_window
, &mRoot
, &drwX
, &drwY
, &drwWidth
,
90 &drwHeight
, &drwBorderWidth
, &drwDepth
);
93 XTranslateCoordinates(mDisplay
, vo_window
, mRoot
, 0, 0,
94 &drwcX
, &drwcY
, &mRoot
);
95 aspect(&dwidth
,&dheight
,A_NOZOOM
);
97 mp_msg(MSGT_VO
, MSGL_V
, "[xvidix] dcx: %d dcy: %d dx: %d dy: %d dw: %d dh: %d\n",
98 drwcX
, drwcY
, drwX
, drwY
, drwWidth
, drwHeight
);
100 /* following stuff copied from vo_xmga.c */
104 aspect(&dwidth
,&dheight
,A_NOZOOM
);
105 drwcX
=drwX
=vo_dx
; drwcY
=drwY
=vo_dy
; drwWidth
=vo_dwidth
; drwHeight
=vo_dheight
;
111 aspect(&dwidth
,&dheight
,A_ZOOM
);
112 drwX
= (vo_screenwidth
- ((int)dwidth
> vo_screenwidth
? vo_screenwidth
: dwidth
)) / 2;
114 drwY
= (vo_screenheight
- ((int)dheight
> vo_screenheight
? vo_screenheight
: dheight
)) / 2;
116 drwWidth
= ((int)dwidth
> vo_screenwidth
? vo_screenwidth
: dwidth
);
117 drwHeight
= ((int)dheight
> vo_screenheight
? vo_screenheight
: dheight
);
118 mp_msg(MSGT_VO
, MSGL_V
, "[xvidix-fs] dcx: %d dcy: %d dx: %d dy: %d dw: %d dh: %d\n",
119 drwcX
, drwcY
, drwX
, drwY
, drwWidth
, drwHeight
);
123 vo_dwidth
=drwWidth
; vo_dheight
=drwHeight
;
125 #ifdef CONFIG_XINERAMA
126 if (XineramaIsActive(mDisplay
))
128 XineramaScreenInfo
*screens
;
132 screens
= XineramaQueryScreens(mDisplay
, &num_screens
);
134 /* find the screen we are on */
135 while (i
<num_screens
&&
136 ((screens
[i
].x_org
< (int)drwcX
) ||
137 (screens
[i
].y_org
< (int)drwcY
) ||
138 (screens
[i
].x_org
+ screens
[i
].width
>= (int)drwcX
) ||
139 (screens
[i
].y_org
+ screens
[i
].height
>= (int)drwcY
)))
146 /* save the screen we are on */
149 /* oops.. couldnt find the screen we are on
150 * because the upper left corner left the
151 * visual range. assume we are still on the
157 /* set drwcX and drwcY to the right values */
158 drwcX
= drwcX
- screens
[i
].x_org
;
159 drwcY
= drwcY
- screens
[i
].y_org
;
164 if ( vo_panscan
> 0.0f
&& vo_fs
)
166 drwcX
-=vo_panscan_x
>> 1;
167 drwcY
-=vo_panscan_y
>> 1;
168 drwX
-=vo_panscan_x
>> 1;
169 drwY
-=vo_panscan_y
>> 1;
170 drwWidth
+=vo_panscan_x
;
171 drwHeight
+=vo_panscan_y
;
174 /* set new values in VIDIX */
175 if (force_update
|| (window_x
!= drwcX
) || (window_y
!= drwcY
) ||
176 (window_width
!= drwWidth
) || (window_height
!= drwHeight
))
179 // do a backup of window coordinates
180 w
.x
= window_x
= drwcX
;
181 w
.y
= window_y
= drwcY
;
184 w
.w
= window_width
= drwWidth
;
185 w
.h
= window_height
= drwHeight
;
187 if(sub_vo
->control(VOCTRL_XOVERLAY_SET_WIN
,&w
) != VO_TRUE
)
188 mp_msg(MSGT_VO
, MSGL_ERR
, "xvidx: set_overlay failed\n");
190 mp_msg(MSGT_VO
, MSGL_V
, "[xvidix] window properties: pos: %dx%d, size: %dx%d\n", vo_dx
, vo_dy
, window_width
, window_height
);
195 /* fill drawable with specified color */
196 XSetBackground(mDisplay
, vo_gc
, 0L);
197 XClearWindow( mDisplay
,vo_window
);
198 XSetForeground(mDisplay
, vo_gc
, colorkey
);
199 XFillRectangle(mDisplay
, vo_window
, vo_gc
, drwX
, drwY
, drwWidth
,
200 (vo_fs
? drwHeight
- 1 : drwHeight
));
202 /* flush, update drawable */
208 /* connect to server, create and map window,
209 * allocate colors and (shared) memory
211 static int config(uint32_t width
, uint32_t height
, uint32_t d_width
,
212 uint32_t d_height
, uint32_t flags
, char *title
, uint32_t format
)
216 XSetWindowAttributes xswa
;
217 unsigned long xswamask
;
218 XWindowAttributes attribs
;
219 int window_depth
, r
, g
, b
;
220 mp_colorkey_t colork
;
223 sprintf(_title
,"MPlayer %s X11 Overlay", sub_info
->name
);
228 image_height
= height
;
230 image_format
= format
;
232 aspect_save_orig(width
, height
);
233 aspect_save_prescale(d_width
, d_height
);
234 update_xinerama_info();
236 window_width
= d_width
;
237 window_height
= d_height
;
239 r
= (vo_colorkey
& 0x00ff0000) >> 16;
240 g
= (vo_colorkey
& 0x0000ff00) >> 8;
241 b
= vo_colorkey
& 0x000000ff;
242 switch(vo_depthonscreen
)
245 colorkey
= vo_colorkey
;
248 colorkey
= vo_colorkey
& 0x00ffffff;
251 colorkey
= ((r
>> 3) << 11) | ((g
>> 2) << 5) | (b
>> 3);
254 colorkey
= ((r
>> 3) << 10) | ((g
>> 3) << 5) | (b
>> 3);
257 mp_msg(MSGT_VO
, MSGL_ERR
, "Sorry, this (%d) color depth is not supported\n",
260 mp_msg(MSGT_VO
, MSGL_V
, "Using colorkey: %x\n", colorkey
);
262 aspect(&d_width
, &d_height
, A_NOZOOM
);
264 vo_dx
=( vo_screenwidth
- d_width
) / 2; vo_dy
=( vo_screenheight
- d_height
) / 2;
267 vo_dwidth
=d_width
; vo_dheight
=d_height
;
269 #ifdef X11_FULLSCREEN
270 if ( ( flags
&VOFLAG_FULLSCREEN
)||(flags
& VOFLAG_SWSCALE
) ) aspect(&d_width
, &d_height
, A_ZOOM
);
274 /* Make the window */
275 XGetWindowAttributes(mDisplay
, DefaultRootWindow(mDisplay
), &attribs
);
278 window_depth
= attribs
.depth
;
279 if ((window_depth
!= 15) && (window_depth
!= 16) && (window_depth
!= 24)
280 && (window_depth
!= 32))
282 XMatchVisualInfo(mDisplay
, mScreen
, window_depth
, TrueColor
, &vinfo
);
284 xswa
.background_pixel
= BlackPixel(mDisplay
, mScreen
);
285 xswa
.border_pixel
= 0;
286 xswa
.colormap
= XCreateColormap(mDisplay
, RootWindow(mDisplay
, mScreen
),
287 vinfo
.visual
, AllocNone
);
288 xswamask
= CWBackPixel
| CWBorderPixel
| CWColormap
;
290 vo_x11_create_vo_window(&vinfo
, vo_dx
, vo_dy
,
291 window_width
, window_height
, flags
,
292 xswa
.colormap
, "xvidix", title
);
293 XChangeWindowAttributes(mDisplay
, vo_window
, xswamask
, &xswa
);
295 if ( ( !WinID
)&&( flags
&VOFLAG_FULLSCREEN
) ) { vo_dx
=0; vo_dy
=0; vo_dwidth
=vo_screenwidth
; vo_dheight
=vo_screenheight
; vo_fs
=1; }
297 if(sub_vo
->config(image_width
,image_height
,vo_dwidth
,vo_dheight
,
298 flags
| VOFLAG_XOVERLAY_SUB_VO
,NULL
,format
)) {
299 mp_msg(MSGT_VO
, MSGL_ERR
, "xover: sub vo config failed\n");
302 colork
.x11
= colorkey
;
306 if(sub_vo
->control(VOCTRL_XOVERLAY_SET_COLORKEY
,&colork
) != VO_TRUE
)
307 mp_msg(MSGT_VO
, MSGL_WARN
, "xover: set_colorkey failed\n");
311 XSync(mDisplay
, False
);
318 static void check_events(void)
320 const int event
= vo_x11_check_events(mDisplay
);
322 if ((event
& VO_EVENT_RESIZE
) || (event
& VO_EVENT_EXPOSE
))
324 sub_vo
->check_events();
328 /* draw_osd, flip_page, draw_slice, draw_frame should be
329 overwritten with vidix functions (vosub_vidix.c) */
330 static void draw_osd(void)
332 mp_msg(MSGT_VO
, MSGL_FATAL
, "xover error: didn't used sub vo draw_osd!\n");
335 static void flip_page(void)
337 mp_msg(MSGT_VO
, MSGL_FATAL
, "xover error: didn't used sub vo flip_page!\n");
340 static int draw_slice(uint8_t *src
[], int stride
[],
341 int w
, int h
, int x
, int y
)
349 mp_msg(MSGT_VO
, MSGL_FATAL
, "xover error: didn't used sub vo draw_slice!\n");
353 static int draw_frame(uint8_t *src
[])
356 mp_msg(MSGT_VO
, MSGL_FATAL
, "xover error: didn't used sub vo draw_frame!\n");
360 static void uninit(void)
362 if(!vo_config_count
) return;
363 if(sub_vo
) sub_vo
->uninit();
366 // Restore our callbacks
367 video_out_xover
.old_functions
->draw_frame
= draw_frame
;
368 video_out_xover
.old_functions
->draw_slice
= draw_slice
;
369 video_out_xover
.old_functions
->flip_page
= flip_page
;
370 video_out_xover
.old_functions
->draw_osd
= draw_osd
;
373 static int preinit(const char *arg
)
378 mp_msg(MSGT_VO
, MSGL_ERR
, "VO XOverlay need a subdriver\n");
382 const struct vo_driver
*candidate
;
383 for(i
= 0; (candidate
= video_out_drivers
[i
]) != NULL
; i
++)
384 if (!candidate
->is_new
&& !strcmp(candidate
->info
->short_name
,arg
) &&
385 strcmp(candidate
->info
->short_name
,"xover"))
388 mp_msg(MSGT_VO
, MSGL_ERR
, "VO XOverlay: Subdriver %s not found\n", arg
);
392 const struct vo_old_functions
*functions
= candidate
->old_functions
;
393 if (functions
->control(VOCTRL_XOVERLAY_SUPPORT
,NULL
) != VO_TRUE
) {
394 mp_msg(MSGT_VO
, MSGL_ERR
, "VO XOverlay: %s doesn't support XOverlay\n", arg
);
398 if (!vo_init()) return VO_FALSE
;
399 if(functions
->preinit(NULL
)) {
400 mp_msg(MSGT_VO
, MSGL_ERR
, "VO XOverlay: Subvo init failed\n");
404 sub_info
= candidate
->info
;
405 // Setup the sub vo callbacks
406 video_out_xover
.old_functions
->draw_frame
= sub_vo
->draw_frame
;
407 video_out_xover
.old_functions
->draw_slice
= sub_vo
->draw_slice
;
408 video_out_xover
.old_functions
->flip_page
= sub_vo
->flip_page
;
409 video_out_xover
.old_functions
->draw_osd
= sub_vo
->draw_osd
;
413 static int control(uint32_t request
, void *data
)
415 if(!sub_vo
) return VO_ERROR
;
417 case VOCTRL_GET_PANSCAN
:
418 if ( !vo_config_count
|| !vo_fs
) return VO_FALSE
;
423 case VOCTRL_FULLSCREEN
:
425 case VOCTRL_SET_PANSCAN
:
426 if ( vo_fs
&& ( vo_panscan
!= vo_panscan_amount
) )
433 return sub_vo
->control(request
,data
);