summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorRudolf Polzer <divverent@xonotic.org>2013-01-02 12:55:52 +0100
committerwm4 <wm4@nowhere>2013-01-13 22:36:42 +0100
commit4044754d24c677ed82016b5b8f3011686d7d2ff6 (patch)
tree14c367b7c2e79c16ef7bfe8a14299e36cc7dd5df /video
parentc15cc15415d76e1a74b3f4a3087b9c208195cc2a (diff)
downloadmpv-4044754d24c677ed82016b5b8f3011686d7d2ff6.tar.bz2
mpv-4044754d24c677ed82016b5b8f3011686d7d2ff6.tar.xz
vo_x11, vo_xv: XShmCompletion event support
This fixes OSD flicker with vo_xv at high frame rates.
Diffstat (limited to 'video')
-rw-r--r--video/out/vo_x11.c36
-rw-r--r--video/out/vo_xv.c41
-rw-r--r--video/out/x11_common.c5
-rw-r--r--video/out/x11_common.h7
4 files changed, 73 insertions, 16 deletions
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;