From 3fbd1b0cb576b46ac8df2697cb388db78f48012d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 Jan 2014 16:14:29 -0800 Subject: dri3: Track current Present swap mode and adjust buffer counts This automatically adjusts the number of buffers that we want based on what swapping mode the X server is using and the current swap interval: swap mode interval buffers copy > 0 1 copy 0 2 flip > 0 2 flip 0 3 Note that flip with swap interval 0 is currently limited to twice the underlying refresh rate because of how the kernel manages flipping. Moving from 3 to 4 buffers would help, but that seems ridiculous. v2: Just update num_back at the point that the values that change num_back change. This means we'll have the updated value at the point that the freeing of old going-to-be-unused backbuffers happens, which might not have been the case before (change by anholt, acked by keithp). Signed-off-by: Keith Packard Signed-off-by: Eric Anholt Reviewed-by: Eric Anholt --- src/glx/dri3_glx.c | 35 ++++++++++++++++++++++++++++++----- src/glx/dri3_priv.h | 24 +++++------------------- 2 files changed, 35 insertions(+), 24 deletions(-) (limited to 'src/glx') diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c index 94f0eca8588..70ec057d0b6 100644 --- a/src/glx/dri3_glx.c +++ b/src/glx/dri3_glx.c @@ -269,6 +269,16 @@ dri3_create_context(struct glx_screen *base, static void dri3_free_render_buffer(struct dri3_drawable *pdraw, struct dri3_buffer *buffer); +static void +dri3_update_num_back(struct dri3_drawable *priv) +{ + priv->num_back = 1; + if (priv->flipping) + priv->num_back++; + if (priv->swap_interval == 0) + priv->num_back++; +} + static void dri3_destroy_drawable(__GLXDRIdrawable *base) { @@ -326,6 +336,8 @@ dri3_create_drawable(struct glx_screen *base, XID xDrawable, break; } + dri3_update_num_back(pdraw); + (void) __glXInitialize(psc->base.dpy); /* Create a new drawable */ @@ -373,6 +385,15 @@ dri3_handle_present_event(struct dri3_drawable *priv, xcb_present_generic_event_ priv->recv_sbc = (priv->send_sbc & 0xffffffff00000000LL) | ce->serial; if (priv->recv_sbc > priv->send_sbc) priv->recv_sbc -= 0x100000000; + switch (ce->mode) { + case XCB_PRESENT_COMPLETE_MODE_FLIP: + priv->flipping = true; + break; + case XCB_PRESENT_COMPLETE_MODE_COPY: + priv->flipping = false; + break; + } + dri3_update_num_back(priv); } else { priv->recv_msc_serial = ce->serial; } @@ -389,6 +410,10 @@ dri3_handle_present_event(struct dri3_drawable *priv, xcb_present_generic_event_ if (buf && buf->pixmap == ie->pixmap) { buf->busy = 0; + if (priv->num_back <= b && b < DRI3_MAX_BACK) { + dri3_free_render_buffer(priv, buf); + priv->buffers[b] = NULL; + } break; } } @@ -1067,10 +1092,9 @@ dri3_find_back(xcb_connection_t *c, struct dri3_drawable *priv) xcb_present_generic_event_t *ge; for (;;) { - - for (b = 0; b < DRI3_NUM_BACK; b++) { - int id = DRI3_BACK_ID(b); - struct dri3_buffer *buffer = priv->buffers[id]; + for (b = 0; b < priv->num_back; b++) { + int id = DRI3_BACK_ID(b); + struct dri3_buffer *buffer = priv->buffers[id]; if (!buffer) return b; @@ -1185,7 +1209,7 @@ dri3_free_buffers(__DRIdrawable *driDrawable, switch (buffer_type) { case dri3_buffer_back: first_id = DRI3_BACK_ID(0); - n_id = DRI3_NUM_BACK; + n_id = DRI3_MAX_BACK; break; case dri3_buffer_front: first_id = DRI3_FRONT_ID; @@ -1437,6 +1461,7 @@ dri3_set_swap_interval(__GLXDRIdrawable *pdraw, int interval) } priv->swap_interval = interval; + dri3_update_num_back(priv); return 0; } diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h index 9d142cf5137..1d124f8abd7 100644 --- a/src/glx/dri3_priv.h +++ b/src/glx/dri3_priv.h @@ -143,25 +143,9 @@ struct dri3_context __DRIcontext *driContext; }; -#define DRI3_NUM_BACK 2 +#define DRI3_MAX_BACK 3 #define DRI3_BACK_ID(i) (i) -#define DRI3_FRONT_ID (DRI3_NUM_BACK) - -static inline int -dri3_buf_id_next(int buf_id) -{ - if (buf_id == DRI3_NUM_BACK - 1) - return 0; - return buf_id + 1; -} - -static inline int -dri3_buf_id_prev(int buf_id) -{ - if (buf_id == 0) - return DRI3_NUM_BACK - 1; - return buf_id - 1; -} +#define DRI3_FRONT_ID (DRI3_MAX_BACK) static inline int dri3_pixmap_buf_id(enum dri3_buffer_type buffer_type) @@ -172,7 +156,7 @@ dri3_pixmap_buf_id(enum dri3_buffer_type buffer_type) return DRI3_FRONT_ID; } -#define DRI3_NUM_BUFFERS (1 + DRI3_NUM_BACK) +#define DRI3_NUM_BUFFERS (1 + DRI3_MAX_BACK) struct dri3_drawable { __GLXDRIdrawable base; @@ -182,6 +166,7 @@ struct dri3_drawable { uint8_t have_back; uint8_t have_fake_front; uint8_t is_pixmap; + uint8_t flipping; /* SBC numbers are tracked by using the serial numbers * in the present request and complete events @@ -198,6 +183,7 @@ struct dri3_drawable { struct dri3_buffer *buffers[DRI3_NUM_BUFFERS]; int cur_back; + int num_back; uint32_t *stamp; -- cgit v1.2.3