Mesa (master): st: implement GL_DEPTH_STENCIL format for glReadPixels and DrawPixels()

Brian Paul brianp at kemper.freedesktop.org
Tue Apr 7 23:32:59 UTC 2009


Module: Mesa
Branch: master
Commit: b7615e5240707b022b81478dde545cec7fb9397f
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=b7615e5240707b022b81478dde545cec7fb9397f

Author: Brian Paul <brianp at vmware.com>
Date:   Tue Apr  7 17:32:29 2009 -0600

st: implement GL_DEPTH_STENCIL format for glReadPixels and DrawPixels()

---

 src/mesa/state_tracker/st_cb_drawpixels.c |   82 +++++++++++++++++++----------
 src/mesa/state_tracker/st_cb_readpixels.c |   54 ++++++++++++++-----
 src/mesa/state_tracker/st_cb_readpixels.h |    3 +-
 3 files changed, 96 insertions(+), 43 deletions(-)

diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index 8926aa3..ebb1d11 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -309,6 +309,8 @@ _mesa_base_format(GLenum format)
    switch (format) {
    case GL_DEPTH_COMPONENT:
       return GL_DEPTH_COMPONENT;
+   case GL_DEPTH_STENCIL:
+      return GL_DEPTH_STENCIL;
    case GL_STENCIL_INDEX:
       return GL_STENCIL_INDEX;
    default:
@@ -617,7 +619,7 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
 
 static void
 draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
-                    GLsizei width, GLsizei height, GLenum type,
+                    GLsizei width, GLsizei height, GLenum format, GLenum type,
                     const struct gl_pixelstore_attrib *unpack,
                     const GLvoid *pixels)
 {
@@ -634,6 +636,11 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
 
    strb = st_renderbuffer(ctx->DrawBuffer->
                           Attachment[BUFFER_STENCIL].Renderbuffer);
+
+   if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+      y = ctx->DrawBuffer->Height - y - height;
+   }
+
    pt = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0,
                                  PIPE_TRANSFER_WRITE, x, y,
                                  width, height);
