When a buffer invalidation event is received from the X server, the
"invalidate" hook of the DRI2 flush extension is executed: A generic
implementation (dri2InvalidateDrawable) is provided that just bumps
the "pStamp" sequence number in __DRIdrawableRec.

For old servers not supporting buffer invalidation events, the
invalidate hook will be called after flushing the fake front/back
buffer (that's typically once per frame -- not a lot worse than the
situation we were in before).

Backwards compatibility should be preserved with version 2 of the
flush extension, but the "flushInvalidate" callback has been marked as
deprecated.

Note that this bumps the required dri2proto version to 2.3.
---
 configure.ac                                 |    2 +-
 include/GL/internal/dri_interface.h          |   16 ++++++++++-
 src/glx/x11/dri2.c                           |   10 ++++++-
 src/glx/x11/dri2.h                           |    3 ++
 src/glx/x11/dri2_glx.c                       |   37 ++++++++++++++++++++-----
 src/glx/x11/glx_pbuffer.c                    |    4 ---
 src/glx/x11/glxclient.h                      |    4 +++
 src/glx/x11/glxcmds.c                        |    4 ---
 src/mesa/drivers/dri/common/dri_util.c       |   15 ++++++++++-
 src/mesa/drivers/dri/common/dri_util.h       |    8 +++--
 src/mesa/drivers/dri/intel/intel_context.c   |    1 -
 src/mesa/drivers/dri/intel/intel_screen.c    |    2 +-
 src/mesa/drivers/dri/intel/intel_tex_image.c |    4 ++-
 13 files changed, 84 insertions(+), 26 deletions(-)

diff --git a/configure.ac b/configure.ac
index 6ae526d..0efbeb0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,7 +20,7 @@ AC_CANONICAL_HOST
 dnl Versions for external dependencies
 LIBDRM_REQUIRED=2.4.15
 LIBDRM_RADEON_REQUIRED=2.4.17
-DRI2PROTO_REQUIRED=2.2
+DRI2PROTO_REQUIRED=2.3
 GLPROTO_REQUIRED=1.4.11
 
 dnl Check for progs
diff --git a/include/GL/internal/dri_interface.h 
b/include/GL/internal/dri_interface.h
index ec6238f..e818744 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -262,7 +262,7 @@ struct __DRItexBufferExtensionRec {
  * Used by drivers that implement DRI2
  */
 #define __DRI2_FLUSH "DRI2_Flush"
-#define __DRI2_FLUSH_VERSION 2
+#define __DRI2_FLUSH_VERSION 3
 struct __DRI2flushExtensionRec {
     __DRIextension base;
     void (*flush)(__DRIdrawable *drawable);
@@ -273,11 +273,25 @@ struct __DRI2flushExtensionRec {
      * getBuffers/getBuffersWithFormat before it starts rendering
      * again.
      *
+     * This function is only called when \c SwapBuffers is the reason
+     * buffers have become invalid, and it's deprecated in favor of
+     * \c ::invalidate.
+     *
      * \param drawable the drawable to flush and invalidate
      *
      * \since 2
      */
     void (*flushInvalidate)(__DRIdrawable *drawable);
+
+    /**
+     * Ask the driver to call getBuffers/getBuffersWithFormat before
+     * it starts rendering again.
+     *
+     * \param drawable the drawable to invalidate
+     *
+     * \since 3
+     */
+    void (*invalidate)(__DRIdrawable *drawable);
 };
 
 
diff --git a/src/glx/x11/dri2.c b/src/glx/x11/dri2.c
index 2cb5d34..4a84066 100644
--- a/src/glx/x11/dri2.c
+++ b/src/glx/x11/dri2.c
@@ -81,7 +81,7 @@ static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
                                    dri2Info,
                                    dri2ExtensionName,
                                    &dri2ExtensionHooks,
-                                   0, NULL)
+                                   DRI2NumberEvents, NULL)
 
 static Bool
 DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
