From a69fabc76cc5a8d744fb184bfc5a4096ee596c13 Mon Sep 17 00:00:00 2001 From: Adel Gadllah Date: Mon, 24 Feb 2014 20:44:42 +0100 Subject: [PATCH] dri3: Add GLX_EXT_buffer_age support v2: Indent according to Mesa style, reuse sbc instead of making a new swap_count field, and actually get a usable back before returning the age of the back (fixing updated piglit tests). Changes by anholt. Signed-off-by: Adel Gadllah Reviewed-by: Robert Bragg (v1) Reviewed-by: Adel Gadllah (v2) Reviewed-by: Eric Anholt --- src/glx/dri2_glx.c | 1 + src/glx/dri3_glx.c | 20 ++++++++++++++++++++ src/glx/dri3_priv.h | 1 + src/glx/glx_pbuffer.c | 33 ++++++++++++++++++++++++++++++--- src/glx/glxclient.h | 1 + src/glx/glxextensions.c | 1 + src/glx/glxextensions.h | 1 + 7 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c index 75fc9510bf4..5a960b05d84 100644 --- a/src/glx/dri2_glx.c +++ b/src/glx/dri2_glx.c @@ -1287,6 +1287,7 @@ dri2CreateScreen(int screen, struct glx_display * priv) psp->waitForSBC = NULL; psp->setSwapInterval = NULL; psp->getSwapInterval = NULL; + psp->getBufferAge = NULL; if (pdp->driMinor >= 2) { psp->getDrawableMSC = dri2DrawableGetMSC; diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c index ba801847671..b7dac8e67b5 100644 --- a/src/glx/dri3_glx.c +++ b/src/glx/dri3_glx.c @@ -1340,6 +1340,7 @@ dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, target_msc = priv->msc + priv->swap_interval * (priv->send_sbc - priv->recv_sbc); priv->buffers[buf_id]->busy = 1; + priv->buffers[buf_id]->last_swap = priv->send_sbc; xcb_present_pixmap(c, priv->base.xDrawable, priv->buffers[buf_id]->pixmap, @@ -1379,6 +1380,22 @@ dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, return ret; } +static int +dri3_get_buffer_age(__GLXDRIdrawable *pdraw) +{ + xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy); + struct dri3_drawable *priv = (struct dri3_drawable *) pdraw; + int back_id = DRI3_BACK_ID(dri3_find_back(c, priv)); + + if (back_id < 0 || !priv->buffers[back_id]) + return 0; + + if (priv->buffers[back_id]->last_swap != 0) + return priv->send_sbc - priv->buffers[back_id]->last_swap + 1; + else + return 0; +} + /** dri3_open * * Wrapper around xcb_dri3_open @@ -1737,6 +1754,9 @@ dri3_create_screen(int screen, struct glx_display * priv) psp->copySubBuffer = dri3_copy_sub_buffer; __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer"); + psp->getBufferAge = dri3_get_buffer_age; + __glXEnableDirectExtension(&psc->base, "GLX_EXT_buffer_age"); + free(driverName); free(deviceName); diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h index 1d124f8abd7..316e3131532 100644 --- a/src/glx/dri3_priv.h +++ b/src/glx/dri3_priv.h @@ -97,6 +97,7 @@ struct dri3_buffer { uint32_t cpp; uint32_t flags; uint32_t width, height; + uint64_t last_swap; enum dri3_buffer_type buffer_type; }; diff --git a/src/glx/glx_pbuffer.c b/src/glx/glx_pbuffer.c index 978730cecb3..0cd05545786 100644 --- a/src/glx/glx_pbuffer.c +++ b/src/glx/glx_pbuffer.c @@ -285,6 +285,10 @@ GetDrawableAttribute(Display * dpy, GLXDrawable drawable, unsigned int num_attributes; GLboolean use_glx_1_3; +#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) + __GLXDRIdrawable *pdraw; +#endif + if (dpy == NULL) return 0; @@ -311,6 +315,32 @@ GetDrawableAttribute(Display * dpy, GLXDrawable drawable, if (!opcode) return 0; +#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) + pdraw = GetGLXDRIDrawable(dpy, drawable); + + if (attribute == GLX_BACK_BUFFER_AGE_EXT) { + struct glx_screen *psc = pdraw->psc; + struct glx_context *gc = __glXGetCurrentContext(); + + /* The GLX_EXT_buffer_age spec says: + * + * "If querying GLX_BACK_BUFFER_AGE_EXT and is not bound to + * the calling thread's current context a GLXBadDrawable error is + * generated." + */ + if (gc == NULL || gc->currentDpy != dpy || + (gc->currentDrawable != drawable && gc->currentReadable != drawable)) { + __glXSendError(dpy, GLXBadDrawable, drawable, X_GLXGetDrawableAttributes, false); + return 0; + } + + if (psc->driScreen->getBufferAge != NULL) + *value = psc->driScreen->getBufferAge(pdraw); + + return 0; + } +#endif + LockDisplay(dpy); if (use_glx_1_3) { @@ -350,9 +380,6 @@ GetDrawableAttribute(Display * dpy, GLXDrawable drawable, _XEatData(dpy, length); } else { -#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) - __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); -#endif _XRead(dpy, (char *) data, length * sizeof(CARD32)); /* Search the set of returned attributes for the attribute requested by diff --git a/src/glx/glxclient.h b/src/glx/glxclient.h index a7118af2260..74c19c48564 100644 --- a/src/glx/glxclient.h +++ b/src/glx/glxclient.h @@ -125,6 +125,7 @@ struct __GLXDRIscreenRec { int64_t *msc, int64_t *sbc); int (*setSwapInterval)(__GLXDRIdrawable *pdraw, int interval); int (*getSwapInterval)(__GLXDRIdrawable *pdraw); + int (*getBufferAge)(__GLXDRIdrawable *pdraw); }; struct __GLXDRIdrawableRec diff --git a/src/glx/glxextensions.c b/src/glx/glxextensions.c index f186c133a25..ac1b4a7b02e 100644 --- a/src/glx/glxextensions.c +++ b/src/glx/glxextensions.c @@ -103,6 +103,7 @@ static const struct extension_info known_glx_extensions[] = { { GLX(SGIX_visual_select_group), VER(0,0), Y, Y, N, N }, { GLX(EXT_texture_from_pixmap), VER(0,0), Y, N, N, N }, { GLX(INTEL_swap_event), VER(0,0), Y, N, N, N }, + { GLX(EXT_buffer_age), VER(0,0), Y, N, Y, Y }, { NULL } }; diff --git a/src/glx/glxextensions.h b/src/glx/glxextensions.h index 8436a943bbc..37e4ccc8303 100644 --- a/src/glx/glxextensions.h +++ b/src/glx/glxextensions.h @@ -66,6 +66,7 @@ enum SGIX_visual_select_group_bit, EXT_texture_from_pixmap_bit, INTEL_swap_event_bit, + EXT_buffer_age_bit, }; /* From the GLX perspective, the ARB and EXT extensions are identical. Use a -- 2.30.2