1 /* vo_xv.c, X11 Xv interface */
3 // Number of buffers _FOR_DOUBLEBUFFERING_MODE_
4 // Use option -double to enable double buffering! (default: single buffer)
26 #include "video_out.h"
27 #include "video_out_internal.h"
31 #include <X11/Xutil.h>
34 #include "x11_common.h"
36 #include "fastmemcpy.h"
40 #include "subopt-helper.h"
42 #include "input/input.h"
45 #include "gui/interface.h"
48 #include "libavutil/common.h"
50 static const vo_info_t info
= {
53 "Gerd Knorr <kraxel@goldbach.in-berlin.de> and others",
57 const LIBVO_EXTERN(xv
)
61 #include <X11/extensions/XShm.h>
63 static XShmSegmentInfo Shminfo
[NUM_BUFFERS
];
64 static int Shmem_Flag
;
67 // Note: depends on the inclusion of X11/extensions/XShm.h
68 #include <X11/extensions/Xv.h>
69 #include <X11/extensions/Xvlib.h>
71 // FIXME: dynamically allocate this stuff
72 static void allocate_xvimage(int);
73 static unsigned int ver
, rel
, req
, ev
, err
;
74 static unsigned int formats
, adaptors
, xv_format
;
75 static XvAdaptorInfo
*ai
= NULL
;
76 static XvImageFormatValues
*fo
=NULL
;
78 static int current_buf
= 0;
79 static int current_ip_buf
= 0;
80 static int num_buffers
= 1; // default
81 static int visible_buf
= -1; // -1 means: no buffer was drawn yet
82 static XvImage
*xvimage
[NUM_BUFFERS
];
85 static uint32_t image_width
;
86 static uint32_t image_height
;
87 static uint32_t image_format
;
93 static uint32_t drwX
, drwY
, drwBorderWidth
, drwDepth
;
94 static uint32_t max_width
= 0, max_height
= 0; // zero means: not set
96 static void (*draw_alpha_fnc
) (int x0
, int y0
, int w
, int h
,
97 unsigned char *src
, unsigned char *srca
,
100 static void draw_alpha_yv12(int x0
, int y0
, int w
, int h
,
101 unsigned char *src
, unsigned char *srca
,
104 x0
+= image_width
* (vo_panscan_x
>> 1) / (vo_dwidth
+ vo_panscan_x
);
105 vo_draw_alpha_yv12(w
, h
, src
, srca
, stride
,
106 xvimage
[current_buf
]->data
+
107 xvimage
[current_buf
]->offsets
[0] +
108 xvimage
[current_buf
]->pitches
[0] * y0
+ x0
,
109 xvimage
[current_buf
]->pitches
[0]);
112 static void draw_alpha_yuy2(int x0
, int y0
, int w
, int h
,
113 unsigned char *src
, unsigned char *srca
,
116 x0
+= image_width
* (vo_panscan_x
>> 1) / (vo_dwidth
+ vo_panscan_x
);
117 vo_draw_alpha_yuy2(w
, h
, src
, srca
, stride
,
118 xvimage
[current_buf
]->data
+
119 xvimage
[current_buf
]->offsets
[0] +
120 xvimage
[current_buf
]->pitches
[0] * y0
+ 2 * x0
,
121 xvimage
[current_buf
]->pitches
[0]);
124 static void draw_alpha_uyvy(int x0
, int y0
, int w
, int h
,
125 unsigned char *src
, unsigned char *srca
,
128 x0
+= image_width
* (vo_panscan_x
>> 1) / (vo_dwidth
+ vo_panscan_x
);
129 vo_draw_alpha_yuy2(w
, h
, src
, srca
, stride
,
130 xvimage
[current_buf
]->data
+
131 xvimage
[current_buf
]->offsets
[0] +
132 xvimage
[current_buf
]->pitches
[0] * y0
+ 2 * x0
+ 1,
133 xvimage
[current_buf
]->pitches
[0]);
136 static void draw_alpha_null(int x0
, int y0
, int w
, int h
,
137 unsigned char *src
, unsigned char *srca
,
143 static void deallocate_xvimage(int foo
);
145 static void calc_drwXY(uint32_t *drwX
, uint32_t *drwY
) {
148 aspect(&vo_dwidth
, &vo_dheight
, A_ZOOM
);
149 vo_dwidth
= FFMIN(vo_dwidth
, vo_screenwidth
);
150 vo_dheight
= FFMIN(vo_dheight
, vo_screenheight
);
151 *drwX
= (vo_screenwidth
- vo_dwidth
) / 2;
152 *drwY
= (vo_screenheight
- vo_dheight
) / 2;
153 mp_msg(MSGT_VO
, MSGL_V
, "[xv-fs] dx: %d dy: %d dw: %d dh: %d\n",
154 *drwX
, *drwY
, vo_dwidth
, vo_dheight
);
155 } else if (WinID
== 0) {
162 * connect to server, create and map window,
163 * allocate colors and (shared) memory
165 static int config(uint32_t width
, uint32_t height
, uint32_t d_width
,
166 uint32_t d_height
, uint32_t flags
, char *title
,
172 XSetWindowAttributes xswa
;
173 XWindowAttributes attribs
;
174 unsigned long xswamask
;
179 unsigned int modeline_width
, modeline_height
;
180 static uint32_t vm_width
;
181 static uint32_t vm_height
;
184 image_height
= height
;
186 image_format
= format
;
188 if ((max_width
!= 0 && max_height
!= 0) &&
189 (image_width
> max_width
|| image_height
> max_height
))
191 mp_msg( MSGT_VO
, MSGL_ERR
, MSGTR_VO_XV_ImagedimTooHigh
,
192 image_width
, image_height
, max_width
, max_height
);
196 vo_mouse_autohide
= 1;
202 if (flags
& VOFLAG_MODESWITCHING
)
205 flip_flag
= flags
& VOFLAG_FLIPPING
;
207 vo_doublebuffering
? (vo_directrendering
? NUM_BUFFERS
: 2) : 1;
209 /* check image formats */
214 for (i
= 0; i
< formats
; i
++)
216 mp_msg(MSGT_VO
, MSGL_V
,
217 "Xvideo image format: 0x%x (%4.4s) %s\n", fo
[i
].id
,
219 (fo
[i
].format
== XvPacked
) ? "packed" : "planar");
220 if (fo
[i
].id
== format
)
221 xv_format
= fo
[i
].id
;
229 guiGetEvent(guiSetShVideo
, 0); // the GUI will set up / resize the window
235 hint
.width
= d_width
;
236 hint
.height
= d_height
;
240 if ((d_width
== 0) && (d_height
== 0))
242 vm_width
= image_width
;
243 vm_height
= image_height
;
247 vm_height
= d_height
;
249 vo_vm_switch(vm_width
, vm_height
, &modeline_width
,
251 hint
.x
= (vo_screenwidth
- modeline_width
) / 2;
252 hint
.y
= (vo_screenheight
- modeline_height
) / 2;
253 hint
.width
= modeline_width
;
254 hint
.height
= modeline_height
;
255 aspect_save_screenres(modeline_width
, modeline_height
);
258 hint
.flags
= PPosition
| PSize
/* | PBaseSize */ ;
259 hint
.base_width
= hint
.width
;
260 hint
.base_height
= hint
.height
;
261 XGetWindowAttributes(mDisplay
, DefaultRootWindow(mDisplay
),
263 depth
= attribs
.depth
;
264 if (depth
!= 15 && depth
!= 16 && depth
!= 24 && depth
!= 32)
266 XMatchVisualInfo(mDisplay
, mScreen
, depth
, TrueColor
, &vinfo
);
268 xswa
.background_pixel
= 0;
269 if (xv_ck_info
.method
== CK_METHOD_BACKGROUND
)
271 xswa
.background_pixel
= xv_colorkey
;
273 xswa
.border_pixel
= 0;
274 xswamask
= CWBackPixel
| CWBorderPixel
;
278 vo_window
= WinID
? ((Window
) WinID
) : mRootWin
;
281 XUnmapWindow(mDisplay
, vo_window
);
282 XChangeWindowAttributes(mDisplay
, vo_window
, xswamask
,
284 vo_x11_selectinput_witherr(mDisplay
, vo_window
,
285 StructureNotifyMask
|
292 XMapWindow(mDisplay
, vo_window
);
293 XGetGeometry(mDisplay
, vo_window
, &mRoot
,
294 &drwX
, &drwY
, &vo_dwidth
, &vo_dheight
,
295 &drwBorderWidth
, &drwDepth
);
296 if (vo_dwidth
<= 0) vo_dwidth
= d_width
;
297 if (vo_dheight
<= 0) vo_dheight
= d_height
;
298 aspect_save_prescale(vo_dwidth
, vo_dheight
);
302 vo_x11_create_vo_window(&vinfo
, vo_dx
, vo_dy
, d_width
, d_height
,
303 flags
, CopyFromParent
, "xv", title
);
304 XChangeWindowAttributes(mDisplay
, vo_window
, xswamask
, &xswa
);
308 XFreeGC(mDisplay
, vo_gc
);
309 vo_gc
= XCreateGC(mDisplay
, vo_window
, 0L, &xgcv
);
310 XSync(mDisplay
, False
);
314 /* Grab the mouse pointer in our window */
316 XGrabPointer(mDisplay
, vo_window
, True
, 0,
317 GrabModeAsync
, GrabModeAsync
,
318 vo_window
, None
, CurrentTime
);
319 XSetInputFocus(mDisplay
, vo_window
, RevertToNone
, CurrentTime
);
324 mp_msg(MSGT_VO
, MSGL_V
, "using Xvideo port %d for hw scaling\n",
332 draw_alpha_fnc
= draw_alpha_yv12
;
336 draw_alpha_fnc
= draw_alpha_yuy2
;
339 draw_alpha_fnc
= draw_alpha_uyvy
;
342 draw_alpha_fnc
= draw_alpha_null
;
346 for (current_buf
= 0; current_buf
< num_buffers
; ++current_buf
)
347 deallocate_xvimage(current_buf
);
349 for (current_buf
= 0; current_buf
< num_buffers
; ++current_buf
)
350 allocate_xvimage(current_buf
);
355 aspect(&vo_dwidth
, &vo_dheight
, A_NOZOOM
);
356 if ((flags
& VOFLAG_FULLSCREEN
) && WinID
<= 0) vo_fs
= 1;
357 calc_drwXY(&drwX
, &drwY
);
361 vo_xv_draw_colorkey(drwX
- (vo_panscan_x
>> 1),
362 drwY
- (vo_panscan_y
>> 1),
363 vo_dwidth
+ vo_panscan_x
- 1,
364 vo_dheight
+ vo_panscan_y
- 1);
366 mp_msg(MSGT_VO
, MSGL_V
, "[xv] dx: %d dy: %d dw: %d dh: %d\n", drwX
,
367 drwY
, vo_dwidth
, vo_dheight
);
370 vo_x11_setlayer(mDisplay
, vo_window
, vo_ontop
);
375 static void allocate_xvimage(int foo
)
378 * allocate XvImages. FIXME: no error checking, without
379 * mit-shm this will bomb... trzing to fix ::atmos
382 if (mLocalDisplay
&& XShmQueryExtension(mDisplay
))
387 mp_msg(MSGT_VO
, MSGL_INFO
,
388 MSGTR_LIBVO_XV_SharedMemoryNotSupported
);
393 (XvImage
*) XvShmCreateImage(mDisplay
, xv_port
, xv_format
,
394 NULL
, image_width
, image_height
,
398 shmget(IPC_PRIVATE
, xvimage
[foo
]->data_size
, IPC_CREAT
| 0777);
399 Shminfo
[foo
].shmaddr
= (char *) shmat(Shminfo
[foo
].shmid
, 0, 0);
400 Shminfo
[foo
].readOnly
= False
;
402 xvimage
[foo
]->data
= Shminfo
[foo
].shmaddr
;
403 XShmAttach(mDisplay
, &Shminfo
[foo
]);
404 XSync(mDisplay
, False
);
405 shmctl(Shminfo
[foo
].shmid
, IPC_RMID
, 0);
410 (XvImage
*) XvCreateImage(mDisplay
, xv_port
, xv_format
, NULL
,
411 image_width
, image_height
);
412 xvimage
[foo
]->data
= malloc(xvimage
[foo
]->data_size
);
413 XSync(mDisplay
, False
);
415 memset(xvimage
[foo
]->data
, 128, xvimage
[foo
]->data_size
);
419 static void deallocate_xvimage(int foo
)
424 XShmDetach(mDisplay
, &Shminfo
[foo
]);
425 shmdt(Shminfo
[foo
].shmaddr
);
429 free(xvimage
[foo
]->data
);
433 XSync(mDisplay
, False
);
437 static inline void put_xvimage( XvImage
* xvi
)
442 XvShmPutImage(mDisplay
, xv_port
, vo_window
, vo_gc
,
443 xvi
, 0, 0, image_width
,
444 image_height
, drwX
- (vo_panscan_x
>> 1),
445 drwY
- (vo_panscan_y
>> 1), vo_dwidth
+ vo_panscan_x
,
446 vo_dheight
+ vo_panscan_y
,
451 XvPutImage(mDisplay
, xv_port
, vo_window
, vo_gc
,
452 xvi
, 0, 0, image_width
, image_height
,
453 drwX
- (vo_panscan_x
>> 1), drwY
- (vo_panscan_y
>> 1),
454 vo_dwidth
+ vo_panscan_x
,
455 vo_dheight
+ vo_panscan_y
);
459 static void check_events(void)
461 int e
= vo_x11_check_events(mDisplay
);
463 if (e
& VO_EVENT_RESIZE
)
465 XGetGeometry(mDisplay
, vo_window
, &mRoot
, &drwX
, &drwY
, &vo_dwidth
,
466 &vo_dheight
, &drwBorderWidth
, &drwDepth
);
467 mp_msg(MSGT_VO
, MSGL_V
, "[xv] dx: %d dy: %d dw: %d dh: %d\n", drwX
,
468 drwY
, vo_dwidth
, vo_dheight
);
470 calc_drwXY(&drwX
, &drwY
);
473 if (e
& VO_EVENT_EXPOSE
|| e
& VO_EVENT_RESIZE
)
475 vo_xv_draw_colorkey(drwX
- (vo_panscan_x
>> 1),
476 drwY
- (vo_panscan_y
>> 1),
477 vo_dwidth
+ vo_panscan_x
- 1,
478 vo_dheight
+ vo_panscan_y
- 1);
481 if ((e
& VO_EVENT_EXPOSE
|| e
& VO_EVENT_RESIZE
) && int_pause
)
483 /* did we already draw a buffer */
484 if ( visible_buf
!= -1 )
486 /* redraw the last visible buffer */
487 put_xvimage( xvimage
[visible_buf
] );
492 static void draw_osd(void)
494 vo_draw_text(image_width
-
495 image_width
* vo_panscan_x
/ (vo_dwidth
+ vo_panscan_x
),
496 image_height
, draw_alpha_fnc
);
499 static void flip_page(void)
501 put_xvimage( xvimage
[current_buf
] );
503 /* remember the currently visible buffer */
504 visible_buf
= current_buf
;
509 vo_directrendering
? 0 : ((current_buf
+ 1) % num_buffers
);
512 XSync(mDisplay
, False
);
516 static int draw_slice(uint8_t * image
[], int stride
[], int w
, int h
,
521 dst
= xvimage
[current_buf
]->data
+ xvimage
[current_buf
]->offsets
[0] +
522 xvimage
[current_buf
]->pitches
[0] * y
+ x
;
523 memcpy_pic(dst
, image
[0], w
, h
, xvimage
[current_buf
]->pitches
[0],
531 dst
= xvimage
[current_buf
]->data
+ xvimage
[current_buf
]->offsets
[1] +
532 xvimage
[current_buf
]->pitches
[1] * y
+ x
;
533 if (image_format
!= IMGFMT_YV12
)
534 memcpy_pic(dst
, image
[1], w
, h
, xvimage
[current_buf
]->pitches
[1],
537 memcpy_pic(dst
, image
[2], w
, h
, xvimage
[current_buf
]->pitches
[1],
540 dst
= xvimage
[current_buf
]->data
+ xvimage
[current_buf
]->offsets
[2] +
541 xvimage
[current_buf
]->pitches
[2] * y
+ x
;
542 if (image_format
== IMGFMT_YV12
)
543 memcpy_pic(dst
, image
[1], w
, h
, xvimage
[current_buf
]->pitches
[1],
546 memcpy_pic(dst
, image
[2], w
, h
, xvimage
[current_buf
]->pitches
[1],
552 static int draw_frame(uint8_t * src
[])
557 static uint32_t draw_image(mp_image_t
* mpi
)
559 if (mpi
->flags
& MP_IMGFLAG_DIRECT
)
562 current_buf
= (int) (mpi
->priv
); // hack!
565 if (mpi
->flags
& MP_IMGFLAG_DRAW_CALLBACK
)
566 return VO_TRUE
; // done
567 if (mpi
->flags
& MP_IMGFLAG_PLANAR
)
569 draw_slice(mpi
->planes
, mpi
->stride
, mpi
->w
, mpi
->h
, 0, 0);
572 if (mpi
->flags
& MP_IMGFLAG_YUV
)
575 memcpy_pic(xvimage
[current_buf
]->data
+
576 xvimage
[current_buf
]->offsets
[0], mpi
->planes
[0],
577 mpi
->w
* (mpi
->bpp
/ 8), mpi
->h
,
578 xvimage
[current_buf
]->pitches
[0], mpi
->stride
[0]);
581 return VO_FALSE
; // not (yet) supported
584 static uint32_t get_image(mp_image_t
* mpi
)
586 int buf
= current_buf
; // we shouldn't change current_buf unless we do DR!
588 if (mpi
->type
== MP_IMGTYPE_STATIC
&& num_buffers
> 1)
589 return VO_FALSE
; // it is not static
590 if (mpi
->imgfmt
!= image_format
)
591 return VO_FALSE
; // needs conversion :(
592 // if(mpi->flags&MP_IMGFLAG_READABLE) return VO_FALSE; // slow video ram
593 if (mpi
->flags
& MP_IMGFLAG_READABLE
&&
594 (mpi
->type
== MP_IMGTYPE_IPB
|| mpi
->type
== MP_IMGTYPE_IP
))
596 // reference (I/P) frame of IP or IPB:
598 return VO_FALSE
; // not enough
600 // for IPB with 2 buffers we can DR only one of the 2 P frames:
601 if (mpi
->type
== MP_IMGTYPE_IPB
&& num_buffers
< 3
604 buf
= current_ip_buf
;
605 if (mpi
->type
== MP_IMGTYPE_IPB
)
606 ++buf
; // preserve space for B
608 if (mpi
->height
> xvimage
[buf
]->height
)
609 return VO_FALSE
; //buffer to small
610 if (mpi
->width
* (mpi
->bpp
/ 8) > xvimage
[buf
]->pitches
[0])
611 return VO_FALSE
; //buffer to small
612 if ((mpi
->flags
& (MP_IMGFLAG_ACCEPT_STRIDE
| MP_IMGFLAG_ACCEPT_WIDTH
))
613 || (mpi
->width
* (mpi
->bpp
/ 8) == xvimage
[buf
]->pitches
[0]))
617 xvimage
[current_buf
]->data
+ xvimage
[current_buf
]->offsets
[0];
618 mpi
->stride
[0] = xvimage
[current_buf
]->pitches
[0];
619 mpi
->width
= mpi
->stride
[0] / (mpi
->bpp
/ 8);
620 if (mpi
->flags
& MP_IMGFLAG_PLANAR
)
622 if (mpi
->flags
& MP_IMGFLAG_SWAPPED
)
626 xvimage
[current_buf
]->data
+
627 xvimage
[current_buf
]->offsets
[1];
629 xvimage
[current_buf
]->data
+
630 xvimage
[current_buf
]->offsets
[2];
631 mpi
->stride
[1] = xvimage
[current_buf
]->pitches
[1];
632 mpi
->stride
[2] = xvimage
[current_buf
]->pitches
[2];
637 xvimage
[current_buf
]->data
+
638 xvimage
[current_buf
]->offsets
[2];
640 xvimage
[current_buf
]->data
+
641 xvimage
[current_buf
]->offsets
[1];
642 mpi
->stride
[1] = xvimage
[current_buf
]->pitches
[2];
643 mpi
->stride
[2] = xvimage
[current_buf
]->pitches
[1];
646 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
647 mpi
->priv
= (void *) current_buf
;
648 // printf("mga: get_image() SUCCESS -> Direct Rendering ENABLED\n");
654 static int query_format(uint32_t format
)
657 int flag
= VFCAP_CSP_SUPPORTED
| VFCAP_CSP_SUPPORTED_BY_HW
| VFCAP_HWSCALE_UP
| VFCAP_HWSCALE_DOWN
| VFCAP_OSD
| VFCAP_ACCEPT_STRIDE
; // FIXME! check for DOWN
659 /* check image formats */
660 for (i
= 0; i
< formats
; i
++)
662 if (fo
[i
].id
== format
)
663 return flag
; //xv_format = fo[i].id;
668 static void uninit(void)
672 if (!vo_config_count
)
675 XvFreeAdaptorInfo(ai
);
681 for (i
= 0; i
< num_buffers
; i
++)
682 deallocate_xvimage(i
);
684 vo_vm_close(mDisplay
);
686 mp_input_rm_event_fd(ConnectionNumber(mDisplay
));
690 static int preinit(const char *arg
)
695 strarg_t ck_src_arg
= { 0, NULL
};
696 strarg_t ck_method_arg
= { 0, NULL
};
701 /* name arg type arg var test */
702 { "port", OPT_ARG_INT
, &xv_port
, (opt_test_f
)int_pos
},
703 { "adaptor", OPT_ARG_INT
, &xv_adaptor
, (opt_test_f
)int_non_neg
},
704 { "ck", OPT_ARG_STR
, &ck_src_arg
, xv_test_ck
},
705 { "ck-method", OPT_ARG_STR
, &ck_method_arg
, xv_test_ckm
},
711 /* parse suboptions */
712 if ( subopt_parse( arg
, subopts
) != 0 )
717 /* modify colorkey settings according to the given options */
718 xv_setup_colorkeyhandling( ck_method_arg
.str
, ck_src_arg
.str
);
723 /* check for Xvideo extension */
724 if (Success
!= XvQueryExtension(mDisplay
, &ver
, &rel
, &req
, &ev
, &err
))
726 mp_msg(MSGT_VO
, MSGL_ERR
,
727 MSGTR_LIBVO_XV_XvNotSupportedByX11
);
731 /* check for Xvideo support */
733 XvQueryAdaptors(mDisplay
, DefaultRootWindow(mDisplay
), &adaptors
,
736 mp_msg(MSGT_VO
, MSGL_ERR
, MSGTR_LIBVO_XV_XvQueryAdaptorsFailed
);
745 for (port_found
= 0, i
= 0; !port_found
&& i
< adaptors
; i
++)
747 if ((ai
[i
].type
& XvInputMask
) && (ai
[i
].type
& XvImageMask
))
749 for (xv_p
= ai
[i
].base_id
;
750 xv_p
< ai
[i
].base_id
+ ai
[i
].num_ports
; ++xv_p
)
762 if (XvGrabPort(mDisplay
, xv_port
, CurrentTime
))
766 mp_msg(MSGT_VO
, MSGL_WARN
,
767 MSGTR_LIBVO_XV_InvalidPortParameter
);
772 for (i
= 0; i
< adaptors
&& xv_port
== 0; i
++)
774 /* check if adaptor number has been specified */
775 if (xv_adaptor
!= -1 && xv_adaptor
!= i
)
778 if ((ai
[i
].type
& XvInputMask
) && (ai
[i
].type
& XvImageMask
))
780 for (xv_p
= ai
[i
].base_id
;
781 xv_p
< ai
[i
].base_id
+ ai
[i
].num_ports
; ++xv_p
)
782 if (!XvGrabPort(mDisplay
, xv_p
, CurrentTime
))
785 mp_msg(MSGT_VO
, MSGL_V
,
786 "[VO_XV] Using Xv Adapter #%d (%s)\n",
791 mp_msg(MSGT_VO
, MSGL_WARN
,
792 MSGTR_LIBVO_XV_CouldNotGrabPort
, (int) xv_p
);
800 mp_msg(MSGT_VO
, MSGL_ERR
,
801 MSGTR_LIBVO_XV_CouldNotFindFreePort
);
803 mp_msg(MSGT_VO
, MSGL_ERR
,
804 MSGTR_LIBVO_XV_NoXvideoSupport
);
808 if ( !vo_xv_init_colorkey() )
810 return -1; // bail out, colorkey setup failed
812 vo_xv_enable_vsync();
813 vo_xv_get_max_img_dim( &max_width
, &max_height
);
815 fo
= XvListImageFormats(mDisplay
, xv_port
, (int *) &formats
);
817 mp_input_add_event_fd(ConnectionNumber(mDisplay
), check_events
);
821 static int control(uint32_t request
, void *data
, ...)
826 return int_pause
= 1;
828 return int_pause
= 0;
829 case VOCTRL_QUERY_FORMAT
:
830 return query_format(*((uint32_t *) data
));
831 case VOCTRL_GET_IMAGE
:
832 return get_image(data
);
833 case VOCTRL_DRAW_IMAGE
:
834 return draw_image(data
);
835 case VOCTRL_GUISUPPORT
:
837 case VOCTRL_GET_PANSCAN
:
838 if (!vo_config_count
|| !vo_fs
)
841 case VOCTRL_FULLSCREEN
:
843 /* indended, fallthrough to update panscan on fullscreen/windowed switch */
844 case VOCTRL_SET_PANSCAN
:
845 if ((vo_fs
&& (vo_panscan
!= vo_panscan_amount
))
846 || (!vo_fs
&& vo_panscan_amount
))
848 int old_y
= vo_panscan_y
;
852 if (old_y
!= vo_panscan_y
)
854 vo_x11_clearwindow_part(mDisplay
, vo_window
,
855 vo_dwidth
+ vo_panscan_x
- 1,
856 vo_dheight
+ vo_panscan_y
- 1,
858 vo_xv_draw_colorkey(drwX
- (vo_panscan_x
>> 1),
859 drwY
- (vo_panscan_y
>> 1),
860 vo_dwidth
+ vo_panscan_x
- 1,
861 vo_dheight
+ vo_panscan_y
- 1);
866 case VOCTRL_SET_EQUALIZER
:
872 value
= va_arg(ap
, int);
876 return vo_xv_set_eq(xv_port
, data
, value
);
878 case VOCTRL_GET_EQUALIZER
:
884 value
= va_arg(ap
, int *);
888 return vo_xv_get_eq(xv_port
, data
, value
);
893 case VOCTRL_UPDATE_SCREENINFO
:
894 update_xinerama_info();