radeon: fix frontbuffer read/drawpixels
authorDave Airlie <airlied@redhat.com>
Fri, 18 Dec 2009 04:35:03 +0000 (14:35 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 18 Dec 2009 04:35:03 +0000 (14:35 +1000)
Bug 25699

The main problem was the optimising flush wasn't doing the front
rendering checks properly.

src/mesa/drivers/dri/r600/r700_clear.c
src/mesa/drivers/dri/radeon/radeon_common.c
src/mesa/drivers/dri/radeon/radeon_common.h
src/mesa/drivers/dri/radeon/radeon_ioctl.c
src/mesa/drivers/dri/radeon/radeon_span.c

index c6546ab00c2e674daa81dd18e7949d33fc173103..526d3843d16e7669fdbc4081ea494ef4439e8201 100644 (file)
@@ -57,6 +57,10 @@ void r700Clear(GLcontext * ctx, GLbitfield mask)
 
     radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s %x\n", __func__, mask);
 
+    if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT)) {
+        context->radeon.front_buffer_dirty = GL_TRUE;
+    }
+
     if( GL_TRUE == r700ClearFast(context, mask) )
     {
         return;
index 51fa6189377d78576ea666102d9b3f4fdc4a5ab4..2a2b16a54bd2bba0b9f2744f92ff157e3e6fd37f 100644 (file)
@@ -641,6 +641,27 @@ void radeonCopySubBuffer(__DRIdrawablePrivate * dPriv,
        }
 }
 
+/**
+ * Check if we're about to draw into the front color buffer.
+ * If so, set the intel->front_buffer_dirty field to true.
+ */
+void
+radeon_check_front_buffer_rendering(GLcontext *ctx)
+{
+       radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+       const struct gl_framebuffer *fb = ctx->DrawBuffer;
+
+       if (fb->Name == 0) {
+               /* drawing to window system buffer */
+               if (fb->_NumColorDrawBuffers > 0) {
+                       if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
+                               radeon->front_buffer_dirty = GL_TRUE;
+                       }
+               }
+       }
+}
+
+
 void radeon_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
 {
        radeonContextPtr radeon = RADEON_CONTEXT(ctx);
@@ -1095,7 +1116,7 @@ void radeonFlush(GLcontext *ctx)
           then no point flushing anything at all.
        */
        if (!radeon->dma.flush && !radeon->cmdbuf.cs->cdw && is_empty_list(&radeon->dma.reserved))
-               return;
+               goto flush_front;
 
        if (radeon->dma.flush)
                radeon->dma.flush( ctx );
@@ -1103,6 +1124,7 @@ void radeonFlush(GLcontext *ctx)
        if (radeon->cmdbuf.cs->cdw)
                rcommonFlushCmdBuf(radeon, __FUNCTION__);
 
+flush_front:
        if ((ctx->DrawBuffer->Name == 0) && radeon->front_buffer_dirty) {
                __DRIscreen *const screen = radeon->radeonScreen->driScreen;
 
index 0608fe2418c5b7daa1804baa2678c37f4069956a..faad145cc4978fcfce30b6469a0e5849c80b9935 100644 (file)
@@ -43,6 +43,8 @@ radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb,
                           struct radeon_bo *bo);
 struct radeon_renderbuffer *
 radeon_create_renderbuffer(gl_format format, __DRIdrawablePrivate *driDrawPriv);
+
+void radeon_check_front_buffer_rendering(GLcontext *ctx);
 static inline struct radeon_renderbuffer *radeon_renderbuffer(struct gl_renderbuffer *rb)
 {
        struct radeon_renderbuffer *rrb = (struct radeon_renderbuffer *)rb;
index a0106d00fa227bc95a1ea6267277e90ddd5b320c..13fd6f99719057c148006950d628013bd2b5422c 100644 (file)
@@ -575,6 +575,10 @@ static void radeonClear( GLcontext *ctx, GLbitfield mask )
    GLuint color_mask = 0;
    GLuint orig_mask = mask;
 
+   if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT)) {
+      rmesa->radeon.front_buffer_dirty = GL_TRUE;
+   }
+
    if ( RADEON_DEBUG & RADEON_IOCTL ) {
       fprintf( stderr, "radeonClear\n");
    }
