[Mesa-dev] [PATCH 1/3] dri2: Serialize with all X rendering on glXWaitX()

Chris Wilson chris at chris-wilson.co.uk
Sat Oct 22 10:00:51 UTC 2016


Xorg may implement fine grained per-drawable serialisation. If the
client is reading from shared pixmap sources, flushing rendering to the
current drawable is not enough (even if the current code did that, it
does not). Instead, following a glXWaitX() ensure that all X rendering to
shared buffers associated with the glXContext is flushed by doing a
DRI2GetBuffers() roundtrip prior to GL rendering.

References: https://bugs.freedesktop.org/show_bug.cgi?id=52930
References: https://bugs.freedesktop.org/show_bug.cgi?id=90264
References: https://bugs.freedesktop.org/show_bug.cgi?id=97914
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 include/GL/internal/dri_interface.h         | 12 ++++++++-
 src/glx/dri2_glx.c                          | 16 ++++++++++--
 src/mesa/drivers/dri/common/dri_util.c      |  6 +++++
 src/mesa/drivers/dri/common/dri_util.h      |  4 +++
 src/mesa/drivers/dri/i965/brw_context.c     | 38 ++++++++---------------------
 src/mesa/drivers/dri/i965/brw_context.h     | 23 +++++++++++++++--
 src/mesa/drivers/dri/i965/intel_screen.c    |  5 ++--
 src/mesa/drivers/dri/i965/intel_tex_image.c |  5 ++--
 8 files changed, 71 insertions(+), 38 deletions(-)

diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index d0b1bc6..ca1fc38 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -270,7 +270,7 @@ struct __DRItexBufferExtensionRec {
  * Used by drivers that implement DRI2
  */
 #define __DRI2_FLUSH "DRI2_Flush"
-#define __DRI2_FLUSH_VERSION 4
+#define __DRI2_FLUSH_VERSION 5
 
 #define __DRI2_FLUSH_DRAWABLE (1 << 0) /* the drawable should be flushed. */
 #define __DRI2_FLUSH_CONTEXT  (1 << 1) /* glFlush should be called */
@@ -316,6 +316,16 @@ struct __DRI2flushExtensionRec {
                              __DRIdrawable *drawable,
                              unsigned flags,
                              enum __DRI2throttleReason throttle_reason);
+
+    /**
+     * Ask the driver to call getBuffers/getBuffersWithFormat on all
+     * surfaces on this screen before it starts rendering again.
+     *
+     * \param screen the screen to invalidate
+     *
+     * \since 5
+     */
+    void (*invalidateScreen)(__DRIscreen *screen);
 };
 
 
diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c
index d6eb281..58f1e85 100644
--- a/src/glx/dri2_glx.c
+++ b/src/glx/dri2_glx.c
@@ -633,7 +633,7 @@ dri2_copy_drawable(struct dri2_drawable *priv, int dest, int src)
 }
 
 static void
-dri2_wait_x(struct glx_context *gc)
+__dri2_copy_x(struct glx_context *gc)
 {
    struct dri2_drawable *priv = (struct dri2_drawable *)
       GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
@@ -645,6 +645,18 @@ dri2_wait_x(struct glx_context *gc)
 }
 
 static void
+dri2_wait_x(struct glx_context *gc)
+{
+   struct dri2_context *pcp = (struct dri2_context *) gc;
+   struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc;
+
+   if (psc->f && psc->f->base.version >= 5 && psc->f->invalidateScreen)
+       psc->f->invalidateScreen(psc->driScreen);
+   else
+      __dri2_copy_x(gc);
+}
+
+static void
 dri2_wait_gl(struct glx_context *gc)
 {
    struct dri2_drawable *priv = (struct dri2_drawable *)
@@ -979,7 +991,7 @@ dri2InvalidateBuffers(Display *dpy, XID drawable)
 
    psc = (struct dri2_screen *) pdraw->psc;
 
-   if (pdraw && psc->f && psc->f->base.version >= 3 && psc->f->invalidate)
+   if (psc->f && psc->f->base.version >= 3 && psc->f->invalidate)
        psc->f->invalidate(pdp->driDrawable);
 }
 
diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
index 79cb050..68fa0fe 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -805,6 +805,12 @@ dri2InvalidateDrawable(__DRIdrawable *drawable)
     drawable->dri2.stamp++;
 }
 
+void
+dri2InvalidateScreen(__DRIscreen *screen)
+{
+    screen->dri2.stamp++;
+}
+
 /**
  * Check that the gl_framebuffer associated with dPriv is the right size.
  * Resize the gl_framebuffer if needed.
diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
index 6987f55..eb761d4 100644
--- a/src/mesa/drivers/dri/common/dri_util.h
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -172,6 +172,7 @@ struct __DRIscreenRec {
 	const __DRIdri2LoaderExtension *loader;
 	const __DRIimageLookupExtension *image;
 	const __DRIuseInvalidateExtension *useInvalidate;
+	unsigned int stamp;
     } dri2;
 
     struct {
@@ -285,6 +286,9 @@ extern void
 dri2InvalidateDrawable(__DRIdrawable *drawable);
 
 extern void
+dri2InvalidateScreen(__DRIscreen *screen);
+
+extern void
 driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv);
 
 extern void
diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index d6204fd..8ea17c3 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -1287,14 +1287,12 @@ intelMakeCurrent(__DRIcontext * driContextPriv,
          fb = _mesa_get_incomplete_framebuffer();
       } else {
          fb = driDrawPriv->driverPrivate;
-         driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1;
       }
 
       if (driReadPriv == NULL) {
          readFb = _mesa_get_incomplete_framebuffer();
       } else {
          readFb = driReadPriv->driverPrivate;
-         driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1;
       }
 
       /* The sRGB workaround changes the renderbuffer's format. We must change
@@ -1382,11 +1380,6 @@ intel_update_dri2_buffers(struct brw_context *brw, __DRIdrawable *drawable)
    int i, count;
    const char *region_name;
 
-   /* Set this up front, so that in case our buffers get invalidated
-    * while we're getting new buffers, we don't clobber the stamp and
-    * thus ignore the invalidate. */
-   drawable->lastStamp = drawable->dri2.stamp;
-
    if (unlikely(INTEL_DEBUG & DEBUG_DRI))
       fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
 
