dri3: Add GLX_EXT_buffer_age support
authorAdel Gadllah <adel.gadllah@gmail.com>
Mon, 24 Feb 2014 19:44:42 +0000 (20:44 +0100)
committerEric Anholt <eric@anholt.net>
Thu, 13 Mar 2014 21:19:21 +0000 (14:19 -0700)
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 <adel.gadllah@gmail.com>
Reviewed-by: Robert Bragg <robert@sixbynine.org> (v1)
Reviewed-by: Adel Gadllah <adel.gadllah@gmail.com> (v2)
Reviewed-by: Eric Anholt <eric@anholt.net>
src/glx/dri2_glx.c
src/glx/dri3_glx.c
src/glx/dri3_priv.h
src/glx/glx_pbuffer.c
src/glx/glxclient.h
src/glx/glxextensions.c
src/glx/glxextensions.h

index 75fc9510bf47a1511b1f11d561fff4be791f3f78..5a960b05d846ca8cf12dd277b19141dc142578aa 100644 (file)
@@ -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;
index ba8018476713e59d4740e44786a8b1cef13cf2d9..b7dac8e67b5632bc0b24de3f5b2a4859e2073908 100644 (file)
@@ -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);
 
index 1d124f8abd7f0abe7463f535837210c6258b9f23..316e313153262b64158d8dd9468e27b1c65232f3 100644 (file)
@@ -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;
 };
index 978730cecb32a0121f6eb591f5c0235cfbafe0ad..0cd05545786c657a2cc7bda67dd144b2f395d7d9 100644 (file)
@@ -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 <draw> 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
index a7118af2260256bea1a8ca9dfd196dae323122c8..74c19c485643746173955a15200e026329488867 100644 (file)
@@ -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
index f186c133a254d511bd7bc55bd69572e73893fa7d..ac1b4a7b02ee249eb0447b5e4531d95e76dff8ad 100644 (file)
@@ -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 }
 };
 
index 8436a943bbc611d46479e8845980ca72a6ebdf2f..37e4ccc8303deeb6b6a60f823a378dba78314636 100644 (file)
@@ -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