dri2: Event driven buffer validation.
authorFrancisco Jerez <currojerez@riseup.net>
Mon, 8 Feb 2010 18:27:56 +0000 (19:27 +0100)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 16 Feb 2010 15:38:50 +0000 (10:38 -0500)
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 before flushing the fake front/back
buffer (that's typically once per frame -- not a lot worse than the
situation we were in before).

No effort has been made on preserving backwards compatibility with
version 2 of the flush extension, but I think it's acceptable because
AFAIK no released stack is making use of it.

Signed-off-by: Kristian Høgsberg <krh@bitplanet.net>
include/GL/internal/dri_interface.h
src/glx/dri2.c
src/glx/dri2_glx.c
src/glx/glxclient.h
src/mesa/drivers/dri/common/dri_util.c
src/mesa/drivers/dri/common/dri_util.h
src/mesa/drivers/dri/intel/intel_context.c
src/mesa/drivers/dri/intel/intel_screen.c
src/mesa/drivers/dri/intel/intel_tex_image.c

index 58540d60057f06f4177515b90057a4adfede6fe8..cb99c270f52c64b67fcb56bd892bf16defffbae2 100644 (file)
@@ -269,22 +269,20 @@ 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);
 
     /**
-     * Flush all rendering queue in the driver to the drm and
-     * invalidate all buffers.  The driver will call out to
-     * getBuffers/getBuffersWithFormat before it starts rendering
-     * again.
+     * Ask the driver to call getBuffers/getBuffersWithFormat before
+     * it starts rendering again.
      *
-     * \param drawable the drawable to flush and invalidate
+     * \param drawable the drawable to invalidate
      *
-     * \since 2
+     * \since 3
      */
-    void (*flushInvalidate)(__DRIdrawable *drawable);
+    void (*invalidate)(__DRIdrawable *drawable);
 };
 
 
index 91053d3fb61d539a49556e3f8c99842ec86b09b9..a7a8cb50aa3fa6a9f8337be4fb4f25789317e48d 100644 (file)
@@ -81,7 +81,7 @@ static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
                                    dri2Info,
                                    dri2ExtensionName,
                                    &dri2ExtensionHooks,
-                                   1, NULL)
+                                   DRI2NumberEvents, NULL)
 
 static Bool
 DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
@@ -126,7 +126,15 @@ DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
       return True;
    }
 #endif
+#ifdef DRI2_InvalidateBuffers
+   case DRI2_InvalidateBuffers:
+   {
+      xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire;
 
+      dri2InvalidateBuffers(dpy, awire->drawable);
+      return False;
+   }
+#endif
    default:
       /* client doesn't support server event */
       break;
index 15a3ea590730a8086f8c3a697f0a89b5b9d02401..29d589cdb900f9fc86106e259ce0c3216ab259eb 100644 (file)
@@ -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);
@@ -386,11 +397,6 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
                    remainder, &ret);
 #endif
 
-#if __DRI2_FLUSH_VERSION >= 2
-    if (pdraw->psc->f)
-       (*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable);
-#endif
-
     return ret;
 }
 
@@ -485,6 +491,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)
@@ -651,11 +668,8 @@ dri2CreateDisplay(Display * dpy)
    }
 
    pdp->driPatch = 0;
-   pdp->swapAvailable = 0;
-#ifdef X_DRI2SwapBuffers
-   if (pdp->driMinor >= 2)
-      pdp->swapAvailable = 1;
-#endif
+   pdp->swapAvailable = (pdp->driMinor >= 2);
+   pdp->invalidateAvailable = (pdp->driMinor >= 3);
 
    pdp->base.destroyDisplay = dri2DestroyDisplay;
    pdp->base.createScreen = dri2CreateScreen;
index f88e9fbcdedc284809c183e2aa7ef194d2b90980..04ce781c43514e3b164d572202e0e6b411a08522 100644 (file)
@@ -182,6 +182,8 @@ struct __GLXDRIdrawableRec
 extern __GLXDRIdisplay *driswCreateDisplay(Display * dpy);
 extern __GLXDRIdisplay *driCreateDisplay(Display * dpy);
 extern __GLXDRIdisplay *dri2CreateDisplay(Display * dpy);
+extern void dri2InvalidateBuffers(Display *dpy, XID drawable);
+
 
 extern void DRI_glXUseXFont(Font font, int first, int count, int listbase);
 
index befe1675a04805cbd0ef5efba35ff054684354f2..b891fca2b1cb4e64d9920fe07825c0f4b7b75db8 100644 (file)
@@ -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 = &pdraw->dri2.clipRect;
     pdraw->pBackClipRects = &pdraw->dri2.clipRect;
 
+    pdraw->pStamp = &pdraw->dri2.stamp;
+    *pdraw->pStamp = pdraw->lastStamp + 1;
+
     return pdraw;
 }
 
@@ -949,4 +951,10 @@ driCalculateSwapUsage( __DRIdrawable *dPriv, int64_t last_swap_ust,
    return usage;
 }
 
+void
+dri2InvalidateDrawable(__DRIdrawable *drawable)
+{
+    drawable->dri2.stamp++;
+}
+
 /*@}*/
index 8d02524f3865d187022ed48291c8becfa43f17ce..8f0cd4cf9d8d196cf0d74c0961ee923953c2797b 100644 (file)
@@ -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
+     * to dri2.stamp if DRI2 is being used).
      */
     unsigned int *pStamp;
 
@@ -377,9 +378,8 @@ struct __DRIdrawableRec {
      */
     unsigned int swap_interval;
 
-    GLboolean validBuffers;
-
     struct {
+       unsigned int stamp;
        drm_clip_rect_t clipRect;
     } dri2;
 };
@@ -559,4 +559,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_ */
index fa2168b6efb96531a45408a7602ff82462e97f66..81d5a32476c435a288a1e1c75ec046d7f331eeac 100644 (file)
@@ -366,8 +366,8 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
        }
    }
 
-   drawable->validBuffers = GL_TRUE;
    driUpdateFramebufferSize(&intel->ctx, drawable);
+   drawable->lastStamp = drawable->dri2.stamp;
 }
 
 void
index f7ce87e063f3822f2fa24285f60c3054c3343662..8eed8ee73753482f2f6f50e97db72dc88673d4e7 100644 (file)
@@ -123,22 +123,19 @@ intelDRI2Flush(__DRIdrawable *drawable)
 }
 
 static void
-intelDRI2FlushInvalidate(__DRIdrawable *drawable)
+intelDRI2Invalidate(__DRIdrawable *drawable)
 {
    struct intel_context *intel = drawable->driContextPriv->driverPrivate;
 
    intel->using_dri2_swapbuffers = GL_TRUE;
-
-   intelDRI2Flush(drawable);
-   drawable->validBuffers = GL_FALSE;
-
+   dri2InvalidateDrawable(drawable);
    intel_update_renderbuffers(intel->driContext, drawable);
 }
 
 static const struct __DRI2flushExtensionRec intelFlushExtension = {
     { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
     intelDRI2Flush,
-    intelDRI2FlushInvalidate,
+    intelDRI2Invalidate,
 };
 
 static const __DRIextension *intelScreenExtensions[] = {
index d63292edd312fdf009f4cc77fd866ea130411f18..bc4e5c6136738ae344cb30f5e1a4df4a9d39d3cb 100644 (file)
@@ -748,7 +748,7 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
    if (!intelObj)
       return;
 
-   if (!dPriv->validBuffers)
+   if (dPriv->lastStamp != *dPriv->pStamp)
       intel_update_renderbuffers(pDRICtx, dPriv);
 
    rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);