@@ -650,53 +657,74 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
       const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
       GLint row;
       for (row = 0; row < height; row++) {
-         GLint spanY = row;
-         GLubyte values[MAX_WIDTH];
+         GLubyte sValues[MAX_WIDTH];
+         GLuint zValues[MAX_WIDTH];
          GLenum destType = GL_UNSIGNED_BYTE;
          const GLvoid *source = _mesa_image_address2d(unpack, pixels,
                                                       width, height,
-                                                      GL_COLOR_INDEX, type,
+                                                      format, type,
                                                       row, skipPixels);
-         _mesa_unpack_stencil_span(ctx, spanWidth, destType, values,
+         _mesa_unpack_stencil_span(ctx, spanWidth, destType, sValues,
                                    type, source, unpack,
                                    ctx->_ImageTransferState);
+
+         if (format == GL_DEPTH_STENCIL) {
+            _mesa_unpack_depth_span(ctx, spanWidth, GL_UNSIGNED_INT, zValues,
+                                    (1 << 24) - 1, type, source, unpack);
+         }
+
          if (zoom) {
-            /*
-            _swrast_write_zoomed_stencil_span(ctx, 0, 0, spanWidth,
-                                              spanX, spanY, values);
-            */
+            _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with "
+                          "zoom not complete");
          }
-         else {
+
+         {
+            GLint spanY;
+
             if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
-               spanY = height - spanY - 1;
+               spanY = height - row - 1;
+            }
+            else {
+               spanY = row;
             }
 
+            /* now pack the stencil (and Z) values in the dest format */
             switch (pt->format) {
             case PIPE_FORMAT_S8_UNORM:
                {
                   ubyte *dest = stmap + spanY * pt->stride + spanX;
-                  memcpy(dest, values, spanWidth);
+                  memcpy(dest, sValues, spanWidth);
                }
                break;
             case PIPE_FORMAT_S8Z24_UNORM:
-               {
+               if (format == GL_DEPTH_STENCIL) {
+                  uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
+                  GLint k;
+                  for (k = 0; k < spanWidth; k++) {
+                     dest[k] = zValues[k] | (sValues[k] << 24);
+                  }
+               }
+               else {
                   uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
                   GLint k;
                   for (k = 0; k < spanWidth; k++) {
-                     uint p = dest[k];
-                     p = (p & 0xffffff) | (values[k] << 24);
-                     dest[k] = p;
+                     dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24);
                   }
                }
                break;
             case PIPE_FORMAT_Z24S8_UNORM:
-               {
+               if (format == GL_DEPTH_STENCIL) {
                   uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
                   GLint k;
                   for (k = 0; k < spanWidth; k++) {
-                     uint p = dest[k];
-                     p = (p & 0xffffff00) | (values[k] & 0xff);
-                     dest[k] = p;
+                     dest[k] = zValues[k] | (sValues[k] << 24);
+                  }
+               }
+               else {
+                  uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
+                  GLint k;
+                  for (k = 0; k < spanWidth; k++) {
+                     dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff);
                   }
                }
                break;
@@ -731,8 +759,10 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
    GLuint bufferFormat;
    const GLfloat *color;
 
-   if (format == GL_STENCIL_INDEX) {
-      draw_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels);
+   if (format == GL_STENCIL_INDEX ||
+       format == GL_DEPTH_STENCIL) {
+      draw_stencil_pixels(ctx, x, y, width, height, format, type,
+                          unpack, pixels);
       return;
    }
 
@@ -747,11 +777,6 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
       stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE);
       color = ctx->Current.RasterColor;
    }
-   else if (format == GL_STENCIL_INDEX) {
-      ps = st->state.framebuffer.zsbuf;
-      /* XXX special case - can't use texture map */
-      color = NULL;
-   }
    else {
       ps = st->state.framebuffer.cbufs[0];
       stfp = combined_drawpix_fragment_program(ctx);
@@ -797,7 +822,8 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
    }
 
    /* this will do stencil pixel transfer ops */
-   st_read_stencil_pixels(ctx, srcx, srcy, width, height, GL_UNSIGNED_BYTE,
+   st_read_stencil_pixels(ctx, srcx, srcy, width, height,
+                          GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
                           &ctx->DefaultPacking, buffer);
 
    ptDraw = screen->get_tex_transfer(screen, rbDraw->texture, 0, 0, 0,
diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c
index e151efc..9ce5f3f 100644
--- a/src/mesa/state_tracker/st_cb_readpixels.c
+++ b/src/mesa/state_tracker/st_cb_readpixels.c
@@ -56,7 +56,8 @@
  */
 void
 st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
-                       GLsizei width, GLsizei height, GLenum type,
+                       GLsizei width, GLsizei height,
+                       GLenum format, GLenum type,
                        const struct gl_pixelstore_attrib *packing,
                        GLvoid *pixels)
 {
@@ -84,7 +85,8 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
    /* process image row by row */
    for (j = 0; j < height; j++) {
       GLvoid *dest;
-      GLstencil values[MAX_WIDTH];
+      GLstencil sValues[MAX_WIDTH];
+      GLfloat zValues[MAX_WIDTH];
       GLint srcY;
 
       if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
@@ -94,29 +96,47 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
          srcY = j;
       }
 
-      /* get stencil values */
+      /* get stencil (and Z) values */
       switch (pt->format) {
       case PIPE_FORMAT_S8_UNORM:
          {
             const ubyte *src = stmap + srcY * pt->stride;
-            memcpy(values, src, width);
+            memcpy(sValues, src, width);
          }
          break;
       case PIPE_FORMAT_S8Z24_UNORM:
-         {
+         if (format == GL_DEPTH_STENCIL) {
+            const uint *src = (uint *) (stmap + srcY * pt->stride);
+            const GLfloat scale = 1.0 / (0xffffff);
+            GLint k;
+            for (k = 0; k < width; k++) {
+               sValues[k] = src[k] >> 24;
+               zValues[k] = (src[k] & 0xffffff) * scale;
+            }
+         }
+         else {
             const uint *src = (uint *) (stmap + srcY * pt->stride);
             GLint k;
             for (k = 0; k < width; k++) {
-               values[k] = src[k] >> 24;
+               sValues[k] = src[k] >> 24;
             }
          }
          break;
       case PIPE_FORMAT_Z24S8_UNORM:
-         {
+         if (format == GL_DEPTH_STENCIL) {
             const uint *src = (uint *) (stmap + srcY * pt->stride);
+            const GLfloat scale = 1.0 / (0xffffff);
             GLint k;
             for (k = 0; k < width; k++) {
-               values[k] = src[k] & 0xff;
+               sValues[k] = src[k] & 0xff;
+               zValues[k] = (src[k] >> 8) * scale;
+            }
+         }
+         else {
+            const uint *src = (uint *) (stmap + srcY * pt->stride);
+            GLint k;
+            for (k = 0; k < width; k++) {
+               sValues[k] = src[k] & 0xff;
             }
          }
          break;
@@ -126,12 +146,16 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
 
       /* store */
       dest = _mesa_image_address2d(packing, pixels, width, height,
-                                   GL_STENCIL_INDEX, type, j, 0);
-
-      _mesa_pack_stencil_span(ctx, width, type, dest, values, packing);
+                                   format, type, j, 0);
+      if (format == GL_DEPTH_STENCIL) {
+         _mesa_pack_depth_stencil_span(ctx, width, dest,
+                                       zValues, sValues, packing);
+      }
+      else {
+         _mesa_pack_stencil_span(ctx, width, type, dest, sValues, packing);
+      }
    }
 
-
    /* unmap the stencil buffer */
    screen->transfer_unmap(screen, pt);
    screen->tex_transfer_destroy(pt);
@@ -329,8 +353,10 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
    /* make sure rendering has completed */
    st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
 
-   if (format == GL_STENCIL_INDEX) {
-      st_read_stencil_pixels(ctx, x, y, width, height, type, pack, dest);
+   if (format == GL_STENCIL_INDEX ||
+       format == GL_DEPTH_STENCIL) {
+      st_read_stencil_pixels(ctx, x, y, width, height,
+                             format, type, pack, dest);
       return;
    }
    else if (format == GL_DEPTH_COMPONENT) {
diff --git a/src/mesa/state_tracker/st_cb_readpixels.h b/src/mesa/state_tracker/st_cb_readpixels.h
index 9e151be..c90ef02 100644
--- a/src/mesa/state_tracker/st_cb_readpixels.h
+++ b/src/mesa/state_tracker/st_cb_readpixels.h
@@ -34,7 +34,8 @@ st_get_color_read_renderbuffer(GLcontext *ctx);
 
 extern void
 st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
-                       GLsizei width, GLsizei height, GLenum type,
+                       GLsizei width, GLsizei height,
+                       GLenum format, GLenum type,
                        const struct gl_pixelstore_attrib *packing,
                        GLvoid *pixels);
 




More information about the mesa-commit mailing list