Make some functions static.
[mplayer.git] / libvo / vo_xvidix.c
blob5e4e9059b445799dc555e55c5f10f3c349658e8e
1 /*
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! ;))
9 */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <math.h>
15 #include <errno.h>
17 #include "config.h"
18 #include "video_out.h"
19 #include "video_out_internal.h"
21 #include <X11/Xlib.h>
22 #include <X11/Xutil.h>
23 //#include <X11/keysym.h>
25 #ifdef HAVE_XINERAMA
26 #include <X11/extensions/Xinerama.h>
27 #endif
29 #include "x11_common.h"
30 #include "aspect.h"
31 #include "mp_msg.h"
33 #include "vosub_vidix.h"
34 #include "vidix/vidixlib.h"
36 #ifdef HAVE_NEW_GUI
37 #include "Gui/interface.h"
38 #endif
41 static vo_info_t info = {
42 "X11 (VIDIX)",
43 "xvidix",
44 "Alex Beregszaszi",
48 LIBVO_EXTERN(xvidix)
49 #define UNUSED(x) ((void)(x)) /* Removes warning about unused arguments */
50 /* X11 related variables */
51 /* Colorkey handling */
52 static XGCValues mGCV;
53 static int colorkey;
54 static vidix_grkey_t gr_key;
56 /* VIDIX related */
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);
74 #ifdef HAVE_XINERAMA
75 extern int xinerama_screen;
76 #endif
78 static void set_window(int force_update)
80 Window mRoot;
82 if (WinID)
84 XGetGeometry(mDisplay, vo_window, &mRoot, &drwX, &drwY, &drwWidth,
85 &drwHeight, &drwBorderWidth, &drwDepth);
86 drwX = drwY = 0;
88 XTranslateCoordinates(mDisplay, vo_window, mRoot, 0, 0,
89 &drwcX, &drwcY, &mRoot);
90 aspect(&dwidth, &dheight, A_NOZOOM);
91 if (!vo_fs)
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 */
97 } else
99 aspect(&dwidth, &dheight, A_NOZOOM);
100 drwcX = drwX = vo_dx;
101 drwcY = drwY = vo_dy;
102 drwWidth = vo_dwidth;
103 drwHeight = vo_dheight;
106 #if X11_FULLSCREEN
107 if (vo_fs)
109 aspect(&dwidth, &dheight, A_ZOOM);
110 drwX =
111 (vo_screenwidth -
112 (dwidth > vo_screenwidth ? vo_screenwidth : dwidth)) / 2;
113 drwcX = drwX;
114 drwY =
115 (vo_screenheight -
116 (dheight > vo_screenheight ? vo_screenheight : dheight)) / 2;
117 drwcY = drwY;
118 drwWidth = (dwidth > vo_screenwidth ? vo_screenwidth : dwidth);
119 drwHeight =
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);
125 #endif
127 vo_dwidth = drwWidth;
128 vo_dheight = drwHeight;
130 #ifdef HAVE_XINERAMA
131 if (XineramaIsActive(mDisplay))
133 XineramaScreenInfo *screens;
134 int num_screens;
135 int i = 0;
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)))
145 i++;
148 if (i < num_screens)
150 /* save the screen we are on */
151 xinerama_screen = i;
152 } else
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
157 * same screen
159 i = xinerama_screen;
162 /* set drwcX and drwcY to the right values */
163 drwcX = drwcX - screens[i].x_org;
164 drwcY = drwcY - screens[i].y_org;
165 XFree(screens);
167 #endif
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
184 window_x = drwcX;
185 window_y = drwcY;
186 vo_dx = drwcX;
187 vo_dy = drwcY;
188 window_width = drwWidth;
189 window_height = drwHeight;
191 /* FIXME: implement runtime resize/move if possible, this way is very ugly! */
192 vidix_stop();
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));
200 abort();
202 vidix_start();
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);
209 /* mDrawColorKey: */
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 */
221 XFlush(mDisplay);
223 return;
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,
231 uint32_t format)
233 XVisualInfo vinfo;
235 // XSizeHints hint;
236 XSetWindowAttributes xswa;
237 unsigned long xswamask;
238 XWindowAttributes attribs;
239 int window_depth, r, g, b;
241 title = "MPlayer VIDIX X11 Overlay";
243 panscan_init();
245 image_height = height;
246 image_width = width;
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);
254 vo_dx = 0;
255 vo_dy = 0;
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,
259 vo_screenheight);
260 window_width = d_width;
261 window_height = d_height;
263 // vo_fs = flags&0x01;
264 // if (vo_fs)
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)
272 case 32:
273 colorkey = vo_colorkey;
274 break;
275 case 24:
276 colorkey = vo_colorkey & 0x00ffffff;
277 break;
278 case 16:
279 colorkey = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
280 break;
281 case 15:
282 colorkey = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
283 break;
284 default:
285 mp_msg(MSGT_VO, MSGL_ERR,
286 "Sorry, this (%d) color depth is not supported\n",
287 vo_depthonscreen);
289 mp_msg(MSGT_VO, MSGL_V, "Using colorkey: %x\n", colorkey);
291 aspect(&d_width, &d_height, A_NOZOOM);
293 vo_dwidth = d_width;
294 vo_dheight = d_height;
296 #ifdef HAVE_NEW_GUI
297 if (use_gui)
298 guiGetEvent(guiSetShVideo, 0); // the GUI will set up / resize the window
299 else
301 #endif
303 #ifdef X11_FULLSCREEN
304 if ((flags & VOFLAG_FULLSCREEN) || (flags & VOFLAG_SWSCALE))
305 aspect(&d_width, &d_height, A_ZOOM);
306 #endif
307 dwidth = d_width;
308 dheight = d_height;
309 /* Make the window */
310 XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay),
311 &attribs);
313 /* from vo_x11 */
314 window_depth = attribs.depth;
315 if ((window_depth != 15) && (window_depth != 16)
316 && (window_depth != 24) && (window_depth != 32))
317 window_depth = 24;
318 XMatchVisualInfo(mDisplay, mScreen, window_depth, TrueColor,
319 &vinfo);
321 xswa.background_pixel = BlackPixel(mDisplay, mScreen);
322 xswa.border_pixel = 0;
323 xswa.colormap =
324 XCreateColormap(mDisplay, RootWindow(mDisplay, mScreen),
325 vinfo.visual, AllocNone);
326 xswa.event_mask =
327 StructureNotifyMask | ExposureMask | KeyPressMask |
328 PropertyChangeMask | ((WinID == 0) ? 0
329 : (ButtonPressMask | ButtonReleaseMask |
330 PointerMotionMask));
331 xswamask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
333 if (WinID >= 0)
335 vo_window =
336 WinID ? ((Window) WinID) : RootWindow(mDisplay, mScreen);
337 if (WinID)
339 XUnmapWindow(mDisplay, vo_window);
340 XChangeWindowAttributes(mDisplay, vo_window, xswamask,
341 &xswa);
342 vo_x11_selectinput_witherr(mDisplay, vo_window,
343 StructureNotifyMask |
344 KeyPressMask |
345 PropertyChangeMask |
346 PointerMotionMask |
347 ButtonPressMask |
348 ButtonReleaseMask |
349 ExposureMask);
350 XMapWindow(mDisplay, vo_window);
351 } else
352 XSelectInput(mDisplay, vo_window, ExposureMask);
353 } else
355 if (vo_window == None)
357 vo_window =
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,
362 xswamask, &xswa);
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)
373 vo_x11_fullscreen();
375 } else
376 vo_x11_nofs_sizepos(vo_dx, vo_dy, vo_dwidth, vo_dheight);
379 if (vo_gc != None)
380 XFreeGC(mDisplay, vo_gc);
381 vo_gc = XCreateGC(mDisplay, vo_window, GCForeground, &mGCV);
382 #ifdef HAVE_NEW_GUI
384 #endif
386 if ((!WinID) && (flags & VOFLAG_FULLSCREEN))
388 vo_dx = 0;
389 vo_dy = 0;
390 vo_dwidth = vo_screenwidth;
391 vo_dheight = vo_screenheight;
392 vo_fs = 1;
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;
402 gr_key.ckey.red = r;
403 gr_key.ckey.green = g;
404 gr_key.ckey.blue = b;
405 } else
406 gr_key.ckey.op = CKEY_FALSE;
407 vidix_grkey_set(&gr_key);
410 set_window(1);
412 XSync(mDisplay, False);
414 panscan_calc();
416 if (vo_ontop)
417 vo_x11_setlayer(mDisplay, vo_window, vo_ontop);
419 return (0);
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))
427 set_window(0);
429 return;
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");
438 return;
441 static void flip_page(void)
443 mp_msg(MSGT_VO, MSGL_FATAL,
444 "[xvidix] error: didn't used vidix flip_page!\n");
445 return;
448 static int draw_slice(uint8_t * src[], int stride[],
449 int w, int h, int x, int y)
451 UNUSED(src);
452 UNUSED(stride);
453 UNUSED(w);
454 UNUSED(h);
455 UNUSED(x);
456 UNUSED(y);
457 mp_msg(MSGT_VO, MSGL_FATAL,
458 "[xvidix] error: didn't used vidix draw_slice!\n");
459 return (-1);
462 static int draw_frame(uint8_t * src[])
464 UNUSED(src);
465 mp_msg(MSGT_VO, MSGL_FATAL,
466 "[xvidix] error: didn't used vidix draw_frame!\n");
467 return (-1);
470 static int query_format(uint32_t format)
472 return (vidix_query_fourcc(format));
475 static void uninit(void)
477 if (!vo_config_count)
478 return;
479 vidix_term();
481 if (vidix_name)
483 free(vidix_name);
484 vidix_name = NULL;
487 vo_x11_uninit();
490 static int preinit(const char *arg)
493 if (arg)
494 vidix_name = strdup(arg);
495 else
497 mp_msg(MSGT_VO, MSGL_INFO,
498 "No vidix driver name provided, probing available ones (-v option for details)!\n");
499 vidix_name = NULL;
502 if (!vo_init())
503 return (-1);
505 if (vidix_preinit(vidix_name, &video_out_xvidix) != 0)
506 return (1);
508 return (0);
511 static int control(uint32_t request, void *data, ...)
513 switch (request)
515 case VOCTRL_QUERY_FORMAT:
516 return query_format(*((uint32_t *) data));
517 case VOCTRL_GUISUPPORT:
518 return VO_TRUE;
519 case VOCTRL_GET_PANSCAN:
520 if (!vo_config_count || !vo_fs)
521 return VO_FALSE;
522 return VO_TRUE;
523 case VOCTRL_ONTOP:
524 vo_x11_ontop();
525 return VO_TRUE;
526 case VOCTRL_FULLSCREEN:
527 vo_x11_fullscreen();
528 case VOCTRL_SET_PANSCAN:
529 if (vo_fs && (vo_panscan != vo_panscan_amount))
531 panscan_calc();
532 set_window(0);
534 return VO_TRUE;
535 case VOCTRL_SET_EQUALIZER:
537 va_list ap;
538 int value;
540 va_start(ap, data);
541 value = va_arg(ap, int);
543 va_end(ap);
545 return vidix_control(request, data, (int *) value);
547 case VOCTRL_GET_EQUALIZER:
549 va_list ap;
550 int *value;
552 va_start(ap, data);
553 value = va_arg(ap, int *);
555 va_end(ap);
557 return vidix_control(request, data, value);
560 return vidix_control(request, data);
561 // return VO_NOTIMPL;