From b7615e5240707b022b81478dde545cec7fb9397f Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 7 Apr 2009 17:32:29 -0600 Subject: [PATCH] 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 8926aa38a28..ebb1d1142aa 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 e151efcb88f..9ce5f3fe84c 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 9e151be51fb..c90ef029062 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); -- 2.30.2