intel: Support blitting to multiple color draw buffers
authorAnuj Phogat <anuj.phogat@gmail.com>
Wed, 12 Dec 2012 03:36:05 +0000 (19:36 -0800)
committerIan Romanick <ian.d.romanick@intel.com>
Tue, 15 Jan 2013 23:08:55 +0000 (15:08 -0800)
This patch enables blitting to multiple color attachments of a
framebuffer.  It also fixes a case when blitting to a framebuffer with
renderbuffer/texture attached to non-zero attachment point
i.e. GL_COLOR_ATTACHMENT{1, 2, ...}.  Earlier we were incorrectly
blitting to GL_COLOR_ATTACHMENT0 by default.

V2: Use intel_copy_texsubimage() for blitting only if all the color
attachments can blit using it.

Signed-off-by: Anuj Phogat <anuj.phogat@gmail.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/mesa/drivers/dri/i965/brw_blorp_blit.cpp
src/mesa/drivers/dri/intel/intel_fbo.c

index 69dab75d2c6bbfa4b677e9a7f2b6c2835cefff37..bc7916a1bd4340000476653065b66c94afc5fb75 100644 (file)
@@ -263,8 +263,9 @@ try_blorp_blit(struct intel_context *intel,
       }
       for (unsigned i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; ++i) {
          dst_irb = intel_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[i]);
-         do_blorp_blit(intel, buffer_bit, src_irb, dst_irb, srcX0, srcY0,
-                       dstX0, dstY0, dstX1, dstY1, mirror_x, mirror_y);
+        if (dst_irb)
+            do_blorp_blit(intel, buffer_bit, src_irb, dst_irb, srcX0, srcY0,
+                          dstX0, dstY0, dstX1, dstY1, mirror_x, mirror_y);
       }
       break;
    case GL_DEPTH_BUFFER_BIT:
index 034fa8a96d542c8aecff47134602abcf9994cc36..481080944dd786dc3a94ac51dde8d8d8e606cd55 100644 (file)
@@ -793,44 +793,72 @@ intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
                                           GLbitfield mask, GLenum filter)
 {
    if (mask & GL_COLOR_BUFFER_BIT) {
+      GLint i;
       const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
       const struct gl_framebuffer *readFb = ctx->ReadBuffer;
-      const struct gl_renderbuffer_attachment *drawAtt =
-         &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
+      const struct gl_renderbuffer_attachment *drawAtt;
       struct intel_renderbuffer *srcRb = 
          intel_renderbuffer(readFb->_ColorReadBuffer);
 
-      /* If the source and destination are the same size with no
-         mirroring, the rectangles are within the size of the
-         texture and there is no scissor then we can use
-         glCopyTexSubimage2D to implement the blit. This will end
-         up as a fast hardware blit on some drivers */
-      if (srcRb && drawAtt && drawAtt->Texture &&
-          srcX0 - srcX1 == dstX0 - dstX1 &&
-          srcY0 - srcY1 == dstY0 - dstY1 &&
-          srcX1 >= srcX0 &&
-          srcY1 >= srcY0 &&
-          srcX0 >= 0 && srcX1 <= readFb->Width &&
-          srcY0 >= 0 && srcY1 <= readFb->Height &&
-          dstX0 >= 0 && dstX1 <= drawFb->Width &&
-          dstY0 >= 0 && dstY1 <= drawFb->Height &&
-          !ctx->Scissor.Enabled) {
-         const struct gl_texture_object *texObj = drawAtt->Texture;
-         const GLuint dstLevel = drawAtt->TextureLevel;
-         const GLenum target = texObj->Target;
-
-         struct gl_texture_image *texImage =
-            _mesa_select_tex_image(ctx, texObj, target, dstLevel);
-
-         if (intel_copy_texsubimage(intel_context(ctx),
-                                    intel_texture_image(texImage),
-                                    dstX0, dstY0,
-                                    srcRb,
-                                    srcX0, srcY0,
-                                    srcX1 - srcX0, /* width */
-                                    srcY1 - srcY0))
-            mask &= ~GL_COLOR_BUFFER_BIT;
+      /* If the source and destination are the same size with no mirroring,
+       * the rectangles are within the size of the texture and there is no
+       * scissor then we can use glCopyTexSubimage2D to implement the blit.
+       * This will end up as a fast hardware blit on some drivers.
+       */
+      const GLboolean use_intel_copy_texsubimage =
+         srcX0 - srcX1 == dstX0 - dstX1 &&
+         srcY0 - srcY1 == dstY0 - dstY1 &&
+         srcX1 >= srcX0 &&
+         srcY1 >= srcY0 &&
+         srcX0 >= 0 && srcX1 <= readFb->Width &&
+         srcY0 >= 0 && srcY1 <= readFb->Height &&
+         dstX0 >= 0 && dstX1 <= drawFb->Width &&
+         dstY0 >= 0 && dstY1 <= drawFb->Height &&
+         !ctx->Scissor.Enabled;
+
+      /* Verify that all the draw buffers can be blitted using
+       * intel_copy_texsubimage().
+       */
+      for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
+         int idx = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
+         if (idx == -1)
+            continue;
+         drawAtt = &drawFb->Attachment[idx];
+
+         if (srcRb && drawAtt && drawAtt->Texture &&
+             use_intel_copy_texsubimage)
+            continue;
+         else
+            return mask;
       }
+
+      /* Blit to all active draw buffers */
+      for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
+         int idx = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
+         if (idx == -1)
+            continue;
+         drawAtt = &drawFb->Attachment[idx];
+
+         {
+            const struct gl_texture_object *texObj = drawAtt->Texture;
+            const GLuint dstLevel = drawAtt->TextureLevel;
+            const GLenum target = texObj->Target;
+
+            struct gl_texture_image *texImage =
+               _mesa_select_tex_image(ctx, texObj, target, dstLevel);
+
+            if (!intel_copy_texsubimage(intel_context(ctx),
+                                        intel_texture_image(texImage),
+                                        dstX0, dstY0,
+                                        srcRb,
+                                        srcX0, srcY0,
+                                        srcX1 - srcX0, /* width */
+                                        srcY1 - srcY0))
+               return mask;
+         }
+      }
+
+      mask &= ~GL_COLOR_BUFFER_BIT;
    }
 
    return mask;