Mesa (master): radeon: Add DRI2 flush extension to so we synchronize properly.

Jerome Glisse glisse at kemper.freedesktop.org
Mon Aug 2 15:16:31 UTC 2010


Module: Mesa
Branch: master
Commit: 8446f257b3e3ca4a3eb2c79bc357e46343e04e87
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=8446f257b3e3ca4a3eb2c79bc357e46343e04e87

Author: Mario Kleiner <mario.kleiner at tuebingen.mpg.de>
Date:   Sun Jul 25 16:29:24 2010 +0200

radeon: Add DRI2 flush extension to so we synchronize properly.

When DRI2 swap buffer is pending (copy buffer not pageflipping)
we need to make sure we have the flush extension so radeon doesn't
resume rendering on the not yet blitted front buffer.

Modified version of Jerome's patch to add flush extension
in the correct place.

This prepares a possible fix for:

https://bugs.freedesktop.org/show_bug.cgi?id=28341
https://bugs.freedesktop.org/show_bug.cgi?id=28410

Signed-off-by: Jerome Glisse <jglisse at redhat.com>
Signed-off-by: Mario Kleiner <mario.kleiner at tuebingen.mpg.de>

---

 src/mesa/drivers/dri/r200/r200_swtcl.c             |    2 +
 src/mesa/drivers/dri/r200/r200_tcl.c               |    2 +
 src/mesa/drivers/dri/r300/r300_render.c            |    2 +
 src/mesa/drivers/dri/r600/r700_clear.c             |    3 +
 src/mesa/drivers/dri/r600/r700_render.c            |    4 ++
 .../drivers/dri/radeon/radeon_common_context.c     |   42 ++++++++++++++++++++
 .../drivers/dri/radeon/radeon_common_context.h     |    1 +
 src/mesa/drivers/dri/radeon/radeon_screen.c        |   17 ++++++++
 src/mesa/drivers/dri/radeon/radeon_swtcl.c         |    2 +
 src/mesa/drivers/dri/radeon/radeon_tcl.c           |    2 +
 10 files changed, 77 insertions(+), 0 deletions(-)

