2 VIDIX accelerated overlay in a X window
4 (C) Alex Beregszaszi & Zoltan Ponekker & Nick Kurshev
6 WS window manager by Pontscho/Fresh!
8 Based on vo_gl.c and vo_vesa.c and vo_xmga.c (.so mastah! ;))
18 #include "video_out.h"
19 #include "video_out_internal.h"
22 #include <X11/Xutil.h>
23 //#include <X11/keysym.h>
26 #include <X11/extensions/Xinerama.h>
29 #include "x11_common.h"
33 #include "vosub_vidix.h"
34 #include "vidix/vidixlib.h"
37 #include "Gui/interface.h"
41 static vo_info_t info
= {
49 #define UNUSED(x) ((void)(x)) /* Removes warning about unused arguments */
50 /* X11 related variables */
51 /* Colorkey handling */
52 static XGCValues mGCV
;
54 static vidix_grkey_t gr_key
;
57 static char *vidix_name
;
59 /* Image parameters */
60 static uint32_t image_width
;
61 static uint32_t image_height
;
62 static uint32_t image_format
;
64 /* Window parameters */
65 static uint32_t window_x
, window_y
;
66 static uint32_t window_width
, window_height
;
68 /* used by XGetGeometry & XTranslateCoordinates for moving/resizing window */
69 static uint32_t drwX
, drwY
, drwWidth
, drwHeight
, drwBorderWidth
,
70 drwDepth
, drwcX
, drwcY
, dwidth
, dheight
;
72 extern void set_video_eq(int cap
);
75 extern int xinerama_screen
;
78 static void set_window(int force_update
)
84 XGetGeometry(mDisplay
, vo_window
, &mRoot
, &drwX
, &drwY
, &drwWidth
,
85 &drwHeight
, &drwBorderWidth
, &drwDepth
);
88 XTranslateCoordinates(mDisplay
, vo_window
, mRoot
, 0, 0,
89 &drwcX
, &drwcY
, &mRoot
);
90 aspect(&dwidth
, &dheight
, A_NOZOOM
);
92 mp_msg(MSGT_VO
, MSGL_V
,
93 "[xvidix] dcx: %d dcy: %d dx: %d dy: %d dw: %d dh: %d\n",
94 drwcX
, drwcY
, drwX
, drwY
, drwWidth
, drwHeight
);
96 /* following stuff copied from vo_xmga.c */
99 aspect(&dwidth
, &dheight
, A_NOZOOM
);
100 drwcX
= drwX
= vo_dx
;
101 drwcY
= drwY
= vo_dy
;
102 drwWidth
= vo_dwidth
;
103 drwHeight
= vo_dheight
;
109 aspect(&dwidth
, &dheight
, A_ZOOM
);
112 (dwidth
> vo_screenwidth
? vo_screenwidth
: dwidth
)) / 2;
116 (dheight
> vo_screenheight
? vo_screenheight
: dheight
)) / 2;
118 drwWidth
= (dwidth
> vo_screenwidth
? vo_screenwidth
: dwidth
);
120 (dheight
> vo_screenheight
? vo_screenheight
: dheight
);
121 mp_msg(MSGT_VO
, MSGL_V
,
122 "[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
;
128 vo_dheight
= drwHeight
;
131 if (XineramaIsActive(mDisplay
))
133 XineramaScreenInfo
*screens
;
137 screens
= XineramaQueryScreens(mDisplay
, &num_screens
);
139 /* find the screen we are on */
140 while (i
< num_screens
&&
141 ((screens
[i
].x_org
< drwcX
) || (screens
[i
].y_org
< drwcY
) ||
142 (screens
[i
].x_org
+ screens
[i
].width
>= drwcX
) ||
143 (screens
[i
].y_org
+ screens
[i
].height
>= drwcY
)))
150 /* save the screen we are on */
154 /* oops.. couldnt find the screen we are on
155 * because the upper left corner left the
156 * visual range. assume we are still on the
162 /* set drwcX and drwcY to the right values */
163 drwcX
= drwcX
- screens
[i
].x_org
;
164 drwcY
= drwcY
- screens
[i
].y_org
;
169 if (vo_panscan
> 0.0f
&& vo_fs
)
171 drwcX
-= vo_panscan_x
>> 1;
172 drwcY
-= vo_panscan_y
>> 1;
173 drwX
-= vo_panscan_x
>> 1;
174 drwY
-= vo_panscan_y
>> 1;
175 drwWidth
+= vo_panscan_x
;
176 drwHeight
+= vo_panscan_y
;
179 /* set new values in VIDIX */
180 if (force_update
|| (window_x
!= drwcX
) || (window_y
!= drwcY
) ||
181 (window_width
!= drwWidth
) || (window_height
!= drwHeight
))
183 // do a backup of window coordinates
188 window_width
= drwWidth
;
189 window_height
= drwHeight
;
191 /* FIXME: implement runtime resize/move if possible, this way is very ugly! */
193 if (vidix_init(image_width
, image_height
, vo_dx
, vo_dy
,
194 window_width
, window_height
, image_format
,
195 vo_depthonscreen
, vo_screenwidth
,
196 vo_screenheight
) != 0)
198 mp_msg(MSGT_VO
, MSGL_FATAL
,
199 "Can't initialize VIDIX driver: %s\n", strerror(errno
));
205 mp_msg(MSGT_VO
, MSGL_V
,
206 "[xvidix] window properties: pos: %dx%d, size: %dx%d\n", vo_dx
,
207 vo_dy
, window_width
, window_height
);
211 /* fill drawable with specified color */
212 if (!(vo_colorkey
& 0xff000000))
214 XSetBackground(mDisplay
, vo_gc
, 0L);
215 XClearWindow(mDisplay
, vo_window
);
216 XSetForeground(mDisplay
, vo_gc
, colorkey
);
217 XFillRectangle(mDisplay
, vo_window
, vo_gc
, drwX
, drwY
, drwWidth
,
218 (vo_fs
? drwHeight
- 1 : drwHeight
));
220 /* flush, update drawable */
226 /* connect to server, create and map window,
227 * allocate colors and (shared) memory
229 static int config(uint32_t width
, uint32_t height
, uint32_t d_width
,
230 uint32_t d_height
, uint32_t flags
, char *title
,
236 XSetWindowAttributes xswa
;
237 unsigned long xswamask
;
238 XWindowAttributes attribs
;
239 int window_depth
, r
, g
, b
;
241 title
= "MPlayer VIDIX X11 Overlay";
245 image_height
= height
;
247 image_format
= format
;
248 vo_mouse_autohide
= 1;
250 aspect_save_orig(width
, height
);
251 aspect_save_prescale(d_width
, d_height
);
252 aspect_save_screenres(vo_screenwidth
, vo_screenheight
);
256 vo_dx
= (vo_screenwidth
- d_width
) / 2;
257 vo_dy
= (vo_screenheight
- d_height
) / 2;
258 geometry(&vo_dx
, &vo_dy
, &d_width
, &d_height
, vo_screenwidth
,
260 window_width
= d_width
;
261 window_height
= d_height
;
263 // vo_fs = flags&0x01;
265 // { vo_old_width=d_width; vo_old_height=d_height; }
267 r
= (vo_colorkey
& 0x00ff0000) >> 16;
268 g
= (vo_colorkey
& 0x0000ff00) >> 8;
269 b
= vo_colorkey
& 0x000000ff;
270 switch (vo_depthonscreen
)
273 colorkey
= vo_colorkey
;
276 colorkey
= vo_colorkey
& 0x00ffffff;
279 colorkey
= ((r
>> 3) << 11) | ((g
>> 2) << 5) | (b
>> 3);
282 colorkey
= ((r
>> 3) << 10) | ((g
>> 3) << 5) | (b
>> 3);
285 mp_msg(MSGT_VO
, MSGL_ERR
,
286 "Sorry, this (%d) color depth is not supported\n",
289 mp_msg(MSGT_VO
, MSGL_V
, "Using colorkey: %x\n", colorkey
);
291 aspect(&d_width
, &d_height
, A_NOZOOM
);
294 vo_dheight
= d_height
;
298 guiGetEvent(guiSetShVideo
, 0); // the GUI will set up / resize the window
303 #ifdef X11_FULLSCREEN
304 if ((flags
& VOFLAG_FULLSCREEN
) || (flags
& VOFLAG_SWSCALE
))
305 aspect(&d_width
, &d_height
, A_ZOOM
);
309 /* Make the window */
310 XGetWindowAttributes(mDisplay
, DefaultRootWindow(mDisplay
),
314 window_depth
= attribs
.depth
;
315 if ((window_depth
!= 15) && (window_depth
!= 16)
316 && (window_depth
!= 24) && (window_depth
!= 32))
318 XMatchVisualInfo(mDisplay
, mScreen
, window_depth
, TrueColor
,
321 xswa
.background_pixel
= BlackPixel(mDisplay
, mScreen
);
322 xswa
.border_pixel
= 0;
324 XCreateColormap(mDisplay
, RootWindow(mDisplay
, mScreen
),
325 vinfo
.visual
, AllocNone
);
327 StructureNotifyMask
| ExposureMask
| KeyPressMask
|
328 PropertyChangeMask
| ((WinID
== 0) ? 0
329 : (ButtonPressMask
| ButtonReleaseMask
|
331 xswamask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
336 WinID
? ((Window
) WinID
) : RootWindow(mDisplay
, mScreen
);
339 XUnmapWindow(mDisplay
, vo_window
);
340 XChangeWindowAttributes(mDisplay
, vo_window
, xswamask
,
342 vo_x11_selectinput_witherr(mDisplay
, vo_window
,
343 StructureNotifyMask
|
350 XMapWindow(mDisplay
, vo_window
);
352 XSelectInput(mDisplay
, vo_window
, ExposureMask
);
355 if (vo_window
== None
)
358 XCreateWindow(mDisplay
, RootWindow(mDisplay
, mScreen
),
359 vo_dx
, vo_dy
, window_width
,
360 window_height
, xswa
.border_pixel
,
361 vinfo
.depth
, InputOutput
, vinfo
.visual
,
364 vo_x11_classhint(mDisplay
, vo_window
, "xvidix");
365 vo_hidecursor(mDisplay
, vo_window
);
366 vo_x11_sizehint(vo_dx
, vo_dy
, vo_dwidth
, vo_dheight
, 0);
368 XStoreName(mDisplay
, vo_window
, title
);
369 XMapWindow(mDisplay
, vo_window
);
370 vo_x11_nofs_sizepos(vo_dx
, vo_dy
, vo_dwidth
, vo_dheight
);
372 if (flags
& VOFLAG_FULLSCREEN
)
376 vo_x11_nofs_sizepos(vo_dx
, vo_dy
, vo_dwidth
, vo_dheight
);
380 XFreeGC(mDisplay
, vo_gc
);
381 vo_gc
= XCreateGC(mDisplay
, vo_window
, GCForeground
, &mGCV
);
386 if ((!WinID
) && (flags
& VOFLAG_FULLSCREEN
))
390 vo_dwidth
= vo_screenwidth
;
391 vo_dheight
= vo_screenheight
;
395 if (vidix_grkey_support())
397 vidix_grkey_get(&gr_key
);
398 gr_key
.key_op
= KEYS_PUT
;
399 if (!(vo_colorkey
& 0xff000000))
401 gr_key
.ckey
.op
= CKEY_TRUE
;
403 gr_key
.ckey
.green
= g
;
404 gr_key
.ckey
.blue
= b
;
406 gr_key
.ckey
.op
= CKEY_FALSE
;
407 vidix_grkey_set(&gr_key
);
412 XSync(mDisplay
, False
);
417 vo_x11_setlayer(mDisplay
, vo_window
, vo_ontop
);
422 static void check_events(void)
424 const int event
= vo_x11_check_events(mDisplay
);
426 if ((event
& VO_EVENT_RESIZE
) || (event
& VO_EVENT_EXPOSE
))
432 /* draw_osd, flip_page, draw_slice, draw_frame should be
433 overwritten with vidix functions (vosub_vidix.c) */
434 static void draw_osd(void)
436 mp_msg(MSGT_VO
, MSGL_FATAL
,
437 "[xvidix] error: didn't used vidix draw_osd!\n");
441 static void flip_page(void)
443 mp_msg(MSGT_VO
, MSGL_FATAL
,
444 "[xvidix] error: didn't used vidix flip_page!\n");
448 static int draw_slice(uint8_t * src
[], int stride
[],
449 int w
, int h
, int x
, int y
)
457 mp_msg(MSGT_VO
, MSGL_FATAL
,
458 "[xvidix] error: didn't used vidix draw_slice!\n");
462 static int draw_frame(uint8_t * src
[])
465 mp_msg(MSGT_VO
, MSGL_FATAL
,
466 "[xvidix] error: didn't used vidix draw_frame!\n");
470 static int query_format(uint32_t format
)
472 return (vidix_query_fourcc(format
));
475 static void uninit(void)
477 if (!vo_config_count
)
490 static int preinit(const char *arg
)
494 vidix_name
= strdup(arg
);
497 mp_msg(MSGT_VO
, MSGL_INFO
,
498 "No vidix driver name provided, probing available ones (-v option for details)!\n");
505 if (vidix_preinit(vidix_name
, &video_out_xvidix
) != 0)
511 static int control(uint32_t request
, void *data
, ...)
515 case VOCTRL_QUERY_FORMAT
:
516 return query_format(*((uint32_t *) data
));
517 case VOCTRL_GUISUPPORT
:
519 case VOCTRL_GET_PANSCAN
:
520 if (!vo_config_count
|| !vo_fs
)
526 case VOCTRL_FULLSCREEN
:
528 case VOCTRL_SET_PANSCAN
:
529 if (vo_fs
&& (vo_panscan
!= vo_panscan_amount
))
535 case VOCTRL_SET_EQUALIZER
:
541 value
= va_arg(ap
, int);
545 return vidix_control(request
, data
, (int *) value
);
547 case VOCTRL_GET_EQUALIZER
:
553 value
= va_arg(ap
, int *);
557 return vidix_control(request
, data
, value
);
560 return vidix_control(request
, data
);
561 // return VO_NOTIMPL;