@@ -1430,15 +1423,10 @@ intel_update_dri2_buffers(struct brw_context *brw, __DRIdrawable *drawable)
 }
 
 void
-intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
+__intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
 {
+   __DRIscreen *dri_screen = context->driScreenPriv;
    struct brw_context *brw = context->driverPrivate;
-   __DRIscreen *dri_screen = brw->screen->driScrnPriv;
-
-   /* Set this up front, so that in case our buffers get invalidated
-    * while we're getting new buffers, we don't clobber the stamp and
-    * thus ignore the invalidate. */
-   drawable->lastStamp = drawable->dri2.stamp;
 
    if (unlikely(INTEL_DEBUG & DEBUG_DRI))
       fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
@@ -1460,21 +1448,15 @@ intel_prepare_render(struct brw_context *brw)
 {
    struct gl_context *ctx = &brw->ctx;
    __DRIcontext *driContext = brw->driContext;
-   __DRIdrawable *drawable;
 
-   drawable = driContext->driDrawablePriv;
-   if (drawable && drawable->dri2.stamp != driContext->dri2.draw_stamp) {
-      if (drawable->lastStamp != drawable->dri2.stamp)
-         intel_update_renderbuffers(driContext, drawable);
-      driContext->dri2.draw_stamp = drawable->dri2.stamp;
-   }
-
-   drawable = driContext->driReadablePriv;
-   if (drawable && drawable->dri2.stamp != driContext->dri2.read_stamp) {
-      if (drawable->lastStamp != drawable->dri2.stamp)
-         intel_update_renderbuffers(driContext, drawable);
-      driContext->dri2.read_stamp = drawable->dri2.stamp;
-   }
+   if (driContext->driDrawablePriv)
+      intel_update_renderbuffers(driContext,
+                                 driContext->driDrawablePriv,
+                                 false);
+   if (driContext->driReadablePriv)
+      intel_update_renderbuffers(driContext,
+                                 driContext->driReadablePriv,
+                                 false);
 
    /* If we're currently rendering to the front buffer, the rendering
     * that will happen next will probably dirty the front buffer.  So
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index c92bb9f..42bd991 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -1354,8 +1354,27 @@ enum {
    DRI_CONF_BO_REUSE_ALL
 };
 
-void intel_update_renderbuffers(__DRIcontext *context,
-                                __DRIdrawable *drawable);
+void __intel_update_renderbuffers(__DRIcontext *context,
+                                  __DRIdrawable *drawable);
+static inline void
+intel_update_renderbuffers(__DRIcontext *context,
+                           __DRIdrawable *drawable,
+                           bool force)
+{
+   __DRIscreen *dri_screen = context->driScreenPriv;
+   unsigned int stamp = drawable->dri2.stamp + dri_screen->dri2.stamp;
+
+   if (stamp == drawable->lastStamp && !force)
+      return;
+
+   /* Set this up front, so that in case our buffers get invalidated
+    * while we're getting new buffers, we don't clobber the stamp and
+    * thus ignore the invalidate. */
+   drawable->lastStamp = stamp;
+
+   __intel_update_renderbuffers(context, drawable);
+}
+
 void intel_prepare_render(struct brw_context *brw);
 
 void intel_resolve_for_dri2_flush(struct brw_context *brw,
diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
index e1c3c19..bb4a33e 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.c
+++ b/src/mesa/drivers/dri/i965/intel_screen.c
@@ -207,11 +207,12 @@ intel_dri2_flush(__DRIdrawable *drawable)
 }
 
 static const struct __DRI2flushExtensionRec intelFlushExtension = {
-    .base = { __DRI2_FLUSH, 4 },
+    .base = { __DRI2_FLUSH, 5 },
 
     .flush              = intel_dri2_flush,
-    .invalidate         = dri2InvalidateDrawable,
     .flush_with_flags   = intel_dri2_flush_with_flags,
+    .invalidate         = dri2InvalidateDrawable,
+    .invalidateScreen   = dri2InvalidateScreen,
 };
 
 static struct intel_image_format intel_image_formats[] = {
diff --git a/src/mesa/drivers/dri/i965/intel_tex_image.c b/src/mesa/drivers/dri/i965/intel_tex_image.c
index 4454e53..f65a158 100644
--- a/src/mesa/drivers/dri/i965/intel_tex_image.c
+++ b/src/mesa/drivers/dri/i965/intel_tex_image.c
@@ -289,9 +289,8 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
    if (!texObj)
       return;
 
-   if (dPriv->lastStamp != dPriv->dri2.stamp ||
-       !pDRICtx->driScreenPriv->dri2.useInvalidate)
-      intel_update_renderbuffers(pDRICtx, dPriv);
+   intel_update_renderbuffers(pDRICtx, dPriv,
+                              !pDRICtx->driScreenPriv->dri2.useInvalidate);
 
    rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
    /* If the miptree isn't set, then intel_update_renderbuffers was unable
-- 
2.9.3



More information about the mesa-dev mailing list