[Mesa-dev] [PATCH 3/7] swrast: Use the fast copypixels code to implement fast glBlitFramebuffer().

Eric Anholt eric at anholt.net
Wed Jan 4 18:04:51 PST 2012


They were meaning to do the same thing of memcpying rows, so just
write the code once.
---
 src/mesa/swrast/s_blit.c    |  167 +++++++++----------------------------------
 src/mesa/swrast/s_copypix.c |   13 ++--
 src/mesa/swrast/swrast.h    |    5 ++
 3 files changed, 46 insertions(+), 139 deletions(-)

diff --git a/src/mesa/swrast/s_blit.c b/src/mesa/swrast/s_blit.c
index 803ad2e..6ad4f3f 100644
--- a/src/mesa/swrast/s_blit.c
+++ b/src/mesa/swrast/s_blit.c
@@ -449,117 +449,6 @@ blit_linear(struct gl_context *ctx,
    free(dstBuffer);
 }
 
-
-/**
- * Simple case:  Blit color, depth or stencil with no scaling or flipping.
- * XXX we could easily support vertical flipping here.
- */
-static void
-simple_blit(struct gl_context *ctx,
-            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
-            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-            GLbitfield buffer)
-{
-   struct gl_renderbuffer *readRb, *drawRb;
-   const GLint width = srcX1 - srcX0;
-   const GLint height = srcY1 - srcY0;
-   GLint row, srcY, dstY, yStep;
-   GLint comps, bytesPerRow;
-   void *rowBuffer;
-
-   /* only one buffer */
-   ASSERT(_mesa_bitcount(buffer) == 1);
-   /* no flipping checks */
-   ASSERT(srcX0 < srcX1);
-   ASSERT(srcY0 < srcY1);
-   ASSERT(dstX0 < dstX1);
-   ASSERT(dstY0 < dstY1);
-   /* size checks */
-   ASSERT(srcX1 - srcX0 == dstX1 - dstX0);
-   ASSERT(srcY1 - srcY0 == dstY1 - dstY0);
-
-   /* From the GL_ARB_framebuffer_object spec:
-    *
-    *     "If the source and destination buffers are identical, and the source
-    *      and destination rectangles overlap, the result of the blit operation
-    *      is undefined."
-    *
-    * However, we provide the expected result anyway by flipping the order of
-    * the memcpy of rows.
-    */
-   if (srcY0 > dstY0) {
-      /* src above dst: copy bottom-to-top */
-      yStep = 1;
-      srcY = srcY0;
-      dstY = dstY0;
-   }
-   else {
-      /* src below dst: copy top-to-bottom */
-      yStep = -1;
-      srcY = srcY1 - 1;
-      dstY = dstY1 - 1;
-   }
-
-   switch (buffer) {
-   case GL_COLOR_BUFFER_BIT:
-      readRb = ctx->ReadBuffer->_ColorReadBuffer;
-      drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
-      comps = 4;
-      break;
-   case GL_DEPTH_BUFFER_BIT:
-      readRb = ctx->ReadBuffer->_DepthBuffer;
-      drawRb = ctx->DrawBuffer->_DepthBuffer;
-      comps = 1;
-      break;
-   case GL_STENCIL_BUFFER_BIT:
-      readRb = ctx->ReadBuffer->_StencilBuffer;
-      drawRb = ctx->DrawBuffer->_StencilBuffer;
-      comps = 1;
-      break;
-   default:
-      _mesa_problem(ctx, "unexpected buffer in simple_blit()");
-      return;
-   }
-
-   ASSERT(readRb->DataType == drawRb->DataType);
-
-   /* compute bytes per row */
-   switch (readRb->DataType) {
-   case GL_UNSIGNED_BYTE:
-      bytesPerRow = comps * width * sizeof(GLubyte);
-      break;
-   case GL_UNSIGNED_SHORT:
-      bytesPerRow = comps * width * sizeof(GLushort);
-      break;
-   case GL_UNSIGNED_INT:
-      bytesPerRow = comps * width * sizeof(GLuint);
-      break;
-   case GL_FLOAT:
-      bytesPerRow = comps * width * sizeof(GLfloat);
-      break;
-   default:
-      _mesa_problem(ctx, "unexpected buffer type in simple_blit");
-      return;
-   }
-
-   /* allocate the row buffer */
-   rowBuffer = malloc(bytesPerRow);
-   if (!rowBuffer) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
-      return;
-   }
-
-   for (row = 0; row < height; row++) {
-      readRb->GetRow(ctx, readRb, width, srcX0, srcY, rowBuffer);
-      drawRb->PutRow(ctx, drawRb, width, dstX0, dstY, rowBuffer, NULL);
-      srcY += yStep;
-      dstY += yStep;
-   }
-
-   free(rowBuffer);
-}
-
-
 /**
  * Software fallback for glBlitFramebufferEXT().
  */
@@ -574,6 +463,11 @@ _swrast_BlitFramebuffer(struct gl_context *ctx,
       GL_DEPTH_BUFFER_BIT,
       GL_STENCIL_BUFFER_BIT
    };
