diff options
Diffstat (limited to 'mesalib/src/mesa/main/depthstencil.c')
-rw-r--r-- | mesalib/src/mesa/main/depthstencil.c | 655 |
1 files changed, 655 insertions, 0 deletions
diff --git a/mesalib/src/mesa/main/depthstencil.c b/mesalib/src/mesa/main/depthstencil.c new file mode 100644 index 000000000..7be2aacaf --- /dev/null +++ b/mesalib/src/mesa/main/depthstencil.c @@ -0,0 +1,655 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "glheader.h" +#include "imports.h" +#include "context.h" +#include "fbobject.h" +#include "mtypes.h" +#include "depthstencil.h" +#include "renderbuffer.h" + + +/** + * Adaptor/wrappers for GL_DEPTH_STENCIL renderbuffers. + * + * The problem with a GL_DEPTH_STENCIL renderbuffer is that sometimes we + * want to treat it as a stencil buffer, other times we want to treat it + * as a depth/z buffer and still other times when we want to treat it as + * a combined Z+stencil buffer! That implies we need three different sets + * of Get/Put functions. + * + * We solve this by wrapping the Z24_S8 renderbuffer with depth and stencil + * adaptors, each with the right kind of depth/stencil Get/Put functions. + */ + + +static void * +nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y) +{ + (void) ctx; + (void) rb; + (void) x; + (void) y; + return NULL; +} + + +/** + * Delete a depth or stencil wrapper renderbuffer. + */ +static void +delete_wrapper(struct gl_renderbuffer *rb) +{ + ASSERT(rb->_ActualFormat == GL_DEPTH_COMPONENT24 || + rb->_ActualFormat == GL_STENCIL_INDEX8_EXT); + _mesa_reference_renderbuffer(&rb->Wrapped, NULL); + _mesa_free(rb); +} + + +/** + * Realloc storage for wrapper. + */ +static GLboolean +alloc_wrapper_storage(GLcontext *ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, GLuint width, GLuint height) +{ + /* just pass this on to the wrapped renderbuffer */ + struct gl_renderbuffer *dsrb = rb->Wrapped; + GLboolean retVal; + + (void) internalFormat; + + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + + retVal = dsrb->AllocStorage(ctx, dsrb, dsrb->InternalFormat, width, height); + if (retVal) { + rb->Width = width; + rb->Height = height; + } + return retVal; +} + + + + +/*====================================================================== + * Depth wrapper around depth/stencil renderbuffer + */ + +static void +get_row_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count, + GLint x, GLint y, void *values) +{ + struct gl_renderbuffer *dsrb = z24rb->Wrapped; + GLuint temp[MAX_WIDTH], i; + GLuint *dst = (GLuint *) values; + const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); + ASSERT(z24rb->DataType == GL_UNSIGNED_INT); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + if (!src) { + dsrb->GetRow(ctx, dsrb, count, x, y, temp); + src = temp; + } + for (i = 0; i < count; i++) { + dst[i] = src[i] >> 8; + } +} + +static void +get_values_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count, + const GLint x[], const GLint y[], void *values) +{ + struct gl_renderbuffer *dsrb = z24rb->Wrapped; + GLuint temp[MAX_WIDTH], i; + GLuint *dst = (GLuint *) values; + ASSERT(z24rb->DataType == GL_UNSIGNED_INT); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + ASSERT(count <= MAX_WIDTH); + /* don't bother trying direct access */ + dsrb->GetValues(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + dst[i] = temp[i] >> 8; + } +} + +static void +put_row_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + struct gl_renderbuffer *dsrb = z24rb->Wrapped; + const GLuint *src = (const GLuint *) values; + GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); + ASSERT(z24rb->DataType == GL_UNSIGNED_INT); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + if (dst) { + /* direct access */ + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i] = (src[i] << 8) | (dst[i] & 0xff); + } + } + } + else { + /* get, modify, put */ + GLuint temp[MAX_WIDTH], i; + dsrb->GetRow(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i] = (src[i] << 8) | (temp[i] & 0xff); + } + } + dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask); + } +} + +static void +put_mono_row_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count, + GLint x, GLint y, const void *value, const GLubyte *mask) +{ + struct gl_renderbuffer *dsrb = z24rb->Wrapped; + const GLuint shiftedVal = *((GLuint *) value) << 8; + GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); + ASSERT(z24rb->DataType == GL_UNSIGNED_INT); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + if (dst) { + /* direct access */ + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i] = shiftedVal | (dst[i] & 0xff); + } + } + } + else { + /* get, modify, put */ + GLuint temp[MAX_WIDTH], i; + dsrb->GetRow(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i] = shiftedVal | (temp[i] & 0xff); + } + } + dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask); + } +} + +static void +put_values_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count, + const GLint x[], const GLint y[], + const void *values, const GLubyte *mask) +{ + struct gl_renderbuffer *dsrb = z24rb->Wrapped; + const GLuint *src = (const GLuint *) values; + ASSERT(z24rb->DataType == GL_UNSIGNED_INT); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + if (dsrb->GetPointer(ctx, dsrb, 0, 0)) { + /* direct access */ + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]); + *dst = (src[i] << 8) | (*dst & 0xff); + } + } + } + else { + /* get, modify, put */ + GLuint temp[MAX_WIDTH], i; + dsrb->GetValues(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i] = (src[i] << 8) | (temp[i] & 0xff); + } + } + dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask); + } +} + +static void +put_mono_values_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, + GLuint count, const GLint x[], const GLint y[], + const void *value, const GLubyte *mask) +{ + struct gl_renderbuffer *dsrb = z24rb->Wrapped; + GLuint temp[MAX_WIDTH], i; + const GLuint shiftedVal = *((GLuint *) value) << 8; + /* get, modify, put */ + dsrb->GetValues(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i] = shiftedVal | (temp[i] & 0xff); + } + } + dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask); +} + + +/** + * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like + * a depth renderbuffer. + * \return new depth renderbuffer + */ +struct gl_renderbuffer * +_mesa_new_z24_renderbuffer_wrapper(GLcontext *ctx, + struct gl_renderbuffer *dsrb) +{ + struct gl_renderbuffer *z24rb; + + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + + z24rb = _mesa_new_renderbuffer(ctx, 0); + if (!z24rb) + return NULL; + + z24rb->Wrapped = dsrb; + z24rb->Name = dsrb->Name; + z24rb->RefCount = 1; + z24rb->Width = dsrb->Width; + z24rb->Height = dsrb->Height; + z24rb->InternalFormat = GL_DEPTH_COMPONENT24; + z24rb->_ActualFormat = GL_DEPTH_COMPONENT24; + z24rb->_BaseFormat = GL_DEPTH_COMPONENT; + z24rb->DataType = GL_UNSIGNED_INT; + z24rb->DepthBits = 24; + z24rb->Data = NULL; + z24rb->Delete = delete_wrapper; + z24rb->AllocStorage = alloc_wrapper_storage; + z24rb->GetPointer = nop_get_pointer; + z24rb->GetRow = get_row_z24; + z24rb->GetValues = get_values_z24; + z24rb->PutRow = put_row_z24; + z24rb->PutRowRGB = NULL; + z24rb->PutMonoRow = put_mono_row_z24; + z24rb->PutValues = put_values_z24; + z24rb->PutMonoValues = put_mono_values_z24; + + return z24rb; +} + + +/*====================================================================== + * Stencil wrapper around depth/stencil renderbuffer + */ + +static void +get_row_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count, + GLint x, GLint y, void *values) +{ + struct gl_renderbuffer *dsrb = s8rb->Wrapped; + GLuint temp[MAX_WIDTH], i; + GLubyte *dst = (GLubyte *) values; + const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); + ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + if (!src) { + dsrb->GetRow(ctx, dsrb, count, x, y, temp); + src = temp; + } + for (i = 0; i < count; i++) { + dst[i] = src[i] & 0xff; + } +} + +static void +get_values_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count, + const GLint x[], const GLint y[], void *values) +{ + struct gl_renderbuffer *dsrb = s8rb->Wrapped; + GLuint temp[MAX_WIDTH], i; + GLubyte *dst = (GLubyte *) values; + ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + ASSERT(count <= MAX_WIDTH); + /* don't bother trying direct access */ + dsrb->GetValues(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + dst[i] = temp[i] & 0xff; + } +} + +static void +put_row_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + struct gl_renderbuffer *dsrb = s8rb->Wrapped; + const GLubyte *src = (const GLubyte *) values; + GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); + ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + if (dst) { + /* direct access */ + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i] = (dst[i] & 0xffffff00) | src[i]; + } + } + } + else { + /* get, modify, put */ + GLuint temp[MAX_WIDTH], i; + dsrb->GetRow(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i] = (temp[i] & 0xffffff00) | src[i]; + } + } + dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask); + } +} + +static void +put_mono_row_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count, + GLint x, GLint y, const void *value, const GLubyte *mask) +{ + struct gl_renderbuffer *dsrb = s8rb->Wrapped; + const GLubyte val = *((GLubyte *) value); + GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); + ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + if (dst) { + /* direct access */ + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i] = (dst[i] & 0xffffff00) | val; + } + } + } + else { + /* get, modify, put */ + GLuint temp[MAX_WIDTH], i; + dsrb->GetRow(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i] = (temp[i] & 0xffffff00) | val; + } + } + dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask); + } +} + +static void +put_values_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count, + const GLint x[], const GLint y[], + const void *values, const GLubyte *mask) +{ + struct gl_renderbuffer *dsrb = s8rb->Wrapped; + const GLubyte *src = (const GLubyte *) values; + ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + if (dsrb->GetPointer(ctx, dsrb, 0, 0)) { + /* direct access */ + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]); + *dst = (*dst & 0xffffff00) | src[i]; + } + } + } + else { + /* get, modify, put */ + GLuint temp[MAX_WIDTH], i; + dsrb->GetValues(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i] = (temp[i] & 0xffffff00) | src[i]; + } + } + dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask); + } +} + +static void +put_mono_values_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count, + const GLint x[], const GLint y[], + const void *value, const GLubyte *mask) +{ + struct gl_renderbuffer *dsrb = s8rb->Wrapped; + GLuint temp[MAX_WIDTH], i; + const GLubyte val = *((GLubyte *) value); + /* get, modify, put */ + dsrb->GetValues(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i] = (temp[i] & 0xffffff) | val; + } + } + dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask); +} + + +/** + * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like + * a stencil renderbuffer. + * \return new stencil renderbuffer + */ +struct gl_renderbuffer * +_mesa_new_s8_renderbuffer_wrapper(GLcontext *ctx, struct gl_renderbuffer *dsrb) +{ + struct gl_renderbuffer *s8rb; + + ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + + s8rb = _mesa_new_renderbuffer(ctx, 0); + if (!s8rb) + return NULL; + + s8rb->Wrapped = dsrb; + s8rb->Name = dsrb->Name; + s8rb->RefCount = 1; + s8rb->Width = dsrb->Width; + s8rb->Height = dsrb->Height; + s8rb->InternalFormat = GL_STENCIL_INDEX8_EXT; + s8rb->_ActualFormat = GL_STENCIL_INDEX8_EXT; + s8rb->_BaseFormat = GL_STENCIL_INDEX; + s8rb->DataType = GL_UNSIGNED_BYTE; + s8rb->StencilBits = 8; + s8rb->Data = NULL; + s8rb->Delete = delete_wrapper; + s8rb->AllocStorage = alloc_wrapper_storage; + s8rb->GetPointer = nop_get_pointer; + s8rb->GetRow = get_row_s8; + s8rb->GetValues = get_values_s8; + s8rb->PutRow = put_row_s8; + s8rb->PutRowRGB = NULL; + s8rb->PutMonoRow = put_mono_row_s8; + s8rb->PutValues = put_values_s8; + s8rb->PutMonoValues = put_mono_values_s8; + + return s8rb; +} + + + +/** + ** The following functions are useful for hardware drivers that only + ** implement combined depth/stencil buffers. + ** The GL_EXT_framebuffer_object extension allows indepedent depth and + ** stencil buffers to be used in any combination. + ** Therefore, we sometimes have to merge separate depth and stencil + ** renderbuffers into a single depth+stencil renderbuffer. And sometimes + ** we have to split combined depth+stencil renderbuffers into separate + ** renderbuffers. + **/ + + +/** + * Extract stencil values from the combined depth/stencil renderbuffer, storing + * the values into a separate stencil renderbuffer. + * \param dsRb the source depth/stencil renderbuffer + * \param stencilRb the destination stencil renderbuffer + * (either 8-bit or 32-bit) + */ +void +_mesa_extract_stencil(GLcontext *ctx, + struct gl_renderbuffer *dsRb, + struct gl_renderbuffer *stencilRb) +{ + GLuint row, width, height; + + ASSERT(dsRb); + ASSERT(stencilRb); + + ASSERT(dsRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(dsRb->DataType == GL_UNSIGNED_INT_24_8_EXT); + ASSERT(stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT || + stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT); + ASSERT(dsRb->Width == stencilRb->Width); + ASSERT(dsRb->Height == stencilRb->Height); + + width = dsRb->Width; + height = dsRb->Height; + + for (row = 0; row < height; row++) { + GLuint depthStencil[MAX_WIDTH]; + dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil); + if (stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT) { + /* 8bpp stencil */ + GLubyte stencil[MAX_WIDTH]; + GLuint i; + for (i = 0; i < width; i++) { + stencil[i] = depthStencil[i] & 0xff; + } + stencilRb->PutRow(ctx, stencilRb, width, 0, row, stencil, NULL); + } + else { + /* 32bpp stencil */ + /* the 24 depth bits will be ignored */ + ASSERT(stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT); + stencilRb->PutRow(ctx, stencilRb, width, 0, row, depthStencil, NULL); + } + } +} + + +/** + * Copy stencil values from a stencil renderbuffer into a combined + * depth/stencil renderbuffer. + * \param dsRb the destination depth/stencil renderbuffer + * \param stencilRb the source stencil buffer (either 8-bit or 32-bit) + */ +void +_mesa_insert_stencil(GLcontext *ctx, + struct gl_renderbuffer *dsRb, + struct gl_renderbuffer *stencilRb) +{ + GLuint row, width, height; + + ASSERT(dsRb); + ASSERT(stencilRb); + + ASSERT(dsRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(dsRb->DataType == GL_UNSIGNED_INT_24_8_EXT); + ASSERT(stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT || + stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT); + + ASSERT(dsRb->Width == stencilRb->Width); + ASSERT(dsRb->Height == stencilRb->Height); + + width = dsRb->Width; + height = dsRb->Height; + + for (row = 0; row < height; row++) { + GLuint depthStencil[MAX_WIDTH]; + + dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil); + + if (stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT) { + /* 8bpp stencil */ + GLubyte stencil[MAX_WIDTH]; + GLuint i; + stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil); + for (i = 0; i < width; i++) { + depthStencil[i] = (depthStencil[i] & 0xffffff00) | stencil[i]; + } + } + else { + /* 32bpp stencil buffer */ + GLuint stencil[MAX_WIDTH], i; + ASSERT(stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT); + stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil); + for (i = 0; i < width; i++) { + depthStencil[i] + = (depthStencil[i] & 0xffffff00) | (stencil[i] & 0xff); + } + } + + dsRb->PutRow(ctx, dsRb, width, 0, row, depthStencil, NULL); + } +} + + +/** + * Convert the stencil buffer from 8bpp to 32bpp depth/stencil. + * \param stencilRb the stencil renderbuffer to promote + */ +void +_mesa_promote_stencil(GLcontext *ctx, struct gl_renderbuffer *stencilRb) +{ + const GLsizei width = stencilRb->Width; + const GLsizei height = stencilRb->Height; + GLubyte *data; + GLint i, j, k; + + ASSERT(stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT); + ASSERT(stencilRb->Data); + + data = (GLubyte *) stencilRb->Data; + stencilRb->Data = NULL; + stencilRb->AllocStorage(ctx, stencilRb, GL_DEPTH24_STENCIL8_EXT, + width, height); + + ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT); + + k = 0; + for (i = 0; i < height; i++) { + GLuint depthStencil[MAX_WIDTH]; + for (j = 0; j < width; j++) { + depthStencil[j] = data[k++]; + } + stencilRb->PutRow(ctx, stencilRb, width, 0, i, depthStencil, NULL); + } + _mesa_free(data); + + stencilRb->_BaseFormat = GL_DEPTH_STENCIL_EXT; +} |