@@ -95,6 +95,7 @@ DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
    {
       GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
       xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire;
+
       switch (awire->type) {
       case DRI2_EXCHANGE_COMPLETE:
         aevent->event_type = GLX_EXCHANGE_COMPLETE;
@@ -115,6 +116,13 @@ DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
       aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo;
       return True;
    }
+   case DRI2_InvalidateBuffers:
+   {
+      xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire;
+
+      DRI2InvalidateBuffers(dpy, awire->drawable);
+      return False;
+   }
    default:
       /* client doesn't support server event */
       break;
diff --git a/src/glx/x11/dri2.h b/src/glx/x11/dri2.h
index 114e9f8..943ac59 100644
--- a/src/glx/x11/dri2.h
+++ b/src/glx/x11/dri2.h
@@ -103,4 +103,7 @@ DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, 
CARD64 *ust,
 extern void
 DRI2SwapInterval(Display *dpy, XID drawable, int interval);
 
+extern void
+DRI2InvalidateBuffers(Display *dpy, XID drawable);
+
 #endif
diff --git a/src/glx/x11/dri2_glx.c b/src/glx/x11/dri2_glx.c
index 7b0c52b..73f988d 100644
--- a/src/glx/x11/dri2_glx.c
+++ b/src/glx/x11/dri2_glx.c
@@ -67,6 +67,7 @@ struct __GLXDRIdisplayPrivateRec
    int driMinor;
    int driPatch;
    int swapAvailable;
+   int invalidateAvailable;
 };
 
 struct __GLXDRIcontextPrivateRec
@@ -310,12 +311,18 @@ dri2WaitGL(__GLXDRIdrawable * pdraw)
    XFixesDestroyRegion(pdraw->psc->dpy, region);
 }
 
-
 static void
-dri2FlushFrontBuffer(__DRIdrawable * driDrawable, void *loaderPrivate)
+dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate)
 {
-   (void) driDrawable;
-   dri2WaitGL((__GLXDRIdrawable *) loaderPrivate);
+   __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
+   __GLXdisplayPrivate *priv = __glXInitialize(pdraw->base.psc->dpy);
+   __GLXDRIdisplayPrivate *pdp = (__GLXDRIdisplayPrivate *)priv->dri2Display;
+
+   /* Old servers don't send invalidate events */
+   if (!pdp->invalidateAvailable)
+      DRI2InvalidateBuffers(priv->dpy, pdraw->base.xDrawable);
+
+   dri2WaitGL(loaderPrivate);
 }
 
 
@@ -375,6 +382,10 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t 
target_msc, int64_t divisor,
        (*pdraw->psc->f->flush)(pdraw->driDrawable);
 #endif
 
+    /* Old servers don't send invalidate events */
+    if (!pdp->invalidateAvailable)
+       DRI2InvalidateBuffers(dpyPriv->dpy, pdraw->xDrawable);
+
     /* Old servers can't handle swapbuffers */
     if (!pdp->swapAvailable) {
        dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
@@ -385,7 +396,7 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t 
target_msc, int64_t divisor,
                    remainder, &ret);
 
 #if __DRI2_FLUSH_VERSION >= 2
-    if (pdraw->psc->f)
+    if (pdraw->psc->f && pdraw->psc->f->flushInvalidate)
        (*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable);
 #endif
 
@@ -483,6 +494,17 @@ static const __DRIextension *loader_extensions_old[] = {
    NULL
 };
 
+_X_HIDDEN void
+DRI2InvalidateBuffers(Display *dpy, XID drawable)
+{
+   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
+
+#if __DRI2_FLUSH_VERSION >= 3
+   if (pdraw && pdraw->psc->f)
+      pdraw->psc->f->invalidate(pdraw->driDrawable);
+#endif
+}
+
 static __GLXDRIscreen *
 dri2CreateScreen(__GLXscreenConfigs * psc, int screen,
                  __GLXdisplayPrivate * priv)
@@ -640,9 +662,8 @@ dri2CreateDisplay(Display * dpy)
    }
 
    pdp->driPatch = 0;