+   static const GLenum buffer_enums[3] = {
+      GL_COLOR,
+      GL_DEPTH,
+      GL_STENCIL,
+   };
    GLint i;
 
    if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
@@ -584,39 +478,46 @@ _swrast_BlitFramebuffer(struct gl_context *ctx,
    if (SWRAST_CONTEXT(ctx)->NewState)
       _swrast_validate_derived(ctx);
 
-   swrast_render_start(ctx);
-
+   /* First, try covering whatever buffers possible using the fast 1:1 copy
+    * path.
+    */
    if (srcX1 - srcX0 == dstX1 - dstX0 &&
        srcY1 - srcY0 == dstY1 - dstY0 &&
        srcX0 < srcX1 &&
        srcY0 < srcY1 &&
        dstX0 < dstX1 &&
        dstY0 < dstY1) {
-      /* no stretching or flipping.
-       * filter doesn't matter.
-       */
       for (i = 0; i < 3; i++) {
          if (mask & buffers[i]) {
-            simple_blit(ctx, srcX0, srcY0, srcX1, srcY1,
-                        dstX0, dstY0, dstX1, dstY1, buffers[i]);
-         }
+	    if (swrast_fast_copy_pixels(ctx,
+					srcX0, srcY0,
+					srcX1 - srcX0, srcY1 - srcY0,
+					dstX0, dstY0,
+					buffer_enums[i])) {
+	       mask &= ~buffers[i];
+	    }
+	 }
       }
+
+      if (!mask)
+	 return;
    }
-   else {
-      if (filter == GL_NEAREST) {
-         for (i = 0; i < 3; i++) {
-            if (mask & buffers[i]) {
-               blit_nearest(ctx,  srcX0, srcY0, srcX1, srcY1,
-                            dstX0, dstY0, dstX1, dstY1, buffers[i]);
-            }
-         }
+
+   swrast_render_start(ctx);
+
+   if (filter == GL_NEAREST) {
+      for (i = 0; i < 3; i++) {
+	 if (mask & buffers[i]) {
+	    blit_nearest(ctx,  srcX0, srcY0, srcX1, srcY1,
+			 dstX0, dstY0, dstX1, dstY1, buffers[i]);
+	 }
       }
-      else {
-         ASSERT(filter == GL_LINEAR);
-         if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
-            blit_linear(ctx,  srcX0, srcY0, srcX1, srcY1,
-                        dstX0, dstY0, dstX1, dstY1);
-         }
+   }
+   else {
+      ASSERT(filter == GL_LINEAR);
+      if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
+	 blit_linear(ctx,  srcX0, srcY0, srcX1, srcY1,
+		     dstX0, dstY0, dstX1, dstY1);
       }
    }
 
diff --git a/src/mesa/swrast/s_copypix.c b/src/mesa/swrast/s_copypix.c
index 8fae01f..a14b44b 100644
--- a/src/mesa/swrast/s_copypix.c
+++ b/src/mesa/swrast/s_copypix.c
@@ -422,13 +422,13 @@ copy_stencil_pixels( struct gl_context *ctx, GLint srcx, GLint srcy,
 
 
 /**
- * Try to do a fast copy pixels with memcpy.
+ * Try to do a fast 1:1 blit with memcpy.
  * \return GL_TRUE if successful, GL_FALSE otherwise.
  */
-static GLboolean
-fast_copy_pixels(struct gl_context *ctx,
-                 GLint srcX, GLint srcY, GLsizei width, GLsizei height,
-                 GLint dstX, GLint dstY, GLenum type)
+GLboolean
+swrast_fast_copy_pixels(struct gl_context *ctx,
+			GLint srcX, GLint srcY, GLsizei width, GLsizei height,
+			GLint dstX, GLint dstY, GLenum type)
 {
    struct gl_framebuffer *srcFb = ctx->ReadBuffer;
    struct gl_framebuffer *dstFb = ctx->DrawBuffer;
@@ -578,7 +578,8 @@ _swrast_CopyPixels( struct gl_context *ctx,
 	 ctx->Pixel.ZoomX != 1.0F ||
 	 ctx->Pixel.ZoomY != 1.0F ||
 	 ctx->_ImageTransferState) &&
-       fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty, type)) {
+       swrast_fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty,
+			       type)) {
       /* all done */
       return;
    }
diff --git a/src/mesa/swrast/swrast.h b/src/mesa/swrast/swrast.h
index dd40551..468d22f 100644
--- a/src/mesa/swrast/swrast.h
+++ b/src/mesa/swrast/swrast.h
@@ -110,6 +110,11 @@ _swrast_CopyPixels( struct gl_context *ctx,
 		    GLsizei width, GLsizei height,
 		    GLenum type );
 
+extern GLboolean
+swrast_fast_copy_pixels(struct gl_context *ctx,
+			GLint srcX, GLint srcY, GLsizei width, GLsizei height,
+			GLint dstX, GLint dstY, GLenum type);
+
 extern void
 _swrast_DrawPixels( struct gl_context *ctx,
 		    GLint x, GLint y,
-- 
1.7.7.3



More information about the mesa-dev mailing list