[Mesa-dev] [PATCH 12/24] swrast: MapRenderbuffer in separate depth/stencil readpixels fastpath

Eric Anholt eric at anholt.net
Fri Oct 28 12:50:02 PDT 2011


This introduces two new span helper functions we'll want to use in
several palces as we move to MapRenderbuffer, which pull out integer
depth and stencil values from a renderbuffer mapping based on the
renderbuffer format.
---
 src/mesa/swrast/s_depth.h   |    1 -
 src/mesa/swrast/s_readpix.c |   76 ++++++++++++++++++++++++++++++++-----------
 src/mesa/swrast/s_stencil.c |   39 ++++++++++++++++++++++
 src/mesa/swrast/s_stencil.h |    4 ++
 4 files changed, 100 insertions(+), 20 deletions(-)

diff --git a/src/mesa/swrast/s_depth.h b/src/mesa/swrast/s_depth.h
index 44820ac..8d5cdfa 100644
--- a/src/mesa/swrast/s_depth.h
+++ b/src/mesa/swrast/s_depth.h
@@ -53,7 +53,6 @@ extern void
 _swrast_read_depth_span_uint( struct gl_context *ctx, struct gl_renderbuffer *rb,
                               GLint n, GLint x, GLint y, GLuint depth[] );
 
-
 extern void
 _swrast_clear_depth_buffer( struct gl_context *ctx, struct gl_renderbuffer *rb );
 