diff --git a/src/mesa/drivers/dri/r200/r200_swtcl.c b/src/mesa/drivers/dri/r200/r200_swtcl.c
index 262fe3c..dbf4ad4 100644
--- a/src/mesa/drivers/dri/r200/r200_swtcl.c
+++ b/src/mesa/drivers/dri/r200/r200_swtcl.c
@@ -612,6 +612,8 @@ static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim )
 {
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
 
+   radeon_prepare_render(&rmesa->radeon);
+
    if (rmesa->radeon.swtcl.hw_primitive != hwprim) {
       /* need to disable perspective-correct texturing for point sprites */
       if ((hwprim & 0xf) == R200_VF_PRIM_POINT_SPRITES && ctx->Point.PointSprite) {
diff --git a/src/mesa/drivers/dri/r200/r200_tcl.c b/src/mesa/drivers/dri/r200/r200_tcl.c
index d43e145..4ae0f30 100644
--- a/src/mesa/drivers/dri/r200/r200_tcl.c
+++ b/src/mesa/drivers/dri/r200/r200_tcl.c
@@ -264,6 +264,8 @@ void r200TclPrimitive( GLcontext *ctx,
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
    GLuint newprim = hw_prim | R200_VF_TCL_OUTPUT_VTX_ENABLE;
 
+   radeon_prepare_render(&rmesa->radeon);
+
    if (newprim != rmesa->tcl.hw_primitive ||
        !discrete_prim[hw_prim&0xf]) {
       /* need to disable perspective-correct texturing for point sprites */
diff --git a/src/mesa/drivers/dri/r300/r300_render.c b/src/mesa/drivers/dri/r300/r300_render.c
index bb8f914..cf89ab7 100644
--- a/src/mesa/drivers/dri/r300/r300_render.c
+++ b/src/mesa/drivers/dri/r300/r300_render.c
@@ -327,6 +327,8 @@ void r300RunRenderPrimitive(GLcontext * ctx, int start, int end, int prim)
 	BATCH_LOCALS(&rmesa->radeon);
 	int type, num_verts;
 
+	radeon_prepare_render(&rmesa->radeon);
+
 	type = r300PrimitiveType(rmesa, prim);
 	num_verts = r300NumVerts(rmesa, end - start, prim);
 
diff --git a/src/mesa/drivers/dri/r600/r700_clear.c b/src/mesa/drivers/dri/r600/r700_clear.c
index 09c4856..d1008f2 100644
--- a/src/mesa/drivers/dri/r600/r700_clear.c
+++ b/src/mesa/drivers/dri/r600/r700_clear.c
@@ -48,6 +48,7 @@ static GLboolean r700ClearFast(context_t *context, GLbitfield mask)
 void r700Clear(GLcontext * ctx, GLbitfield mask)
 {
     context_t *context = R700_CONTEXT(ctx);
+    radeonContextPtr radeon = &context->radeon;
     __DRIdrawable *dPriv = radeon_get_drawable(&context->radeon);
     const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask[0]);
     GLbitfield swrast_mask = 0, tri_mask = 0;
@@ -60,6 +61,8 @@ void r700Clear(GLcontext * ctx, GLbitfield mask)
         context->radeon.front_buffer_dirty = GL_TRUE;
     }
 
+    radeon_prepare_render(radeon);
+
     if( GL_TRUE == r700ClearFast(context, mask) )
     {
         return;
diff --git a/src/mesa/drivers/dri/r600/r700_render.c b/src/mesa/drivers/dri/r600/r700_render.c
index 1929b7c..316a094 100644
--- a/src/mesa/drivers/dri/r600/r700_render.c
+++ b/src/mesa/drivers/dri/r600/r700_render.c
@@ -977,6 +977,10 @@ static void r700DrawPrims(GLcontext *ctx,
 {
 	GLboolean retval = GL_FALSE;
 
+	context_t *context = R700_CONTEXT(ctx);
+	radeonContextPtr radeon = &context->radeon;
+	radeon_prepare_render(radeon);
+
 	/* This check should get folded into just the places that
 	 * min/max index are really needed.
 	 */
diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.c b/src/mesa/drivers/dri/radeon/radeon_common_context.c
index 5a7d52c..3665944 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common_context.c
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.c
@@ -493,6 +493,43 @@ radeon_bits_per_pixel(const struct radeon_renderbuffer *rb)
    return _mesa_get_format_bytes(rb->base.Format) * 8; 
 }
 
+/*
+ * Check if drawable has been invalidated by dri2InvalidateDrawable().
+ * Update renderbuffers if so. This prevents a client from accessing
+ * a backbuffer that has a swap pending but not yet completed.
+ *
+ * See intel_prepare_render for equivalent code in intel driver.
+ *
+ */
+void radeon_prepare_render(radeonContextPtr radeon)
+{
+    __DRIcontext *driContext = radeon->dri.context;
+    __DRIdrawable *drawable;
+    __DRIscreen *screen;
+
+    screen = driContext->driScreenPriv;
+    if (!screen->dri2.loader)
+        return;
+
+    drawable = driContext->driDrawablePriv;
+    if (drawable->dri2.stamp != driContext->dri2.draw_stamp) {
+	if (drawable->lastStamp != drawable->dri2.stamp)
+	    radeon_update_renderbuffers(driContext, drawable, GL_FALSE);
+
+	/* Intel driver does the equivalent of this, no clue if it is needed:
+	 * radeon_draw_buffer(radeon->glCtx, &(drawable->driverPrivate)->base);
+	 */
+	driContext->dri2.draw_stamp = drawable->dri2.stamp;
+    }
+
+    drawable = driContext->driReadablePriv;
+    if (drawable->dri2.stamp != driContext->dri2.read_stamp) {
+	if (drawable->lastStamp != drawable->dri2.stamp)
+	    radeon_update_renderbuffers(driContext, drawable, GL_FALSE);
+	driContext->dri2.read_stamp = drawable->dri2.stamp;
+    }
+}
+
 void
 radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
 			    GLboolean front_only)
@@ -514,6 +551,11 @@ radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
 	screen = context->driScreenPriv;
 	radeon = (radeonContextPtr) context->driverPrivate;
 
+	/* 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 (screen->dri2.loader
 	   && (screen->dri2.loader->base.version > 2)
 	   && (screen->dri2.loader->getBuffersWithFormat != NULL)) {
diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h
index 5156c5d..ec773cf 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common_context.h
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h
@@ -614,5 +614,6 @@ GLboolean radeonMakeCurrent(__DRIcontext * driContextPriv,
 			    __DRIdrawable * driDrawPriv,
 			    __DRIdrawable * driReadPriv);
 extern void radeonDestroyContext(__DRIcontext * driContextPriv);
+void radeon_prepare_render(radeonContextPtr radeon);
 
 #endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c
index 82107cc..d3d7b21 100644
--- a/src/mesa/drivers/dri/radeon/radeon_screen.c
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.c
@@ -376,6 +376,21 @@ static const __DRItexBufferExtension r600TexBufferExtension = {
 };
 #endif
 
+static void
+radeonDRI2Flush(__DRIdrawable *drawable)
+{
+    radeonContextPtr rmesa;
+
+    rmesa = (radeonContextPtr) drawable->driContextPriv->driverPrivate;
+    radeonFlush(rmesa->glCtx);
+}
+
+static const struct __DRI2flushExtensionRec radeonFlushExtension = {
+    { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
+    radeonDRI2Flush,
+    dri2InvalidateDrawable,
+};
+
 static int radeon_set_screen_flags(radeonScreenPtr screen, int device_id)
 {
    screen->device_id = device_id;
@@ -1379,6 +1394,8 @@ radeonCreateScreen2(__DRIscreen *sPriv)
    screen->extensions[i++] = &r600TexBufferExtension.base;
 #endif
 
+   screen->extensions[i++] = &radeonFlushExtension.base;
+
    screen->extensions[i++] = NULL;
    sPriv->extensions = screen->extensions;
 
diff --git a/src/mesa/drivers/dri/radeon/radeon_swtcl.c b/src/mesa/drivers/dri/radeon/radeon_swtcl.c
index f2fcb46..67be466 100644
--- a/src/mesa/drivers/dri/radeon/radeon_swtcl.c
+++ b/src/mesa/drivers/dri/radeon/radeon_swtcl.c
@@ -408,6 +408,8 @@ static GLboolean radeon_run_render( GLcontext *ctx,
        !radeon_dma_validate_render( ctx, VB ))
       return GL_TRUE;		
 
+   radeon_prepare_render(&rmesa->radeon);
+
    tnl->Driver.Render.Start( ctx );
 
    for (i = 0 ; i < VB->PrimitiveCount ; i++)
diff --git a/src/mesa/drivers/dri/radeon/radeon_tcl.c b/src/mesa/drivers/dri/radeon/radeon_tcl.c
index ea796e1..5e1718f 100644
--- a/src/mesa/drivers/dri/radeon/radeon_tcl.c
+++ b/src/mesa/drivers/dri/radeon/radeon_tcl.c
@@ -252,6 +252,8 @@ void radeonTclPrimitive( GLcontext *ctx,
    GLuint se_cntl;
    GLuint newprim = hw_prim | RADEON_CP_VC_CNTL_TCL_ENABLE;
 
+   radeon_prepare_render(&rmesa->radeon);
+
    if (newprim != rmesa->tcl.hw_primitive ||
        !discrete_prim[hw_prim&0xf]) {
       RADEON_NEWPRIM( rmesa );




More information about the mesa-commit mailing list