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 /* X11 related variables */
63 /* Colorkey handling */
66 /* Image parameters */
67 static uint32_t image_width
;
68 static uint32_t image_height
;
69 static uint32_t image_format
;
71 /* Window parameters */
72 static uint32_t window_x
, window_y
;
73 static uint32_t window_width
, window_height
;
75 /* used by XGetGeometry & XTranslateCoordinates for moving/resizing window */
76 static uint32_t drwX
, drwY
, drwWidth
, drwHeight
, drwBorderWidth
,
77 drwDepth
, drwcX
, drwcY
, dwidth
, dheight
;
79 static const struct vo_old_functions
*sub_vo
= NULL
;
80 static const struct vo_info_s
*sub_info
;
82 static void set_window(int force_update
)
87 XGetGeometry(mDisplay
, vo_window
, &mRoot
, &drwX
, &drwY
, &drwWidth
,
88 &drwHeight
, &drwBorderWidth
, &drwDepth
);
91 XTranslateCoordinates(mDisplay
, vo_window
, mRoot
, 0, 0,
92 &drwcX
, &drwcY
, &mRoot
);
93 aspect(&dwidth
,&dheight
,A_NOZOOM
);
95 mp_msg(MSGT_VO
, MSGL_V
, "[xvidix] dcx: %d dcy: %d dx: %d dy: %d dw: %d dh: %d\n",
96 drwcX
, drwcY
, drwX
, drwY
, drwWidth
, drwHeight
);
98 /* following stuff copied from vo_xmga.c */
102 aspect(&dwidth
,&dheight
,A_NOZOOM
);
103 drwcX
=drwX
=vo_dx
; drwcY
=drwY
=vo_dy
; drwWidth
=vo_dwidth
; drwHeight
=vo_dheight
;
109 aspect(&dwidth
,&dheight
,A_ZOOM
);
110 drwX
= (vo_screenwidth
- ((int)dwidth
> vo_screenwidth
? vo_screenwidth
: dwidth
)) / 2;
112 drwY
= (vo_screenheight
- ((int)dheight
> vo_screenheight
? vo_screenheight
: dheight
)) / 2;
114 drwWidth
= ((int)dwidth
> vo_screenwidth
? vo_screenwidth
: dwidth
);
115 drwHeight
= ((int)dheight
> vo_screenheight
? vo_screenheight
: dheight
);
116 mp_msg(MSGT_VO
, MSGL_V
, "[xvidix-fs] dcx: %d dcy: %d dx: %d dy: %d dw: %d dh: %d\n",
117 drwcX
, drwcY
, drwX
, drwY
, drwWidth
, drwHeight
);
121 vo_dwidth
=drwWidth
; vo_dheight
=drwHeight
;
123 #ifdef CONFIG_XINERAMA
124 if (XineramaIsActive(mDisplay
))
126 XineramaScreenInfo
*screens
;
130 screens
= XineramaQueryScreens(mDisplay
, &num_screens
);
132 /* find the screen we are on */
133 while (i
<num_screens
&&
134 ((screens
[i
].x_org
< (int)drwcX
) ||
135 (screens
[i
].y_org
< (int)drwcY
) ||
136 (screens
[i
].x_org
+ screens
[i
].width
>= (int)drwcX
) ||
137 (screens
[i
].y_org
+ screens
[i
].height
>= (int)drwcY
)))
144 /* save the screen we are on */
147 /* oops.. couldnt find the screen we are on
148 * because the upper left corner left the
149 * visual range. assume we are still on the
155 /* set drwcX and drwcY to the right values */
156 drwcX
= drwcX
- screens
[i
].x_org
;
157 drwcY
= drwcY
- screens
[i
].y_org
;
162 if ( vo_panscan
> 0.0f
&& vo_fs
)
164 drwcX
-=vo_panscan_x
>> 1;
165 drwcY
-=vo_panscan_y
>> 1;
166 drwX
-=vo_panscan_x
>> 1;
167 drwY
-=vo_panscan_y
>> 1;
168 drwWidth
+=vo_panscan_x
;
169 drwHeight
+=vo_panscan_y
;
172 /* set new values in VIDIX */
173 if (force_update
|| (window_x
!= drwcX
) || (window_y
!= drwcY
) ||
174 (window_width
!= drwWidth
) || (window_height
!= drwHeight
))
177 // do a backup of window coordinates
178 w
.x
= window_x
= drwcX
;
179 w
.y
= window_y
= drwcY
;
182 w
.w
= window_width
= drwWidth
;
183 w
.h
= window_height
= drwHeight
;
185 if(sub_vo
->control(VOCTRL_XOVERLAY_SET_WIN
,&w
) != VO_TRUE
)
186 mp_msg(MSGT_VO
, MSGL_ERR
, "xvidx: set_overlay failed\n");
188 mp_msg(MSGT_VO
, MSGL_V
, "[xvidix] window properties: pos: %dx%d, size: %dx%d\n", vo_dx
, vo_dy
, window_width
, window_height
);
193 /* fill drawable with specified color */
194 XSetBackground(mDisplay
, vo_gc
, 0L);
195 XClearWindow( mDisplay
,vo_window
);
196 XSetForeground(mDisplay
, vo_gc
, colorkey
);
197 XFillRectangle(mDisplay
, vo_window
, vo_gc
, drwX
, drwY
, drwWidth
,
198 (vo_fs
? drwHeight
- 1 : drwHeight
));
200 /* flush, update drawable */
206 /* connect to server, create and map window,
207 * allocate colors and (shared) memory
209 static int config(uint32_t width
, uint32_t height
, uint32_t d_width
,
210 uint32_t d_height
, uint32_t flags
, char *title
, uint32_t format
)
214 XSetWindowAttributes xswa
;
215 unsigned long xswamask
;
216 XWindowAttributes attribs
;
217 int window_depth
, r
, g
, b
;
218 mp_colorkey_t colork
;
221 sprintf(_title
,"MPlayer %s X11 Overlay", sub_info
->name
);
226 image_height
= height
;
228 image_format
= format
;
230 aspect_save_orig(width
, height
);
231 aspect_save_prescale(d_width
, d_height
);
232 update_xinerama_info();
234 window_width
= d_width
;
235 window_height
= d_height
;
237 r
= (vo_colorkey
& 0x00ff0000) >> 16;
238 g
= (vo_colorkey
& 0x0000ff00) >> 8;
239 b
= vo_colorkey
& 0x000000ff;
240 switch(vo_depthonscreen
)
243 colorkey
= vo_colorkey
;
246 colorkey
= vo_colorkey
& 0x00ffffff;
249 colorkey
= ((r
>> 3) << 11) | ((g
>> 2) << 5) | (b
>> 3);
252 colorkey
= ((r
>> 3) << 10) | ((g
>> 3) << 5) | (b
>> 3);
255 mp_msg(MSGT_VO
, MSGL_ERR
, "Sorry, this (%d) color depth is not supported\n",
258 mp_msg(MSGT_VO
, MSGL_V
, "Using colorkey: %x\n", colorkey
);
260 aspect(&d_width
, &d_height
, A_NOZOOM
);
262 vo_dx
=( vo_screenwidth
- d_width
) / 2; vo_dy
=( vo_screenheight
- d_height
) / 2;
265 vo_dwidth
=d_width
; vo_dheight
=d_height
;
267 #ifdef X11_FULLSCREEN
268 if ( ( flags
&VOFLAG_FULLSCREEN
)||(flags
& VOFLAG_SWSCALE
) ) aspect(&d_width
, &d_height
, A_ZOOM
);
272 /* Make the window */
273 XGetWindowAttributes(mDisplay
, DefaultRootWindow(mDisplay
), &attribs
);
276 window_depth
= attribs
.depth
;
277 if ((window_depth
!= 15) && (window_depth
!= 16) && (window_depth
!= 24)
278 && (window_depth
!= 32))
280 XMatchVisualInfo(mDisplay
, mScreen
, window_depth
, TrueColor
, &vinfo
);
282 xswa
.background_pixel
= BlackPixel(mDisplay
, mScreen
);
283 xswa
.border_pixel
= 0;
284 xswa
.colormap
= XCreateColormap(mDisplay
, RootWindow(mDisplay
, mScreen
),
285 vinfo
.visual
, AllocNone
);
286 xswamask
= CWBackPixel
| CWBorderPixel
| CWColormap
;
288 vo_x11_create_vo_window(&vinfo
, vo_dx
, vo_dy
,
289 window_width
, window_height
, flags
,
290 xswa
.colormap
, "xvidix", title
);
291 XChangeWindowAttributes(mDisplay
, vo_window
, xswamask
, &xswa
);
293 if ( ( !WinID
)&&( flags
&VOFLAG_FULLSCREEN
) ) { vo_dx
=0; vo_dy
=0; vo_dwidth
=vo_screenwidth
; vo_dheight
=vo_screenheight
; vo_fs
=1; }
295 if(sub_vo
->config(image_width
,image_height
,vo_dwidth
,vo_dheight
,
296 flags
| VOFLAG_XOVERLAY_SUB_VO
,NULL
,format
)) {
297 mp_msg(MSGT_VO
, MSGL_ERR
, "xover: sub vo config failed\n");
300 colork
.x11
= colorkey
;
304 if(sub_vo
->control(VOCTRL_XOVERLAY_SET_COLORKEY
,&colork
) != VO_TRUE
)
305 mp_msg(MSGT_VO
, MSGL_WARN
, "xover: set_colorkey failed\n");
309 XSync(mDisplay
, False
);
316 static void check_events(void)
318 const int event
= vo_x11_check_events(mDisplay
);
320 if ((event
& VO_EVENT_RESIZE
) || (event
& VO_EVENT_EXPOSE
))
322 sub_vo
->check_events();
326 /* draw_osd, flip_page, draw_slice, draw_frame should be
327 overwritten with vidix functions (vosub_vidix.c) */
328 static void draw_osd(void)
330 mp_msg(MSGT_VO
, MSGL_FATAL
, "xover error: didn't used sub vo draw_osd!\n");
333 static void flip_page(void)
335 mp_msg(MSGT_VO
, MSGL_FATAL
, "xover error: didn't used sub vo flip_page!\n");
338 static int draw_slice(uint8_t *src
[], int stride
[],
339 int w
, int h
, int x
, int y
)
341 mp_msg(MSGT_VO
, MSGL_FATAL
, "xover error: didn't used sub vo draw_slice!\n");
345 static int draw_frame(uint8_t *src
[])
347 mp_msg(MSGT_VO
, MSGL_FATAL
, "xover error: didn't used sub vo draw_frame!\n");
351 static void uninit(void)
353 if(!vo_config_count
) return;
354 if(sub_vo
) sub_vo
->uninit();
357 // Restore our callbacks
358 video_out_xover
.old_functions
->draw_frame
= draw_frame
;
359 video_out_xover
.old_functions
->draw_slice
= draw_slice
;
360 video_out_xover
.old_functions
->flip_page
= flip_page
;
361 video_out_xover
.old_functions
->draw_osd
= draw_osd
;
364 static int preinit(const char *arg
)
369 mp_msg(MSGT_VO
, MSGL_ERR
, "VO XOverlay need a subdriver\n");
373 const struct vo_driver
*candidate
;
374 for(i
= 0; (candidate
= video_out_drivers
[i
]) != NULL
; i
++)
375 if (!candidate
->is_new
&& !strcmp(candidate
->info
->short_name
,arg
) &&
376 strcmp(candidate
->info
->short_name
,"xover"))
379 mp_msg(MSGT_VO
, MSGL_ERR
, "VO XOverlay: Subdriver %s not found\n", arg
);
383 const struct vo_old_functions
*functions
= candidate
->old_functions
;
384 if (functions
->control(VOCTRL_XOVERLAY_SUPPORT
,NULL
) != VO_TRUE
) {
385 mp_msg(MSGT_VO
, MSGL_ERR
, "VO XOverlay: %s doesn't support XOverlay\n", arg
);
389 if (!vo_init()) return VO_FALSE
;
390 if(functions
->preinit(NULL
)) {
391 mp_msg(MSGT_VO
, MSGL_ERR
, "VO XOverlay: Subvo init failed\n");
395 sub_info
= candidate
->info
;
396 // Setup the sub vo callbacks
397 video_out_xover
.old_functions
->draw_frame
= sub_vo
->draw_frame
;
398 video_out_xover
.old_functions
->draw_slice
= sub_vo
->draw_slice
;
399 video_out_xover
.old_functions
->flip_page
= sub_vo
->flip_page
;
400 video_out_xover
.old_functions
->draw_osd
= sub_vo
->draw_osd
;
404 static int control(uint32_t request
, void *data
)
406 if(!sub_vo
) return VO_ERROR
;
408 case VOCTRL_GET_PANSCAN
:
409 if ( !vo_config_count
|| !vo_fs
) return VO_FALSE
;
414 case VOCTRL_FULLSCREEN
:
416 case VOCTRL_SET_PANSCAN
:
417 if ( vo_fs
&& ( vo_panscan
!= vo_panscan_amount
) )
424 return sub_vo
->control(request
,data
);