diff options
author | Brian Paul <[email protected]> | 2011-12-24 08:54:25 -0700 |
---|---|---|
committer | Brian Paul <[email protected]> | 2011-12-24 08:54:25 -0700 |
commit | fd104a84591ae854c5d6adc81e2dc31ef6ab9e8a (patch) | |
tree | 4af4daba5c5ead84b87db74a6f047f2e992db537 /src/mesa/swrast/s_depth.c | |
parent | fb758aab27268593fa6e186d746e8f72831b214d (diff) |
swrast: do depth/stencil clearing with Map/UnmapRenderbuffer()
Another step toward getting rid of the renderbuffer PutRow/etc functions.
v2: fix assorted depth/stencil clear bugs found by Eric
Reviewed-by: José Fonseca <[email protected]>
Diffstat (limited to 'src/mesa/swrast/s_depth.c')
-rw-r--r-- | src/mesa/swrast/s_depth.c | 235 |
1 files changed, 197 insertions, 38 deletions
diff --git a/src/mesa/swrast/s_depth.c b/src/mesa/swrast/s_depth.c index 8d3ad105bce..09c0be68f07 100644 --- a/src/mesa/swrast/s_depth.c +++ b/src/mesa/swrast/s_depth.c @@ -26,6 +26,7 @@ #include "main/glheader.h" #include "main/context.h" #include "main/formats.h" +#include "main/format_pack.h" #include "main/macros.h" #include "main/imports.h" @@ -1312,14 +1313,21 @@ _swrast_read_depth_span_float( struct gl_context *ctx, struct gl_renderbuffer *r } } + /** - * Clear the given z/depth renderbuffer. + * Clear the given z/depth renderbuffer. If the buffer is a combined + * depth+stencil buffer, only the Z bits will be touched. */ void -_swrast_clear_depth_buffer( struct gl_context *ctx, struct gl_renderbuffer *rb ) +_swrast_clear_depth_buffer(struct gl_context *ctx) { + struct gl_renderbuffer *rb = + ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; GLuint clearValue; GLint x, y, width, height; + GLubyte *map; + GLint rowStride, i, j; + GLbitfield mapMode; if (!rb || !ctx->Depth.Mask) { /* no depth buffer, or writing to it is disabled */ @@ -1334,67 +1342,218 @@ _swrast_clear_depth_buffer( struct gl_context *ctx, struct gl_renderbuffer *rb ) clearValue = (GLuint) (ctx->Depth.Clear * ctx->DrawBuffer->_DepthMaxF); } - assert(rb->_BaseFormat == GL_DEPTH_COMPONENT); - /* compute region to clear */ x = ctx->DrawBuffer->_Xmin; y = ctx->DrawBuffer->_Ymin; width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; - if (rb->GetPointer(ctx, rb, 0, 0)) { - /* Direct buffer access is possible. Either this is just malloc'd - * memory, or perhaps the driver mmap'd the zbuffer memory. - */ - if (rb->DataType == GL_UNSIGNED_SHORT) { - if ((clearValue & 0xff) == ((clearValue >> 8) & 0xff) && - ((GLushort *) rb->GetPointer(ctx, rb, 0, 0) + width == - (GLushort *) rb->GetPointer(ctx, rb, 0, 1))) { - /* optimized case */ - GLushort *dst = (GLushort *) rb->GetPointer(ctx, rb, x, y); - GLuint len = width * height * sizeof(GLushort); - memset(dst, (clearValue & 0xff), len); + mapMode = GL_MAP_WRITE_BIT; + if (rb->Format == MESA_FORMAT_S8_Z24 || + rb->Format == MESA_FORMAT_X8_Z24 || + rb->Format == MESA_FORMAT_Z24_S8 || + rb->Format == MESA_FORMAT_Z24_X8) { + mapMode |= GL_MAP_READ_BIT; + } + + ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, + mapMode, &map, &rowStride); + if (!map) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(depth)"); + return; + } + + switch (rb->Format) { + case MESA_FORMAT_Z16: + { + GLfloat clear = (GLfloat) ctx->Depth.Clear; + GLushort clearVal = 0; + _mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal); + if (clearVal == 0xffff && width * 2 == rowStride) { + /* common case */ + memset(map, 0xff, width * height * 2); } else { - /* general case */ - GLint i, j; for (i = 0; i < height; i++) { - GLushort *dst = (GLushort *) rb->GetPointer(ctx, rb, x, y + i); + GLushort *row = (GLushort *) map; for (j = 0; j < width; j++) { - dst[j] = clearValue; + row[j] = clearVal; } + map += rowStride; } } } - else { - GLint i, j; - ASSERT(rb->DataType == GL_UNSIGNED_INT); + break; + case MESA_FORMAT_Z32: + case MESA_FORMAT_Z32_FLOAT: + { + GLfloat clear = (GLfloat) ctx->Depth.Clear; + GLuint clearVal = 0; + _mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal); for (i = 0; i < height; i++) { - GLuint *dst = (GLuint *) rb->GetPointer(ctx, rb, x, y + i); + GLuint *row = (GLuint *) map; for (j = 0; j < width; j++) { - dst[j] = clearValue; + row[j] = clearVal; } + map += rowStride; } } - } - else { - /* Direct access not possible. Use PutRow to write new values. */ - if (rb->DataType == GL_UNSIGNED_SHORT) { - GLushort clearVal16 = (GLushort) (clearValue & 0xffff); - GLint i; + break; + case MESA_FORMAT_S8_Z24: + case MESA_FORMAT_X8_Z24: + case MESA_FORMAT_Z24_S8: + case MESA_FORMAT_Z24_X8: + { + GLfloat clear = (GLfloat) ctx->Depth.Clear; + GLuint clearVal = 0; + GLuint mask; + + if (rb->Format == MESA_FORMAT_S8_Z24 || + rb->Format == MESA_FORMAT_X8_Z24) + mask = 0xff000000; + else + mask = 0xff; + + _mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal); for (i = 0; i < height; i++) { - rb->PutMonoRow(ctx, rb, width, x, y + i, &clearVal16, NULL); + GLuint *row = (GLuint *) map; + for (j = 0; j < width; j++) { + row[j] = (row[j] & mask) | clearVal; + } + map += rowStride; } + } - else if (rb->DataType == GL_UNSIGNED_INT) { - GLint i; - ASSERT(sizeof(clearValue) == sizeof(GLuint)); + break; + case MESA_FORMAT_Z32_FLOAT_X24S8: + /* XXX untested */ + { + GLfloat clearVal = (GLfloat) ctx->Depth.Clear; for (i = 0; i < height; i++) { - rb->PutMonoRow(ctx, rb, width, x, y + i, &clearValue, NULL); + GLfloat *row = (GLfloat *) map; + for (j = 0; j < width; j++) { + row[j * 2] = clearVal; + } + map += rowStride; } } - else { - _mesa_problem(ctx, "bad depth renderbuffer DataType"); + break; + default: + _mesa_problem(ctx, "Unexpected depth buffer format %s" + " in _swrast_clear_depth_buffer()", + _mesa_get_format_name(rb->Format)); + } + + ctx->Driver.UnmapRenderbuffer(ctx, rb); +} + + + + +/** + * Clear both depth and stencil values in a combined depth+stencil buffer. + */ +void +_swrast_clear_depth_stencil_buffer(struct gl_context *ctx) +{ + const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits; + const GLuint writeMask = ctx->Stencil.WriteMask[0]; + const GLuint stencilMax = (1 << stencilBits) - 1; + struct gl_renderbuffer *rb = + ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; + GLint x, y, width, height; + GLbitfield mapMode; + GLubyte *map; + GLint rowStride, i, j; + + /* check that we really have a combined depth+stencil buffer */ + assert(rb == ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer); + + /* compute region to clear */ + x = ctx->DrawBuffer->_Xmin; + y = ctx->DrawBuffer->_Ymin; + width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; + height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; + + mapMode = GL_MAP_WRITE_BIT; + if ((writeMask & stencilMax) != stencilMax) { + /* need to mask stencil values */ + mapMode |= GL_MAP_READ_BIT; + } + + ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, + mapMode, &map, &rowStride); + if (!map) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(depth+stencil)"); + return; + } + + switch (rb->Format) { + case MESA_FORMAT_S8_Z24: + case MESA_FORMAT_Z24_S8: + { + GLfloat zClear = (GLfloat) ctx->Depth.Clear; + GLuint clear = 0, mask; + + _mesa_pack_float_z_row(rb->Format, 1, &zClear, &clear); + + if (rb->Format == MESA_FORMAT_S8_Z24) { + mask = ((~writeMask) & 0xff) << 24; + clear |= (ctx->Stencil.Clear & writeMask & 0xff) << 24; + } + else { + mask = ((~writeMask) & 0xff); + clear |= (ctx->Stencil.Clear & writeMask & 0xff); + } + + for (i = 0; i < height; i++) { + GLuint *row = (GLuint *) map; + if (mask != 0x0) { + for (j = 0; j < width; j++) { + row[j] = (row[j] & mask) | clear; + } + } + else { + for (j = 0; j < width; j++) { + row[j] = clear; + } + } + map += rowStride; + } + } + break; + case MESA_FORMAT_Z32_FLOAT_X24S8: + /* XXX untested */ + { + const GLfloat zClear = (GLfloat) ctx->Depth.Clear; + const GLuint sClear = ctx->Stencil.Clear & writeMask; + const GLuint sMask = (~writeMask) & 0xff; + for (i = 0; i < height; i++) { + GLfloat *zRow = (GLfloat *) map; + GLuint *sRow = (GLuint *) map; + for (j = 0; j < width; j++) { + zRow[j * 2 + 0] = zClear; + } + if (sMask != 0) { + for (j = 0; j < width; j++) { + sRow[j * 2 + 1] = (sRow[j * 2 + 1] & sMask) | sClear; + } + } + else { + for (j = 0; j < width; j++) { + sRow[j * 2 + 1] = sClear; + } + } + map += rowStride; + } } + break; + default: + _mesa_problem(ctx, "Unexpected depth buffer format %s" + " in _swrast_clear_depth_buffer()", + _mesa_get_format_name(rb->Format)); } + + ctx->Driver.UnmapRenderbuffer(ctx, rb); + } |