Mesa (8.0): mesa: add a couple fast-paths to fast_read_rgba_pixels_memcpy()

Brian Paul brianp at kemper.freedesktop.org
Tue Apr 17 23:42:41 UTC 2012


Module: Mesa
Branch: 8.0
Commit: 49ed43b6de98482c898334a9abfc574720391c9f
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=49ed43b6de98482c898334a9abfc574720391c9f

Author: Brian Paul <brianp at vmware.com>
Date:   Tue Apr 17 17:41:09 2012 -0600

mesa: add a couple fast-paths to fast_read_rgba_pixels_memcpy()

Accelerates a few glReadPixels cases for WebGL.
See https://bugs.freedesktop.org/show_bug.cgi?id=48545

v2: Per Jose, use bit twiddling for the swizzle case instead of ubyte
arrays (it's about 44% faster).

Note: This is a candidate for the 8.0 branch.

Reviewed-by: José Fonseca <jfonseca at vmware.com>

(cherry picked from commit a5e95a419e4f6ad93e35a960113d97ae2de27476)

---

 src/mesa/main/readpix.c |   56 ++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 51 insertions(+), 5 deletions(-)

diff --git a/src/mesa/main/readpix.c b/src/mesa/main/readpix.c
index 5b3c246..f3a0d10 100644
--- a/src/mesa/main/readpix.c
+++ b/src/mesa/main/readpix.c
@@ -196,6 +196,11 @@ read_stencil_pixels( struct gl_context *ctx,
    ctx->Driver.UnmapRenderbuffer(ctx, rb);
 }
 
+
+/**
+ * Try to do glReadPixels of RGBA data using a simple memcpy or swizzle.
+ * \return GL_TRUE if successful, GL_FALSE otherwise (use the slow path)
+ */
 static GLboolean
 fast_read_rgba_pixels_memcpy( struct gl_context *ctx,
 			      GLint x, GLint y,
@@ -208,8 +213,20 @@ fast_read_rgba_pixels_memcpy( struct gl_context *ctx,
    struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
    GLubyte *dst, *map;
    int dstStride, stride, j, texelBytes;
+   GLboolean swizzle_rb = GL_FALSE, copy_xrgb = GL_FALSE;
 
-   if (!_mesa_format_matches_format_and_type(rb->Format, format, type))
+   /* XXX we could check for other swizzle/special cases here as needed */
+   if (rb->Format == MESA_FORMAT_RGBA8888_REV &&
+       format == GL_BGRA &&
+       type == GL_UNSIGNED_INT_8_8_8_8_REV) {
+      swizzle_rb = GL_TRUE;
+   }
+   else if (rb->Format == MESA_FORMAT_XRGB8888 &&
+            format == GL_BGRA &&
+            type == GL_UNSIGNED_INT_8_8_8_8_REV) {
+      copy_xrgb = GL_TRUE;
+   }
+   else if (!_mesa_format_matches_format_and_type(rb->Format, format, type))
       return GL_FALSE;
 
    /* check for things we can't handle here */
@@ -240,10 +257,39 @@ fast_read_rgba_pixels_memcpy( struct gl_context *ctx,
    }
 
    texelBytes = _mesa_get_format_bytes(rb->Format);
-   for (j = 0; j < height; j++) {
-      memcpy(dst, map, width * texelBytes);
-      dst += dstStride;
-      map += stride;
+
+   if (swizzle_rb) {
+      /* swap R/B */
+      for (j = 0; j < height; j++) {
+         int i;
+         for (i = 0; i < width; i++) {
+            GLuint *dst4 = (GLuint *) dst, *map4 = (GLuint *) map;
+            GLuint pixel = map4[i];
+            dst4[i] = (pixel & 0xff00ff00)
+                   | ((pixel & 0x00ff0000) >> 16)
+                   | ((pixel & 0x000000ff) << 16);
+         }
+         dst += dstStride;
+         map += stride;
+      }
+   } else if (copy_xrgb) {
+      /* convert xrgb -> argb */
+      for (j = 0; j < height; j++) {
+         GLuint *dst4 = (GLuint *) dst, *map4 = (GLuint *) map;
+         int i;
+         for (i = 0; i < width; i++) {
+            dst4[i] = map4[i] | 0xff000000;  /* set A=0xff */
+         }
+         dst += dstStride;
+         map += stride;
+      }
+   } else {
+      /* just memcpy */
+      for (j = 0; j < height; j++) {
+         memcpy(dst, map, width * texelBytes);
+         dst += dstStride;
+         map += stride;
+      }
    }
 
    ctx->Driver.UnmapRenderbuffer(ctx, rb);




More information about the mesa-commit mailing list