mirror of
https://github.com/mpv-player/mpv
synced 2025-02-03 05:31:34 +00:00
vo_x11, vo_xv: XShmCompletion event support
This fixes OSD flicker with vo_xv at high frame rates.
This commit is contained in:
parent
c15cc15415
commit
4044754d24
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user