radeon: Add DRI2 flush extension to so we synchronize properly.
authorMario Kleiner <mario.kleiner@tuebingen.mpg.de>
Sun, 25 Jul 2010 14:29:24 +0000 (16:29 +0200)
committerJerome Glisse <jglisse@redhat.com>
Mon, 2 Aug 2010 14:43:51 +0000 (10:43 -0400)
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@redhat.com>
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
src/mesa/drivers/dri/r200/r200_swtcl.c
src/mesa/drivers/dri/r200/r200_tcl.c
src/mesa/drivers/dri/r300/r300_render.c
src/mesa/drivers/dri/r600/r700_clear.c
src/mesa/drivers/dri/r600/r700_render.c
src/mesa/drivers/dri/radeon/radeon_common_context.c
src/mesa/drivers/dri/radeon/radeon_common_context.h
src/mesa/drivers/dri/radeon/radeon_screen.c
src/mesa/drivers/dri/radeon/radeon_swtcl.c
src/mesa/drivers/dri/radeon/radeon_tcl.c

index 262fe3cddee8ced62a68bc9b3964e482f385cc06..dbf4ad477db30e7c883aa0befe76f1d3c37c5a23 100644 (file)
@@ -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) {
index d43e14581e931faa03cc3eb30bd398731e5ef78b..4ae0f304918673d67ada3a7188a03b3f230e0ab6 100644 (file)
@@ -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 */
index bb8f91491f556dddf00e2c64bcf6a9327b44cc88..cf89ab7ec3db95cb96bfdd8e14b4ab5f92d8e35b 100644 (file)
@@ -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);
 
index 09c48565b68a3e1fc7cde6a1c60002986e284332..d1008f28b9bfa39760417f88f54b2db35b72e28a 100644 (file)
@@ -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;
index 1929b7cc129798afb1fa9ff51ae53429715bd536..316a0943f4ec0eb36f51811d9933d467c9a9e874 100644 (file)
@@ -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.
         */
index 5a7d52c4d2f2e4651eb79f06a800740794edab98..3665944c3e2192f7984a265db03d855b7e649331 100644 (file)
@@ -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)) {
index 5156c5d0d0a8bcf5db3e2c9ded72205ef407b82f..ec773cfa522042dcfc1fa490c79a7711f25c4937 100644 (file)
@@ -614,5 +614,6 @@ GLboolean radeonMakeCurrent(__DRIcontext * driContextPriv,
                            __DRIdrawable * driDrawPriv,
                            __DRIdrawable * driReadPriv);
 extern void radeonDestroyContext(__DRIcontext * driContextPriv);
+void radeon_prepare_render(radeonContextPtr radeon);
 
 #endif
index 82107cc6aeb5fad49cceb6d25fa4c0248988c87d..d3d7b216baabc0d09b66551d3697ed6227e8bdc8 100644 (file)
@@ -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;
 
index f2fcb46688aa21cbc3e937213c456e2596ca4284..67be466c3f8a8e254028c2168918295dd49d9d3c 100644 (file)
@@ -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++)
index ea796e1a45f826f53c149ba5192702f2193b5327..5e1718f9dfcba3eb84043e354569d7c7bb764d4e 100644 (file)
@@ -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 );