Mercurial > mplayer.hg
comparison libvo/vo_xover.c @ 9569:894d02a6469e
vo_xover is a new vo that should make easy to have x11 support for
all overlay based vo.
Add support for xover to tdfx_vid. Sometimes the display flash bcs
the x server fuckup the overlay settings :( Not so bad as it only append
when i switch the focused window here.
author | albeu |
---|---|
date | Wed, 12 Mar 2003 15:04:05 +0000 |
parents | |
children | 602264261d3e |
comparison
equal
deleted
inserted
replaced
9568:ed8827c95386 | 9569:894d02a6469e |
---|---|
1 /* | |
2 VIDIX accelerated overlay in a X window | |
3 | |
4 (C) Alex Beregszaszi & Zoltan Ponekker & Nick Kurshev | |
5 | |
6 WS window manager by Pontscho/Fresh! | |
7 | |
8 Based on vo_gl.c and vo_vesa.c and vo_xmga.c (.so mastah! ;)) | |
9 */ | |
10 | |
11 #include <stdio.h> | |
12 #include <stdlib.h> | |
13 #include <string.h> | |
14 #include <math.h> | |
15 #include <errno.h> | |
16 #include <unistd.h> | |
17 #include <sys/ioctl.h> | |
18 | |
19 #include "config.h" | |
20 #include "video_out.h" | |
21 #include "video_out_internal.h" | |
22 | |
23 #include <X11/Xlib.h> | |
24 #include <X11/Xutil.h> | |
25 //#include <X11/keysym.h> | |
26 | |
27 #ifdef HAVE_XINERAMA | |
28 #include <X11/extensions/Xinerama.h> | |
29 #endif | |
30 | |
31 #include "x11_common.h" | |
32 #include "aspect.h" | |
33 #include "mp_msg.h" | |
34 | |
35 #include "../mplayer.h" /* exit_player() */ | |
36 | |
37 #ifdef HAVE_NEW_GUI | |
38 #include "../Gui/interface.h" | |
39 #endif | |
40 | |
41 | |
42 static vo_info_t info = | |
43 { | |
44 "General X11 driver for overlay capable vo's", | |
45 "xover", | |
46 "Albeu", | |
47 "" | |
48 }; | |
49 | |
50 LIBVO_EXTERN(xover) | |
51 | |
52 #define UNUSED(x) ((void)(x)) /* Removes warning about unused arguments */ | |
53 | |
54 /* X11 related variables */ | |
55 /* Colorkey handling */ | |
56 static XGCValues mGCV; | |
57 static uint32_t fgColor; | |
58 static uint32_t bgColor; | |
59 | |
60 /* Image parameters */ | |
61 static uint32_t image_width; | |
62 static uint32_t image_height; | |
63 static uint32_t image_format; | |
64 | |
65 /* Window parameters */ | |
66 static uint32_t window_x, window_y; | |
67 static uint32_t window_width, window_height; | |
68 | |
69 /* used by XGetGeometry & XTranslateCoordinates for moving/resizing window */ | |
70 static uint32_t drwX, drwY, drwWidth, drwHeight, drwBorderWidth, | |
71 drwDepth, drwcX, drwcY, dwidth, dheight; | |
72 | |
73 #ifdef HAVE_XINERAMA | |
74 extern int xinerama_screen; | |
75 #endif | |
76 | |
77 static vo_functions_t* sub_vo = NULL; | |
78 | |
79 | |
80 static void set_window(int force_update) | |
81 { | |
82 Window mRoot; | |
83 if ( WinID ) | |
84 { | |
85 XGetGeometry(mDisplay, vo_window, &mRoot, &drwX, &drwY, &drwWidth, | |
86 &drwHeight, &drwBorderWidth, &drwDepth); | |
87 drwX = drwY = 0; | |
88 | |
89 XTranslateCoordinates(mDisplay, vo_window, mRoot, 0, 0, | |
90 &drwcX, &drwcY, &mRoot); | |
91 aspect(&dwidth,&dheight,A_NOZOOM); | |
92 if (!vo_fs) | |
93 mp_msg(MSGT_VO, MSGL_V, "[xvidix] dcx: %d dcy: %d dx: %d dy: %d dw: %d dh: %d\n", | |
94 drwcX, drwcY, drwX, drwY, drwWidth, drwHeight); | |
95 | |
96 /* following stuff copied from vo_xmga.c */ | |
97 } | |
98 else | |
99 { | |
100 aspect(&dwidth,&dheight,A_NOZOOM); | |
101 drwcX=drwX=vo_dx; drwcY=drwY=vo_dy; drwWidth=vo_dwidth; drwHeight=vo_dheight; | |
102 } | |
103 | |
104 #if X11_FULLSCREEN | |
105 if (vo_fs) | |
106 { | |
107 aspect(&dwidth,&dheight,A_ZOOM); | |
108 drwX = (vo_screenwidth - ((int)dwidth > vo_screenwidth ? vo_screenwidth : dwidth)) / 2; | |
109 drwcX = drwX; | |
110 drwY = (vo_screenheight - ((int)dheight > vo_screenheight ? vo_screenheight : dheight)) / 2; | |
111 drwcY = drwY; | |
112 drwWidth = ((int)dwidth > vo_screenwidth ? vo_screenwidth : dwidth); | |
113 drwHeight = ((int)dheight > vo_screenheight ? vo_screenheight : dheight); | |
114 mp_msg(MSGT_VO, MSGL_V, "[xvidix-fs] dcx: %d dcy: %d dx: %d dy: %d dw: %d dh: %d\n", | |
115 drwcX, drwcY, drwX, drwY, drwWidth, drwHeight); | |
116 } | |
117 #endif | |
118 | |
119 vo_dwidth=drwWidth; vo_dheight=drwHeight; | |
120 | |
121 #ifdef HAVE_XINERAMA | |
122 if (XineramaIsActive(mDisplay)) | |
123 { | |
124 XineramaScreenInfo *screens; | |
125 int num_screens; | |
126 int i = 0; | |
127 | |
128 screens = XineramaQueryScreens(mDisplay, &num_screens); | |
129 | |
130 /* find the screen we are on */ | |
131 while (i<num_screens && | |
132 ((screens[i].x_org < (int)drwcX) || | |
133 (screens[i].y_org < (int)drwcY) || | |
134 (screens[i].x_org + screens[i].width >= (int)drwcX) || | |
135 (screens[i].y_org + screens[i].height >= (int)drwcY))) | |
136 { | |
137 i++; | |
138 } | |
139 | |
140 if(i<num_screens) | |
141 { | |
142 /* save the screen we are on */ | |
143 xinerama_screen = i; | |
144 } else { | |
145 /* oops.. couldnt find the screen we are on | |
146 * because the upper left corner left the | |
147 * visual range. assume we are still on the | |
148 * same screen | |
149 */ | |
150 i = xinerama_screen; | |
151 } | |
152 | |
153 /* set drwcX and drwcY to the right values */ | |
154 drwcX = drwcX - screens[i].x_org; | |
155 drwcY = drwcY - screens[i].y_org; | |
156 XFree(screens); | |
157 } | |
158 #endif | |
159 | |
160 if ( vo_panscan > 0.0f && vo_fs ) | |
161 { | |
162 drwcX-=vo_panscan_x >> 1; | |
163 drwcY-=vo_panscan_y >> 1; | |
164 drwX-=vo_panscan_x >> 1; | |
165 drwY-=vo_panscan_y >> 1; | |
166 drwWidth+=vo_panscan_x; | |
167 drwHeight+=vo_panscan_y; | |
168 } | |
169 | |
170 /* set new values in VIDIX */ | |
171 if (force_update || (window_x != drwcX) || (window_y != drwcY) || | |
172 (window_width != drwWidth) || (window_height != drwHeight)) | |
173 { | |
174 mp_win_t w; | |
175 // do a backup of window coordinates | |
176 w.x = window_x = drwcX; | |
177 w.y = window_y = drwcY; | |
178 vo_dx = drwcX; | |
179 vo_dy = drwcY; | |
180 w.w = window_width = drwWidth; | |
181 w.h = window_height = drwHeight; | |
182 | |
183 if(sub_vo->control(VOCTRL_XOVERLAY_SET_WIN,&w) != VO_TRUE) | |
184 mp_msg(MSGT_VO, MSGL_ERR, "xvidx: set_overlay failed\n"); | |
185 | |
186 mp_msg(MSGT_VO, MSGL_V, "[xvidix] window properties: pos: %dx%d, size: %dx%d\n", vo_dx, vo_dy, window_width, window_height); | |
187 } | |
188 | |
189 /* mDrawColorKey: */ | |
190 | |
191 /* fill drawable with specified color */ | |
192 XSetBackground( mDisplay,vo_gc,bgColor ); | |
193 XClearWindow( mDisplay,vo_window ); | |
194 XSetForeground(mDisplay, vo_gc, fgColor); | |
195 XFillRectangle(mDisplay, vo_window, vo_gc, drwX, drwY, drwWidth, | |
196 (vo_fs ? drwHeight - 1 : drwHeight)); | |
197 /* flush, update drawable */ | |
198 XFlush(mDisplay); | |
199 | |
200 return; | |
201 } | |
202 | |
203 /* connect to server, create and map window, | |
204 * allocate colors and (shared) memory | |
205 */ | |
206 static uint32_t config(uint32_t width, uint32_t height, uint32_t d_width, | |
207 uint32_t d_height, uint32_t flags, char *title, uint32_t format) | |
208 { | |
209 XVisualInfo vinfo; | |
210 // XSizeHints hint; | |
211 XSetWindowAttributes xswa; | |
212 unsigned long xswamask; | |
213 XWindowAttributes attribs; | |
214 int window_depth; | |
215 mp_colorkey_t colork; | |
216 char _title[255]; | |
217 | |
218 sprintf(_title,"MPlayer %s X11 Overlay",sub_vo->info->name); | |
219 title = _title; | |
220 | |
221 panscan_init(); | |
222 | |
223 image_height = height; | |
224 image_width = width; | |
225 image_format = format; | |
226 vo_mouse_autohide=1; | |
227 | |
228 aspect_save_orig(width, height); | |
229 aspect_save_prescale(d_width, d_height); | |
230 aspect_save_screenres(vo_screenwidth, vo_screenheight); | |
231 | |
232 vo_dx = 0; | |
233 vo_dy = 0; | |
234 window_width = d_width; | |
235 window_height = d_height; | |
236 | |
237 /* from xmga.c */ | |
238 bgColor = 0x0L; | |
239 switch(vo_depthonscreen) | |
240 { | |
241 case 32: | |
242 case 24: | |
243 fgColor = 0x00ff00ffL; | |
244 break; | |
245 case 16: | |
246 fgColor = 0xf81fL; | |
247 break; | |
248 case 15: | |
249 fgColor = 0x7c1fL; | |
250 break; | |
251 default: | |
252 mp_msg(MSGT_VO, MSGL_ERR, "Sorry, this (%d) color depth is not supported\n", | |
253 vo_depthonscreen); | |
254 } | |
255 | |
256 aspect(&d_width, &d_height, A_NOZOOM); | |
257 | |
258 vo_dx=( vo_screenwidth - d_width ) / 2; vo_dy=( vo_screenheight - d_height ) / 2; | |
259 vo_dwidth=d_width; vo_dheight=d_height; | |
260 | |
261 #ifdef HAVE_NEW_GUI | |
262 if(use_gui) guiGetEvent( guiSetShVideo,0 ); // the GUI will set up / resize the window | |
263 else | |
264 { | |
265 #endif | |
266 | |
267 #ifdef X11_FULLSCREEN | |
268 if ( ( flags&1 )||(flags & 0x04) ) aspect(&d_width, &d_height, A_ZOOM); | |
269 #endif | |
270 dwidth = d_width; | |
271 dheight = d_height; | |
272 /* Make the window */ | |
273 XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &attribs); | |
274 | |
275 /* from vo_x11 */ | |
276 window_depth = attribs.depth; | |
277 if ((window_depth != 15) && (window_depth != 16) && (window_depth != 24) | |
278 && (window_depth != 32)) | |
279 window_depth = 24; | |
280 XMatchVisualInfo(mDisplay, mScreen, window_depth, TrueColor, &vinfo); | |
281 | |
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 xswa.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask | PropertyChangeMask | | |
287 ((WinID==0)?0:(ButtonPressMask | ButtonReleaseMask | PointerMotionMask)); | |
288 xswamask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; | |
289 | |
290 if (WinID >= 0) | |
291 { | |
292 vo_window = WinID ? ((Window)WinID) : RootWindow(mDisplay, mScreen); | |
293 if ( WinID ) | |
294 { | |
295 XUnmapWindow(mDisplay, vo_window); | |
296 XChangeWindowAttributes(mDisplay, vo_window, xswamask, &xswa); | |
297 vo_x11_selectinput_witherr( mDisplay,vo_window,StructureNotifyMask | KeyPressMask | PropertyChangeMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | ExposureMask ); | |
298 } else XSelectInput( mDisplay,vo_window,ExposureMask ); | |
299 } | |
300 else | |
301 { | |
302 if ( vo_window == None ) | |
303 { | |
304 vo_window = XCreateWindow(mDisplay, RootWindow(mDisplay, mScreen), | |
305 vo_dx, vo_dy, window_width, window_height, xswa.border_pixel, | |
306 vinfo.depth, InputOutput, vinfo.visual, xswamask, &xswa); | |
307 | |
308 vo_x11_classhint(mDisplay, vo_window, "xvidix"); | |
309 vo_hidecursor(mDisplay, vo_window); | |
310 vo_x11_sizehint( vo_dx,vo_dy,vo_dwidth,vo_dheight,0 ); | |
311 | |
312 XStoreName(mDisplay, vo_window, title); | |
313 XMapWindow(mDisplay, vo_window); | |
314 | |
315 if ( flags&1 ) vo_x11_fullscreen(); | |
316 | |
317 #ifdef HAVE_XINERAMA | |
318 vo_x11_xinerama_move(mDisplay, vo_window); | |
319 #endif | |
320 } else if ( !(flags&1) ) XMoveResizeWindow( mDisplay,vo_window,vo_dx,vo_dy,vo_dwidth,vo_dheight ); | |
321 } | |
322 | |
323 if ( vo_gc != None ) XFreeGC( mDisplay,vo_gc ); | |
324 vo_gc = XCreateGC(mDisplay, vo_window, GCForeground, &mGCV); | |
325 #ifdef HAVE_NEW_GUI | |
326 } | |
327 #endif | |
328 | |
329 if ( ( !WinID )&&( flags&1 ) ) { vo_dx=0; vo_dy=0; vo_dwidth=vo_screenwidth; vo_dheight=vo_screenheight; vo_fs=1; } | |
330 | |
331 if(sub_vo->config(image_width,image_height,vo_dwidth,vo_dheight, | |
332 flags | VOFLAG_XOVERLAY_SUB_VO,NULL,format)) { | |
333 mp_msg(MSGT_VO, MSGL_ERR, "xover: sub vo config failed\n"); | |
334 return 1; | |
335 } | |
336 colork.x11 = fgColor; | |
337 colork.r = 255; | |
338 colork.g = 0; | |
339 colork.b = 255; | |
340 if(sub_vo->control(VOCTRL_XOVERLAY_SET_COLORKEY,&colork) != VO_TRUE) | |
341 mp_msg(MSGT_VO, MSGL_WARN, "xover: set_colorkey failed\n"); | |
342 | |
343 set_window(1); | |
344 | |
345 XFlush(mDisplay); | |
346 XSync(mDisplay, False); | |
347 | |
348 panscan_calc(); | |
349 | |
350 saver_off(mDisplay); /* turning off screen saver */ | |
351 | |
352 vo_config_count++; | |
353 | |
354 return(0); | |
355 } | |
356 | |
357 static void check_events(void) | |
358 { | |
359 const int event = vo_x11_check_events(mDisplay); | |
360 | |
361 if ((event & VO_EVENT_RESIZE) || (event & VO_EVENT_EXPOSE)) | |
362 set_window(0); | |
363 sub_vo->check_events(); | |
364 return; | |
365 } | |
366 | |
367 /* draw_osd, flip_page, draw_slice, draw_frame should be | |
368 overwritten with vidix functions (vosub_vidix.c) */ | |
369 static void draw_osd(void) | |
370 { | |
371 mp_msg(MSGT_VO, MSGL_FATAL, "xover error: didn't used sub vo draw_osd!\n"); | |
372 } | |
373 | |
374 static void flip_page(void) | |
375 { | |
376 mp_msg(MSGT_VO, MSGL_FATAL, "xover error: didn't used sub vo flip_page!\n"); | |
377 } | |
378 | |
379 static uint32_t draw_slice(uint8_t *src[], int stride[], | |
380 int w, int h, int x, int y) | |
381 { | |
382 UNUSED(src); | |
383 UNUSED(stride); | |
384 UNUSED(w); | |
385 UNUSED(h); | |
386 UNUSED(x); | |
387 UNUSED(y); | |
388 mp_msg(MSGT_VO, MSGL_FATAL, "xover error: didn't used sub vo draw_slice!\n"); | |
389 return 1; | |
390 } | |
391 | |
392 static uint32_t draw_frame(uint8_t *src[]) | |
393 { | |
394 UNUSED(src); | |
395 mp_msg(MSGT_VO, MSGL_FATAL, "xover error: didn't used sub vo draw_frame!\n"); | |
396 return 1; | |
397 } | |
398 | |
399 static void uninit(void) | |
400 { | |
401 if(!vo_config_count) return; | |
402 if(sub_vo) sub_vo->uninit(); | |
403 sub_vo = NULL; | |
404 saver_on(mDisplay); /* screen saver back on */ | |
405 vo_x11_uninit(); | |
406 // Restore our callbacks | |
407 video_out_xover.draw_frame = draw_frame; | |
408 video_out_xover.draw_slice = draw_slice; | |
409 video_out_xover.flip_page = flip_page; | |
410 video_out_xover.draw_osd = draw_osd; | |
411 } | |
412 | |
413 static uint32_t preinit(const char *arg) | |
414 { | |
415 int i; | |
416 | |
417 if(!arg) { | |
418 mp_msg(MSGT_VO, MSGL_ERR, "VO XOverlay need a subdriver\n"); | |
419 return 1; | |
420 } | |
421 | |
422 for(i = 0 ; video_out_drivers[i] != NULL ; i++) { | |
423 if(!strcmp(video_out_drivers[i]->info->short_name,arg) && | |
424 strcmp(video_out_drivers[i]->info->short_name,"xover")) | |
425 break; | |
426 } | |
427 if(!video_out_drivers[i]) { | |
428 mp_msg(MSGT_VO, MSGL_ERR, "VO XOverlay: Subdriver %s not found\n"); | |
429 return 1; | |
430 } | |
431 if(video_out_drivers[i]->control(VOCTRL_XOVERLAY_SUPPORT,NULL) != VO_TRUE) { | |
432 mp_msg(MSGT_VO, MSGL_ERR, "VO XOverlay: %s doesn't support XOverlay\n"); | |
433 return 1; | |
434 } | |
435 // X11 init | |
436 if (!vo_init()) return VO_FALSE; | |
437 if(video_out_drivers[i]->preinit(NULL)) { | |
438 mp_msg(MSGT_VO, MSGL_ERR, "VO XOverlay: Subvo init failed\n"); | |
439 return 1; | |
440 } | |
441 sub_vo = video_out_drivers[i]; | |
442 // Setup the sub vo callbacks | |
443 video_out_xover.draw_frame = sub_vo->draw_frame; | |
444 video_out_xover.draw_slice = sub_vo->draw_slice; | |
445 video_out_xover.flip_page = sub_vo->flip_page; | |
446 video_out_xover.draw_osd = sub_vo->draw_osd; | |
447 return 0; | |
448 } | |
449 | |
450 static uint32_t control(uint32_t request, void *data, ...) | |
451 { | |
452 if(!sub_vo) return VO_ERROR; | |
453 switch (request) { | |
454 case VOCTRL_GUISUPPORT: | |
455 return VO_TRUE; | |
456 case VOCTRL_GET_PANSCAN: | |
457 if ( !vo_config_count || !vo_fs ) return VO_FALSE; | |
458 return VO_TRUE; | |
459 case VOCTRL_FULLSCREEN: | |
460 vo_x11_fullscreen(); | |
461 case VOCTRL_SET_PANSCAN: | |
462 if ( vo_fs && ( vo_panscan != vo_panscan_amount ) ) | |
463 { | |
464 panscan_calc(); | |
465 set_window(0); | |
466 } | |
467 return VO_TRUE; | |
468 default: | |
469 // Safe atm bcs nothing use more than 1 arg | |
470 return sub_vo->control(request,data); | |
471 } | |
472 return VO_NOTIMPL; | |
473 } |