[Mesa-dev] [PATCH 6/6] mesa: Fix framebuffer blitting to GL_COLOR_ATTACHMENTi when i!=0

Anuj Phogat anuj.phogat at gmail.com
Mon Dec 17 19:35:07 PST 2012


This patch fixes a case when blitting to a framebuffer with
renderbuffers/textures attached to GL_COLOR_ATTACHMENT{1, 2, ...}.
Earlier we were incorrectly blitting to GL_COLOR_ATTACHMENT0 by default.

It also fixes a blitting case when drawAttachment->Texture ==
readAttachment->Texture. This was causing an assertion failure in intel's
i965 drivers (intel_miptree_attach_map()) with gles3 conformance test case:
framebuffer_blit_functionality_minifying_blit

V2: Fixed a case when number of draw buffer attachments are zero.
Signed-off-by: Anuj Phogat <anuj.phogat at gmail.com>
---
 src/mesa/main/fbobject.c |   14 +++++++++++++-
 src/mesa/swrast/s_blit.c |   33 ++++++++++++++++++++++++++-------
 2 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index d87239e..f4e427b 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -2818,8 +2818,20 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
 
    /* get color read/draw renderbuffers */
    if (mask & GL_COLOR_BUFFER_BIT) {
+      const  GLuint numColorDrawBuffers =
+         ctx->DrawBuffer->_NumColorDrawBuffers;
       colorReadRb = readFb->_ColorReadBuffer;
-      colorDrawRb = drawFb->_ColorDrawBuffers[0];
+
+      if (numColorDrawBuffers > 0) {
+         for (int i = 0; i < numColorDrawBuffers; i++) {
+            if (ctx->DrawBuffer->_ColorDrawBuffers[i] != NULL) {
+               colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
+	       break;
+	    }
+         }
+      }
+      else
+         colorDrawRb = NULL;
 
       /* From the EXT_framebuffer_object spec:
        *
diff --git a/src/mesa/swrast/s_blit.c b/src/mesa/swrast/s_blit.c
index b0c56a4..c579572 100644
--- a/src/mesa/swrast/s_blit.c
+++ b/src/mesa/swrast/s_blit.c
@@ -111,6 +111,9 @@ blit_nearest(struct gl_context *ctx,
              GLbitfield buffer)
 {
    struct gl_renderbuffer *readRb, *drawRb;
+   struct gl_renderbuffer_attachment *readAtt, *drawAtt;
+   struct gl_framebuffer *readFb = ctx->ReadBuffer;
+   struct gl_framebuffer *drawFb = ctx->DrawBuffer;
 
    const GLint srcWidth = ABS(srcX1 - srcX0);
    const GLint dstWidth = ABS(dstX1 - dstX0);
@@ -146,8 +149,18 @@ blit_nearest(struct gl_context *ctx,
 
    switch (buffer) {
    case GL_COLOR_BUFFER_BIT:
-      readRb = ctx->ReadBuffer->_ColorReadBuffer;
-      drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
+      readAtt = &readFb->Attachment[readFb->_ColorReadBufferIndex];
+      for (int i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
+          int idx = drawFb->_ColorDrawBufferIndexes[i];
+          if (idx != -1) {
+             drawAtt = &drawFb->Attachment[idx];
+          }
+          else {
+	     continue;
+	  }
+      }
+      readRb = readFb->_ColorReadBuffer;
+      drawRb = drawAtt->Renderbuffer;
 
       if (readRb->Format == drawRb->Format) {
 	 mode = DIRECT;
@@ -159,8 +172,10 @@ blit_nearest(struct gl_context *ctx,
 
       break;
    case GL_DEPTH_BUFFER_BIT:
-      readRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
-      drawRb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
+      readAtt = &readFb->Attachment[BUFFER_DEPTH];
+      drawAtt = &drawFb->Attachment[BUFFER_DEPTH];
+      readRb = readAtt->Renderbuffer;
+      drawRb = drawAtt->Renderbuffer;
 
       /* Note that for depth/stencil, the formats of src/dst must match.  By
        * using the core helpers for pack/unpack, we avoid needing to handle
@@ -175,8 +190,10 @@ blit_nearest(struct gl_context *ctx,
       pixelSize = 4;
       break;
    case GL_STENCIL_BUFFER_BIT:
-      readRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
-      drawRb = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
+      readAtt = &readFb->Attachment[BUFFER_STENCIL];
+      drawAtt = &drawFb->Attachment[BUFFER_STENCIL];
+      readRb = readAtt->Renderbuffer;
+      drawRb = drawAtt->Renderbuffer;
       mode = UNPACK_S;
       pixelSize = 1;
       break;
@@ -208,7 +225,9 @@ blit_nearest(struct gl_context *ctx,
       return;
    }
 
-   if (readRb == drawRb) {
+   if ((readRb == drawRb) ||
+       (readAtt->Texture && drawAtt->Texture &&
+        (readAtt->Texture == drawAtt->Texture))) {
       /* map whole buffer for read/write */
       /* XXX we could be clever and just map the union region of the
        * source and dest rects.
-- 
1.7.7.6



More information about the mesa-dev mailing list