-   pdp->swapAvailable = 0;
-   if (pdp->driMinor >= 2)
-      pdp->swapAvailable = 1;
+   pdp->swapAvailable = (pdp->driMinor >= 2);
+   pdp->invalidateAvailable = (pdp->driMinor >= 3);
 
    pdp->base.destroyDisplay = dri2DestroyDisplay;
    pdp->base.createScreen = dri2CreateScreen;
diff --git a/src/glx/x11/glx_pbuffer.c b/src/glx/x11/glx_pbuffer.c
index 501500a..15dffed 100644
--- a/src/glx/x11/glx_pbuffer.c
+++ b/src/glx/x11/glx_pbuffer.c
@@ -188,10 +188,6 @@ DestroyPbuffer(Display * dpy, GLXDrawable drawable)
 
 
 #ifdef GLX_DIRECT_RENDERING
-extern __GLXDRIdrawable *GetGLXDRIDrawable(Display * dpy,
-                                           GLXDrawable drawable,
-                                           int *const scrn_num);
-
 static GLenum
 determineTextureTarget(const int *attribs, int numAttribs)
 {
diff --git a/src/glx/x11/glxclient.h b/src/glx/x11/glxclient.h
index ded4f5a..970cbe0 100644
--- a/src/glx/x11/glxclient.h
+++ b/src/glx/x11/glxclient.h
@@ -793,6 +793,10 @@ extern GLboolean __glXGetMscRateOML(Display * dpy, 
GLXDrawable drawable,
 GLboolean
 __driGetMscRateOML(__DRIdrawable * draw,
                    int32_t * numerator, int32_t * denominator, void *private);
+
+extern __GLXDRIdrawable *
+GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int *const scrn_num);
+
 #endif
 
 #endif /* !__GLX_client_h__ */
diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c
index c3be974..da0dcf1 100644
--- a/src/glx/x11/glxcmds.c
+++ b/src/glx/x11/glxcmds.c
@@ -105,10 +105,6 @@ GarbageCollectDRIDrawables(Display * dpy, 
__GLXscreenConfigs * sc)
    XSetErrorHandler(oldXErrorHandler);
 }
 
-extern __GLXDRIdrawable *GetGLXDRIDrawable(Display * dpy,
-                                           GLXDrawable drawable,
-                                           int *const scrn_num);
-
 /**
  * Get the __DRIdrawable for the drawable associated with a GLXContext
  *
diff --git a/src/mesa/drivers/dri/common/dri_util.c 
b/src/mesa/drivers/dri/common/dri_util.c
index 3649c29..705681e 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -454,7 +454,6 @@ driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig 
*config,
 
     pdp->driScreenPriv = psp;
     pdp->driContextPriv = &psp->dummyContextPriv;
-    pdp->validBuffers = GL_FALSE;
 
     if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes,
                                        renderType == GLX_PIXMAP_BIT)) {
@@ -488,6 +487,9 @@ dri2CreateNewDrawable(__DRIscreen *screen,
     pdraw->pClipRects = _mesa_malloc(sizeof *pdraw->pBackClipRects);
     pdraw->pBackClipRects = _mesa_malloc(sizeof *pdraw->pBackClipRects);
 
+    pdraw->pStamp = _mesa_malloc(sizeof(unsigned int));
+    *pdraw->pStamp = pdraw->lastStamp + 1;
+
     return pdraw;
 }
 
@@ -515,6 +517,11 @@ static void dri_put_drawable(__DRIdrawable *pdp)
            _mesa_free(pdp->pBackClipRects);
            pdp->pBackClipRects = NULL;
        }
+       if (psp->dri2.enabled && pdp->pStamp) {
+               _mesa_free(pdp->pStamp);
+               pdp->pStamp = NULL;
+
+       }
        _mesa_free(pdp);
     }
 }
@@ -948,4 +955,10 @@ driCalculateSwapUsage( __DRIdrawable *dPriv, int64_t 
last_swap_ust,
    return usage;
 }
 
+void
+dri2InvalidateDrawable(__DRIdrawable *drawable)
+{
+       (*drawable->pStamp)++;
+}
+
 /*...@}*/
