From 4044754d24c677ed82016b5b8f3011686d7d2ff6 Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Wed, 2 Jan 2013 12:55:52 +0100 Subject: vo_x11, vo_xv: XShmCompletion event support This fixes OSD flicker with vo_xv at high frame rates. --- video/out/vo_x11.c | 36 ++++++++++++++++++++++++++++-------- video/out/vo_xv.c | 41 +++++++++++++++++++++++++++++++++-------- video/out/x11_common.c | 5 +++++ video/out/x11_common.h | 7 +++++++ 4 files changed, 73 insertions(+), 16 deletions(-) (limited to 'video') diff --git a/video/out/vo_x11.c b/video/out/vo_x11.c index c45dac5bdd..94ca221060 100644 --- a/video/out/vo_x11.c +++ b/video/out/vo_x11.c @@ -49,6 +49,7 @@ #define MODE_BGR 0x2 #include "core/mp_msg.h" +#include "osdep/timer.h" extern int sws_flags; @@ -92,10 +93,10 @@ struct priv { #ifdef HAVE_SHM int Shmem_Flag; + int Shm_Warned_Slow; XShmSegmentInfo Shminfo[1]; int gXErrorFlag; - int CompletionType; #endif }; @@ -120,15 +121,15 @@ static void getMyXImage(struct priv *p) { struct vo *vo = p->vo; #ifdef HAVE_SHM - if (vo->x11->display_is_local && XShmQueryExtension(vo->x11->display)) + if (vo->x11->display_is_local && XShmQueryExtension(vo->x11->display)) { p->Shmem_Flag = 1; - else { + vo->x11->ShmCompletionEvent = XShmGetEventBase(vo->x11->display) + + ShmCompletion; + } else { p->Shmem_Flag = 0; mp_msg(MSGT_VO, MSGL_WARN, "Shared memory not supported\nReverting to normal Xlib\n"); } - if (p->Shmem_Flag) - p->CompletionType = XShmGetEventBase(vo->x11->display) + ShmCompletion; if (p->Shmem_Flag) { p->myximage = @@ -409,6 +410,7 @@ static void Display_Image(struct priv *p, XImage *myximage, uint8_t *ImageData) XShmPutImage(vo->x11->display, vo->x11->window, vo->x11->vo_gc, p->myximage, 0, 0, x, y, p->dst_width, p->myximage->height, True); + vo->x11->ShmCompletionWaitCount++; } else #endif { @@ -458,6 +460,25 @@ static mp_image_t *get_screenshot(struct vo *vo) return res; } +static void wait_for_completion(struct vo *vo, int max_outstanding) +{ +#ifdef HAVE_SHM + struct priv *ctx = vo->priv; + struct vo_x11_state *x11 = vo->x11; + if (ctx->Shmem_Flag) { + while (x11->ShmCompletionWaitCount > max_outstanding) { + if (!ctx->Shm_Warned_Slow) { + mp_msg(MSGT_VO, MSGL_WARN, "[VO_X11] X11 can't keep up! Waiting" + " for XShm completion events...\n"); + ctx->Shm_Warned_Slow = 1; + } + usec_sleep(1000); + check_events(vo); + } + } +#endif +} + static void flip_page(struct vo *vo) { struct priv *p = vo->priv; @@ -471,6 +492,8 @@ static void draw_image(struct vo *vo, mp_image_t *mpi) uint8_t *dst[MP_MAX_PLANES] = {NULL}; int dstStride[MP_MAX_PLANES] = {0}; + wait_for_completion(vo, 0); + if ((p->old_vo_dwidth != vo->dwidth || p->old_vo_dheight != vo->dheight) /*&& y==0 */ && p->zoomFlag) { @@ -635,9 +658,6 @@ const struct vo_driver video_out_x11 = { .srcH = -1, .old_vo_dwidth = -1, .old_vo_dheight = -1, -#ifdef HAVE_SHM - .CompletionType = -1, -#endif }, .preinit = preinit, .query_format = query_format, diff --git a/video/out/vo_xv.c b/video/out/vo_xv.c index de1f3a4855..ea4fa5a015 100644 --- a/video/out/vo_xv.c +++ b/video/out/vo_xv.c @@ -55,6 +55,7 @@ #include "aspect.h" #include "video/csputils.h" #include "core/subopt-helper.h" +#include "osdep/timer.h" static const vo_info_t info = { "X11/Xv", @@ -83,9 +84,10 @@ struct xvctx { struct mp_rect dst_rect; uint32_t max_width, max_height; // zero means: not set int mode_switched; + int Shmem_Flag; #ifdef HAVE_SHM XShmSegmentInfo Shminfo[2]; - int Shmem_Flag; + int Shm_Warned_Slow; #endif }; @@ -255,9 +257,11 @@ static void allocate_xvimage(struct vo *vo, int foo) // align it for faster OSD rendering (draw_bmp.c swscale usage) int aligned_w = FFALIGN(ctx->image_width, 32); #ifdef HAVE_SHM - if (x11->display_is_local && XShmQueryExtension(x11->display)) + if (x11->display_is_local && XShmQueryExtension(x11->display)) { ctx->Shmem_Flag = 1; - else { + x11->ShmCompletionEvent = XShmGetEventBase(x11->display) + + ShmCompletion; + } else { ctx->Shmem_Flag = 0; mp_tmsg(MSGT_VO, MSGL_INFO, "[VO_XV] Shared memory not supported\nReverting to normal Xv.\n"); } @@ -325,7 +329,8 @@ static inline void put_xvimage(struct vo *vo, XvImage *xvi) XvShmPutImage(x11->display, x11->xv_port, x11->window, x11->vo_gc, xvi, src->x0, src->y0, sw, sh, dst->x0, dst->y0, dw, dh, - False); + True); + x11->ShmCompletionWaitCount++; } else #endif { @@ -388,6 +393,25 @@ static void draw_osd(struct vo *vo, struct osd_state *osd) osd_draw_on_image(osd, res, osd->vo_pts, 0, &img); } +static void wait_for_completion(struct vo *vo, int max_outstanding) +{ +#ifdef HAVE_SHM + struct xvctx *ctx = vo->priv; + struct vo_x11_state *x11 = vo->x11; + if (ctx->Shmem_Flag) { + while (x11->ShmCompletionWaitCount > max_outstanding) { + if (!ctx->Shm_Warned_Slow) { + mp_msg(MSGT_VO, MSGL_WARN, "[VO_XV] X11 can't keep up! Waiting" + " for XShm completion events...\n"); + ctx->Shm_Warned_Slow = 1; + } + usec_sleep(1000); + check_events(vo); + } + } +#endif +} + static void flip_page(struct vo *vo) { struct xvctx *ctx = vo->priv; @@ -395,16 +419,15 @@ static void flip_page(struct vo *vo) /* remember the currently visible buffer */ ctx->visible_buf = ctx->current_buf; - ctx->current_buf = (ctx->current_buf + 1) % ctx->num_buffers; - XFlush(vo->x11->display); - return; + + if (!ctx->Shmem_Flag) + XSync(vo->x11->display, False); } static mp_image_t *get_screenshot(struct vo *vo) { struct xvctx *ctx = vo->priv; - if (!ctx->original_image) return NULL; @@ -417,6 +440,8 @@ static void draw_image(struct vo *vo, mp_image_t *mpi) { struct xvctx *ctx = vo->priv; + wait_for_completion(vo, ctx->num_buffers - 1); + struct mp_image xv_buffer = get_xv_buffer(vo, ctx->current_buf); mp_image_copy(&xv_buffer, mpi); diff --git a/video/out/x11_common.c b/video/out/x11_common.c index 05fae825fc..7986817f68 100644 --- a/video/out/x11_common.c +++ b/video/out/x11_common.c @@ -903,6 +903,11 @@ int vo_x11_check_events(struct vo *vo) Event.xclient.data.l[0] == x11->XAWM_DELETE_WINDOW) mplayer_put_key(vo->key_fifo, KEY_CLOSE_WIN); break; + default: + if (Event.type == x11->ShmCompletionEvent) + if (x11->ShmCompletionWaitCount > 0) + x11->ShmCompletionWaitCount--; + break; } } return ret; diff --git a/video/out/x11_common.h b/video/out/x11_common.h index a968724842..dc5e94edc7 100644 --- a/video/out/x11_common.h +++ b/video/out/x11_common.h @@ -80,6 +80,13 @@ struct vo_x11_state { unsigned int oldfuncs; XComposeStatus compose_status; + /* XShm stuff */ + int ShmCompletionEvent; + /* Number of outstanding XShmPutImage requests */ + /* Decremented when ShmCompletionEvent is received */ + /* Increment it before XShmPutImage */ + int ShmCompletionWaitCount; + Atom XA_NET_SUPPORTED; Atom XA_NET_WM_STATE; Atom XA_NET_WM_STATE_FULLSCREEN; -- cgit v1.2.3