index 37904dc8dc99debd11b9d694a06ec3adca326a3c..cffe8406628fec16ecb1ae528b5bfc50a27e4fd8 100644 (file)
@@ -828,18 +828,21 @@ static void map_unmap_rb(struct gl_renderbuffer *rb, int flag)
 }
 
 static void
-radeon_map_unmap_buffers(GLcontext *ctx, GLboolean map)
+radeon_map_unmap_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb,
+                            GLboolean map)
 {
        GLuint i, j;
 
        /* color draw buffers */
        for (j = 0; j < ctx->DrawBuffer->_NumColorDrawBuffers; j++)
-               map_unmap_rb(ctx->DrawBuffer->_ColorDrawBuffers[j], map);
+               map_unmap_rb(fb->_ColorDrawBuffers[j], map);
+
+       map_unmap_rb(fb->_ColorReadBuffer, map);
 
        /* check for render to textures */
        for (i = 0; i < BUFFER_COUNT; i++) {
                struct gl_renderbuffer_attachment *att =
-                       ctx->DrawBuffer->Attachment + i;
+                       fb->Attachment + i;
                struct gl_texture_object *tex = att->Texture;
                if (tex) {
                        /* Render to texture. Note that a mipmapped texture need not
@@ -855,15 +858,15 @@ radeon_map_unmap_buffers(GLcontext *ctx, GLboolean map)
                                radeon_teximage_unmap(image);
                }
        }
-
-       map_unmap_rb(ctx->ReadBuffer->_ColorReadBuffer, map);
-
+       
        /* depth buffer (Note wrapper!) */
-       if (ctx->DrawBuffer->_DepthBuffer)
-               map_unmap_rb(ctx->DrawBuffer->_DepthBuffer->Wrapped, map);
+       if (fb->_DepthBuffer)
+               map_unmap_rb(fb->_DepthBuffer->Wrapped, map);
+
+       if (fb->_StencilBuffer)
+               map_unmap_rb(fb->_StencilBuffer->Wrapped, map);
 
-       if (ctx->DrawBuffer->_StencilBuffer)
-               map_unmap_rb(ctx->DrawBuffer->_StencilBuffer->Wrapped, map);
+       radeon_check_front_buffer_rendering(ctx);
 }
 
 static void radeonSpanRenderStart(GLcontext * ctx)
@@ -888,23 +891,30 @@ static void radeonSpanRenderStart(GLcontext * ctx)
                        ctx->Driver.MapTexture(ctx, ctx->Texture.Unit[i]._Current);
        }
 
-       radeon_map_unmap_buffers(ctx, 1);
+       radeon_map_unmap_framebuffer(ctx, ctx->DrawBuffer, GL_TRUE);
+       if (ctx->ReadBuffer != ctx->DrawBuffer)
+               radeon_map_unmap_framebuffer(ctx, ctx->ReadBuffer, GL_TRUE);
 }
 
 static void radeonSpanRenderFinish(GLcontext * ctx)
 {
        radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
        int i;
+
        _swrast_flush(ctx);
-       if (!rmesa->radeonScreen->driScreen->dri2.enabled) {
-               UNLOCK_HARDWARE(rmesa);
-       }
+
        for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
                if (ctx->Texture.Unit[i]._ReallyEnabled)
                        ctx->Driver.UnmapTexture(ctx, ctx->Texture.Unit[i]._Current);
        }
 
-       radeon_map_unmap_buffers(ctx, 0);
+       radeon_map_unmap_framebuffer(ctx, ctx->DrawBuffer, GL_FALSE);
+       if (ctx->ReadBuffer != ctx->DrawBuffer)
+               radeon_map_unmap_framebuffer(ctx, ctx->ReadBuffer, GL_FALSE);
+
+       if (!rmesa->radeonScreen->driScreen->dri2.enabled) {
+               UNLOCK_HARDWARE(rmesa);
+       }
 }
 
 void radeonInitSpanFuncs(GLcontext * ctx)