diff --git a/src/mesa/drivers/dri/common/dri_util.h 
b/src/mesa/drivers/dri/common/dri_util.h
index 95df702..d473091 100644
--- a/src/mesa/drivers/dri/common/dri_util.h
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -295,7 +295,8 @@ struct __DRIdrawableRec {
     unsigned int index;
 
     /**
-     * Pointer to the "drawable has changed ID" stamp in the SAREA.
+     * Pointer to the "drawable has changed ID" stamp in the SAREA (or
+     * in malloc'ed memory if DRI2 is being used).
      */
     unsigned int *pStamp;
 
@@ -376,8 +377,6 @@ struct __DRIdrawableRec {
      * GLX_MESA_swap_control.
      */
     unsigned int swap_interval;
-
-    GLboolean validBuffers;
 };
 
 /**
@@ -550,4 +549,7 @@ driCalculateSwapUsage( __DRIdrawable *dPriv,
 extern GLint
 driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 );
 
+extern void
+dri2InvalidateDrawable(__DRIdrawable *drawable);
+
 #endif /* _DRI_UTIL_H_ */
diff --git a/src/mesa/drivers/dri/intel/intel_context.c 
b/src/mesa/drivers/dri/intel/intel_context.c
index d52fe2e..b4891b1 100644
--- a/src/mesa/drivers/dri/intel/intel_context.c
+++ b/src/mesa/drivers/dri/intel/intel_context.c
@@ -376,7 +376,6 @@ intel_update_renderbuffers(__DRIcontext *context, 
__DRIdrawable *drawable)
        }
    }
 
-   drawable->validBuffers = GL_TRUE;
    driUpdateFramebufferSize(&intel->ctx, drawable);
 }
 
diff --git a/src/mesa/drivers/dri/intel/intel_screen.c 
b/src/mesa/drivers/dri/intel/intel_screen.c
index 6c2cb3b..74a4a13 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.c
+++ b/src/mesa/drivers/dri/intel/intel_screen.c
@@ -131,7 +131,6 @@ intelDRI2FlushInvalidate(__DRIdrawable *drawable)
    struct intel_context *intel = drawable->driContextPriv->driverPrivate;
 
    intelDRI2Flush(drawable);
-   drawable->validBuffers = GL_FALSE;
 
    /* We're using FlushInvalidate as an indicator that a frame is
     * done.  It's only called immediately after SwapBuffers, so it
@@ -157,6 +156,7 @@ static const struct __DRI2flushExtensionRec 
intelFlushExtension = {
     { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
     intelDRI2Flush,
     intelDRI2FlushInvalidate,
+    dri2InvalidateDrawable,
 };
 
 static const __DRIextension *intelScreenExtensions[] = {
diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c 
b/src/mesa/drivers/dri/intel/intel_tex_image.c
index 6f41eaf..0ecafab 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_image.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_image.c
@@ -742,8 +742,10 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
    if (!intelObj)
       return;
 
-   if (!dPriv->validBuffers)
+   if (dPriv->lastStamp != *dPriv->pStamp) {
+      dPriv->lastStamp = *dPriv->pStamp;
       intel_update_renderbuffers(pDRICtx, dPriv);
+   }
 
    rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
    /* If the region isn't set, then intel_update_renderbuffers was unable
-- 
1.6.4.4


------------------------------------------------------------------------------
Throughout its 18-year history, RSA Conference consistently attracts the
world's best and brightest in the field, creating opportunities for Conference
attendees to learn about information security's most important issues through
interactions with peers, luminaries and emerging and established companies.
http://p.sf.net/sfu/rsaconf-dev2dev
_______________________________________________
Mesa3d-dev mailing list
Mesa3d-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mesa3d-dev

Reply via email to