diff --git a/src/mesa/swrast/s_readpix.c b/src/mesa/swrast/s_readpix.c
index 7b74ed3..b4db25d 100644
--- a/src/mesa/swrast/s_readpix.c
+++ b/src/mesa/swrast/s_readpix.c
@@ -400,7 +400,7 @@ static GLboolean
 fast_read_depth_stencil_pixels(struct gl_context *ctx,
 			       GLint x, GLint y,
 			       GLsizei width, GLsizei height,
-			       GLenum type, GLvoid *dst, int dstStride)
+			       GLvoid *dst, int dstStride)
 {
    struct gl_framebuffer *fb = ctx->ReadBuffer;
    struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
@@ -411,9 +411,6 @@ fast_read_depth_stencil_pixels(struct gl_context *ctx,
    if (rb != stencilRb)
       return GL_FALSE;
 
-   if (type != GL_UNSIGNED_INT_24_8)
-      return GL_FALSE;
-
    if (rb->Format != MESA_FORMAT_Z24_S8 &&
        rb->Format != MESA_FORMAT_S8_Z24)
       return GL_FALSE;
@@ -445,6 +442,53 @@ fast_read_depth_stencil_pixels(struct gl_context *ctx,
 
 
 /**
+ * For separate depth/stencil buffers being read as 24/8 depth/stencil, memcpy
+ * the data (possibly swapping 8/24 vs 24/8 as we go).
+ */
+static GLboolean
+fast_read_depth_stencil_pixels_separate(struct gl_context *ctx,
+					GLint x, GLint y,
+					GLsizei width, GLsizei height,
+					uint32_t *dst, int dstStride)
+{
+   struct gl_framebuffer *fb = ctx->ReadBuffer;
+   struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
+   struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
+   GLubyte *depthMap, *stencilMap;
+   int depthStride, stencilStride, i, j;
+
+   if (_mesa_get_format_datatype(depthRb->Format) != GL_UNSIGNED_INT)
+      return GL_FALSE;
+
+   ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
+			       GL_MAP_READ_BIT, &depthMap, &depthStride);
+   ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
+			       GL_MAP_READ_BIT, &stencilMap, &stencilStride);
+
+   for (j = 0; j < height; j++) {
+      GLstencil stencilVals[MAX_WIDTH];
+
+      _mesa_unpack_uint_z_row(depthRb->Format, width, depthMap, dst);
+      _swrast_read_stencil_span_mapped(ctx, stencilRb, stencilMap, width,
+				       stencilVals);
+
+      for (i = 0; i < width; i++) {
+	 dst[i] = (dst[i] & 0xffffff00) | stencilVals[i];
+      }
+
+      depthMap += depthStride;
+      stencilMap += stencilStride;
+      dst += dstStride / 4;
+   }
+
+   ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
+   ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
+
+   return GL_TRUE;
+}
+
+
+/**
  * Read combined depth/stencil values.
  * We'll have already done error checking to be sure the expected
  * depth and stencil buffers really exist.
@@ -477,10 +521,16 @@ read_depth_stencil_pixels(struct gl_context *ctx,
    dstStride = _mesa_image_row_stride(packing, width,
 				      GL_DEPTH_STENCIL_EXT, type);
 
-   if (!scaleOrBias && !stencilTransfer && !packing->SwapBytes) {
-      if (fast_read_depth_stencil_pixels(ctx, x, y, width, height, type,
+   /* Fast 24/8 reads. */
+   if (type == GL_UNSIGNED_INT_24_8 &&
+       !scaleOrBias && !stencilTransfer && !packing->SwapBytes) {
+      if (fast_read_depth_stencil_pixels(ctx, x, y, width, height,
 					 dst, dstStride))
 	 return;
+
+      if (fast_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
+						  (uint32_t *)dst, dstStride))
+	 return;
    }
 
       /* Reading GL_DEPTH_STENCIL pixels from separate depth/stencil buffers,
@@ -496,19 +546,7 @@ read_depth_stencil_pixels(struct gl_context *ctx,
          _swrast_read_stencil_span(ctx, stencilRb, width,
                                    x, y + i, stencilVals);
 
-         if (!scaleOrBias && !stencilTransfer
-             && ctx->ReadBuffer->Visual.depthBits == 24) {
-            /* ideal case */
-            GLuint zVals[MAX_WIDTH]; /* 24-bit values! */
-            GLint j;
-            ASSERT(depthRb->DataType == GL_UNSIGNED_INT);
-            /* note, we've already been clipped */
-            depthRb->GetRow(ctx, depthRb, width, x, y + i, zVals);
-            for (j = 0; j < width; j++) {
-               depthStencilDst[j] = (zVals[j] << 8) | (stencilVals[j] & 0xff);
-            }
-         }
-         else {
+	 {
             /* general case */
             GLfloat depthVals[MAX_WIDTH];
             _swrast_read_depth_span_float(ctx, depthRb, width, x, y + i,
diff --git a/src/mesa/swrast/s_stencil.c b/src/mesa/swrast/s_stencil.c
index e713e23..e812550 100644
--- a/src/mesa/swrast/s_stencil.c
+++ b/src/mesa/swrast/s_stencil.c
@@ -1070,6 +1070,45 @@ _swrast_read_stencil_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
 }
 
 
+/**
+ * Return a span of stencil values from a stencil buffer mapped by
+ * MapRenderbuffer().
+ *
+ * Used for glRead/CopyPixels
+ */
+void
+_swrast_read_stencil_span_mapped(struct gl_context *ctx,
+				 struct gl_renderbuffer *rb,
+				 void *map, GLint n, GLstencil *stencil)
+{
+   uint8_t *map_u8 = map;
+   uint32_t *map_u32 = map;
+   int i;
+
+   switch (rb->Format) {
+   case MESA_FORMAT_S8:
+      for (i = 0; i < n; i++)
+	 stencil[i] = map_u8[i];
+      break;
+   case MESA_FORMAT_S8_Z24:
+      for (i = 0; i < n; i++)
+	 stencil[i] = map_u32[i] >> 24;
+      break;
+   case MESA_FORMAT_Z24_S8:
+      for (i = 0; i < n; i++)
+	 stencil[i] = map_u32[i] & 0xff;
+      break;
+   case MESA_FORMAT_Z32_FLOAT_X24S8:
+      for (i = 0; i < n; i++)
+	 stencil[i] = map_u32[i * 2 + 1] & 0xff;
+      break;
+   default:
+      _mesa_problem(ctx, "Unknown stencil format %s\n",
+		    _mesa_get_format_name(rb->Format));
+   }
+}
+
+
 
 /**
  * Write a span of stencil values to the stencil buffer.  This function
diff --git a/src/mesa/swrast/s_stencil.h b/src/mesa/swrast/s_stencil.h
index 00f5179..06a2ddd 100644
--- a/src/mesa/swrast/s_stencil.h
+++ b/src/mesa/swrast/s_stencil.h
@@ -40,6 +40,10 @@ extern void
 _swrast_read_stencil_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
                           GLint n, GLint x, GLint y, GLstencil stencil[]);
 
+void
+_swrast_read_stencil_span_mapped(struct gl_context *ctx,
+				 struct gl_renderbuffer *rb,
+				 void *map, GLint n, GLstencil *stencil);
 
 extern void
 _swrast_write_stencil_span( struct gl_context *ctx, GLint n, GLint x, GLint y,
-- 
1.7.7



More information about the mesa-dev mailing list