Support for combined depth/stencil renderbuffers (GL_EXT_packed_depth_stencil).
authorBrian Paul <brian.paul@tungstengraphics.com>
Wed, 16 Nov 2005 04:05:54 +0000 (04:05 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Wed, 16 Nov 2005 04:05:54 +0000 (04:05 +0000)
depthstencil.c provides wrappers for treating depth/stencil buffers either
as regular depth or stencil renderbuffers.

src/mesa/main/dd.h
src/mesa/main/depthstencil.c [new file with mode: 0644]
src/mesa/main/depthstencil.h [new file with mode: 0644]
src/mesa/main/fbobject.c
src/mesa/main/fbobject.h
src/mesa/main/framebuffer.c
src/mesa/main/mtypes.h

index f150cf99e251618c0957dcebafb6da9cb558050d..1e7a93e939aa5591672791f4f8f6adcfdb5f867b 100644 (file)
@@ -802,7 +802,8 @@ struct dd_function_table {
    struct gl_framebuffer * (*NewFramebuffer)(GLcontext *ctx, GLuint name);
    struct gl_renderbuffer * (*NewRenderbuffer)(GLcontext *ctx, GLuint name);
    void (*FramebufferRenderbuffer)(GLcontext *ctx, 
-                                   struct gl_renderbuffer_attachment *att,
+                                   struct gl_framebuffer *fb,
+                                   GLenum attachment,
                                    struct gl_renderbuffer *rb);
    void (*RenderbufferTexture)(GLcontext *ctx,
                                struct gl_renderbuffer_attachment *att,
diff --git a/src/mesa/main/depthstencil.c b/src/mesa/main/depthstencil.c
new file mode 100644 (file)
index 0000000..90e4341
--- /dev/null
@@ -0,0 +1,549 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 1999-2005  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)
+{
+   return NULL;
+}
+
+
+/**
+ * Delete a depth or stencil renderbuffer.
+ */
+static void
+delete_wrapper(struct gl_renderbuffer *rb)
+{
+   struct gl_renderbuffer *dsrb = rb->Wrapped;
+   assert(dsrb);
+   assert(rb->InternalFormat == GL_DEPTH_COMPONENT24 ||
+          rb->InternalFormat == GL_STENCIL_INDEX8_EXT);
+   /* decrement refcount on the wrapped buffer and delete it if necessary */
+   dsrb->RefCount--;
+   if (dsrb->RefCount <= 0) {
+      dsrb->Delete(dsrb);
+   }
+   _mesa_free(rb);
+}
+
+
+/*======================================================================
+ * 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->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->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->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->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 GLubyte *src = (const GLubyte *) values;
+   ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
+   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->_BaseFormat == GL_DEPTH_STENCIL_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_ARB;
+   z24rb->_BaseFormat = GL_DEPTH_COMPONENT;
+   z24rb->DataType = GL_UNSIGNED_INT;
+   z24rb->DepthBits = 24;
+   z24rb->Data = NULL;
+   z24rb->Delete = delete_wrapper;
+   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->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->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->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->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->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->_BaseFormat == GL_DEPTH_STENCIL_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->_BaseFormat = GL_STENCIL_INDEX;
+   s8rb->DataType = GL_UNSIGNED_BYTE;
+   s8rb->StencilBits = 8;
+   s8rb->Data = NULL;
+   s8rb->Delete = delete_wrapper;
+   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;
+}
+
+
+/**
+ * Merge data from a depth renderbuffer and a stencil renderbuffer into a
+ * combined depth/stencil renderbuffer.
+ */
+void
+_mesa_merge_depth_stencil_buffers(GLcontext *ctx,
+                                  struct gl_renderbuffer *dest,
+                                  struct gl_renderbuffer *depth,
+                                  struct gl_renderbuffer *stencil)
+{
+   GLuint depthVals[MAX_WIDTH];
+   GLubyte stencilVals[MAX_WIDTH];
+   GLuint combined[MAX_WIDTH];
+   GLuint row, width;
+
+   ASSERT(dest);
+   ASSERT(depth);
+   ASSERT(stencil);
+
+   ASSERT(dest->InternalFormat == GL_DEPTH24_STENCIL8_EXT);
+   ASSERT(dest->DataType == GL_UNSIGNED_INT_24_8_EXT);
+   ASSERT(depth->InternalFormat == GL_DEPTH_COMPONENT24);
+   ASSERT(depth->DataType == GL_UNSIGNED_INT);
+   ASSERT(stencil->InternalFormat == GL_STENCIL_INDEX8_EXT);
+   ASSERT(stencil->DataType == GL_UNSIGNED_BYTE);
+
+   ASSERT(dest->Width == depth->Width);
+   ASSERT(dest->Height == depth->Height);
+   ASSERT(dest->Width == stencil->Width);
+   ASSERT(dest->Height == stencil->Height);
+
+   width = dest->Width;
+   for (row = 0; row < dest->Height; row++) {
+      GLuint i;
+      depth->GetRow(ctx, depth, width, 0, row, depthVals);
+      stencil->GetRow(ctx, stencil, width, 0, row, stencilVals);
+      for (i = 0; i < width; i++) {
+         combined[i] = (depthVals[i] << 8) | stencilVals[i];
+      }
+      dest->PutRow(ctx, dest, width, 0, row, combined, NULL);
+   }
+}
+
+
+/**
+ * Split combined depth/stencil renderbuffer data into separate depth/stencil
+ * buffers.
+ */
+void
+_mesa_split_depth_stencil_buffer(GLcontext *ctx,
+                                 struct gl_renderbuffer *source,
+                                 struct gl_renderbuffer *depth,
+                                 struct gl_renderbuffer *stencil)
+{
+   GLuint depthVals[MAX_WIDTH];
+   GLubyte stencilVals[MAX_WIDTH];
+   GLuint combined[MAX_WIDTH];
+   GLuint row, width;
+
+   ASSERT(source);
+   ASSERT(depth);
+   ASSERT(stencil);
+
+   ASSERT(source->InternalFormat == GL_DEPTH24_STENCIL8_EXT);
+   ASSERT(source->DataType == GL_UNSIGNED_INT_24_8_EXT);
+   ASSERT(depth->InternalFormat == GL_DEPTH_COMPONENT24);
+   ASSERT(depth->DataType == GL_UNSIGNED_INT);
+   ASSERT(stencil->InternalFormat == GL_STENCIL_INDEX8_EXT);
+   ASSERT(stencil->DataType == GL_UNSIGNED_BYTE);
+
+   ASSERT(source->Width == depth->Width);
+   ASSERT(source->Height == depth->Height);
+   ASSERT(source->Width == stencil->Width);
+   ASSERT(source->Height == stencil->Height);
+
+   width = source->Width;
+   for (row = 0; row < source->Height; row++) {
+      GLuint i;
+      source->GetRow(ctx, source, width, 0, row, combined);
+      for (i = 0; i < width; i++) {
+         depthVals[i] = combined[i] >> 8;
+         stencilVals[i] = combined[i] & 0xff;
+      }
+      depth->PutRow(ctx, depth, width, 0, row, depthVals, NULL);
+      stencil->PutRow(ctx, stencil, width, 0, row, stencilVals, NULL);
+   }
+}
diff --git a/src/mesa/main/depthstencil.h b/src/mesa/main/depthstencil.h
new file mode 100644 (file)
index 0000000..76b75a0
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 1999-2005  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.
+ */
+
+
+#ifndef DEPTHSTENCIL_H
+#define DEPTHSTENCIL_H
+
+
+extern struct gl_renderbuffer *
+_mesa_new_z24_renderbuffer_wrapper(GLcontext *ctx,
+                                   struct gl_renderbuffer *dsrb);
+
+
+extern struct gl_renderbuffer *
+_mesa_new_s8_renderbuffer_wrapper(GLcontext *ctx,
+                                  struct gl_renderbuffer *dsrb);
+
+
+extern void
+_mesa_merge_depth_stencil_buffers(GLcontext *ctx,
+                                  struct gl_renderbuffer *dest,
+                                  struct gl_renderbuffer *depth,
+                                  struct gl_renderbuffer *stencil);
+
+
+extern void
+_mesa_split_depth_stencil_buffer(GLcontext *ctx,
+                                 struct gl_renderbuffer *source,
+                                 struct gl_renderbuffer *depth,
+                                 struct gl_renderbuffer *stencil);
+
+
+
+#endif /* DEPTHSTENCIL_H */
index dc32caae1589fa1e1219efc73ddf15872f4bedea..ecf54a5a797b9309b72e909998fd75fbb673ff5c 100644 (file)
@@ -38,7 +38,6 @@
 #include "texstore.h"
 
 
-
 /* XXX temporarily here */
 #define GL_READ_FRAMEBUFFER_EXT                0x90
 #define GL_DRAW_FRAMEBUFFER_EXT                0x9a
@@ -108,8 +107,9 @@ lookup_framebuffer(GLcontext *ctx, GLuint id)
  * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
  * gl_renderbuffer_attachment object.
  */
-static struct gl_renderbuffer_attachment *
-get_attachment(GLcontext *ctx, struct gl_framebuffer *fb, GLenum attachment)
+struct gl_renderbuffer_attachment *
+_mesa_get_attachment(GLcontext *ctx, struct gl_framebuffer *fb,
+                     GLenum attachment)
 {
    GLuint i;
 
@@ -232,15 +232,17 @@ _mesa_set_renderbuffer_attachment(GLcontext *ctx,
 
 /**
  * Fallback for ctx->Driver.FramebufferRenderbuffer()
- * Sets a framebuffer attachment to a particular renderbuffer.
- * The framebuffer in question is ctx->DrawBuffer.
- * \sa _mesa_renderbuffer_texture
+ * Attach a renderbuffer object to a framebuffer object.
  */
 void
-_mesa_framebuffer_renderbuffer(GLcontext *ctx,
-                               struct gl_renderbuffer_attachment *att,
-                               struct gl_renderbuffer *rb)
+_mesa_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
+                               GLenum attachment, struct gl_renderbuffer *rb)
 {
+   struct gl_renderbuffer_attachment *att;
+
+   att = _mesa_get_attachment(ctx, fb, attachment);
+   ASSERT(att);
+
    if (rb) {
       _mesa_set_renderbuffer_attachment(ctx, att, rb);
    }
@@ -461,7 +463,7 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
    for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
       if (fb->ColorDrawBuffer[i] != GL_NONE) {
          const struct gl_renderbuffer_attachment *att
-            = get_attachment(ctx, fb, fb->ColorDrawBuffer[i]);
+            = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[i]);
          assert(att);
          if (att->Type == GL_NONE) {
             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
@@ -473,7 +475,7 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
    /* Check that the ReadBuffer is present */
    if (fb->ColorReadBuffer != GL_NONE) {
       const struct gl_renderbuffer_attachment *att
-         = get_attachment(ctx, fb, fb->ColorReadBuffer);
+         = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer);
       assert(att);
       if (att->Type == GL_NONE) {
          fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
@@ -1151,7 +1153,7 @@ _mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
    ASSERT(textarget == GL_TEXTURE_1D);
 
    /* XXX read blit */
-   att = get_attachment(ctx, ctx->DrawBuffer, attachment);
+   att = _mesa_get_attachment(ctx, ctx->DrawBuffer, attachment);
    if (att == NULL) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                  "glFramebufferTexture1DEXT(attachment)");
@@ -1200,7 +1202,7 @@ _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
          textarget == GL_TEXTURE_RECTANGLE_ARB ||
          IS_CUBE_FACE(textarget));
 
-   att = get_attachment(ctx, ctx->DrawBuffer, attachment);
+   att = _mesa_get_attachment(ctx, ctx->DrawBuffer, attachment);
    if (att == NULL) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                  "glFramebufferTexture2DEXT(attachment)");
@@ -1252,7 +1254,7 @@ _mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment,
 
    ASSERT(textarget == GL_TEXTURE_3D);
 
-   att = get_attachment(ctx, ctx->DrawBuffer, attachment);
+   att = _mesa_get_attachment(ctx, ctx->DrawBuffer, attachment);
    if (att == NULL) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                  "glFramebufferTexture1DEXT(attachment)");
@@ -1342,7 +1344,7 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
       return;
    }
 
-   att = get_attachment(ctx, fb, attachment);
+   att = _mesa_get_attachment(ctx, fb, attachment);
    if (att == NULL) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                  "glFramebufferRenderbufferEXT(attachment)");
@@ -1365,7 +1367,7 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
 
    assert(ctx->Driver.FramebufferRenderbuffer);
-   ctx->Driver.FramebufferRenderbuffer(ctx, att, rb);
+   ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
 }
 
 
@@ -1413,7 +1415,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
       return;
    }
 
-   att = get_attachment(ctx, buffer, attachment);
+   att = _mesa_get_attachment(ctx, buffer, attachment);
    if (att == NULL) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                   "glGetFramebufferAttachmentParameterivEXT(attachment)");
index 59214ce81d863db2c610519fd4a6c8aead2734b2..71517adfd89fac97500b8fc0f4602003346e248c 100644 (file)
 #define FBOBJECT_H
 
 
+extern struct gl_renderbuffer_attachment *
+_mesa_get_attachment(GLcontext *ctx, struct gl_framebuffer *fb,
+                     GLenum attachment);
+
+
 extern void
 _mesa_remove_attachment(GLcontext *ctx,
                         struct gl_renderbuffer_attachment *att);
@@ -43,9 +48,8 @@ _mesa_set_renderbuffer_attachment(GLcontext *ctx,
                                   struct gl_renderbuffer *rb);
 
 extern void
-_mesa_framebuffer_renderbuffer(GLcontext *ctx,
-                               struct gl_renderbuffer_attachment *att,
-                               struct gl_renderbuffer *rb);
+_mesa_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
+                               GLenum attachment, struct gl_renderbuffer *rb);
 
 extern void
 _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb);
index 956527efbc170eb8132cb54f63c4610d2efad395..4fef9066c837465a6bd312a005b80b375f24a6bd 100644 (file)
@@ -33,6 +33,7 @@
 #include "glheader.h"
 #include "imports.h"
 #include "context.h"
+#include "depthstencil.h"
 #include "mtypes.h"
 #include "fbobject.h"
 #include "framebuffer.h"
@@ -159,7 +160,7 @@ _mesa_destroy_framebuffer(struct gl_framebuffer *fb)
 {
    if (fb) {
       _mesa_free_framebuffer_data(fb);
-      FREE(fb);
+      _mesa_free(fb);
    }
 }
 
@@ -187,6 +188,23 @@ _mesa_free_framebuffer_data(struct gl_framebuffer *fb)
       att->Type = GL_NONE;
       att->Renderbuffer = NULL;
    }
+
+   if (fb->_DepthBuffer) {
+      struct gl_renderbuffer *rb = fb->_DepthBuffer;
+      rb->RefCount--;
+      if (rb->RefCount <= 0) {
+         rb->Delete(rb);
+      }
+      fb->_DepthBuffer = NULL;
+   }
+   if (fb->_StencilBuffer) {
+      struct gl_renderbuffer *rb = fb->_StencilBuffer;
+      rb->RefCount--;
+      if (rb->RefCount <= 0) {
+         rb->Delete(rb);
+      }
+      fb->_StencilBuffer = NULL;
+   }
 }
 
 
@@ -194,7 +212,11 @@ _mesa_free_framebuffer_data(struct gl_framebuffer *fb)
  * Resize the given framebuffer's renderbuffers to the new width and height.
  * This should only be used for window-system framebuffers, not
  * user-created renderbuffers (i.e. made with GL_EXT_framebuffer_object).
- * This will typically be called via ctx->Driver.ResizeBuffers()
+ * This will typically be called via ctx->Driver.ResizeBuffers() or directly
+ * from a device driver.
+ *
+ * \note it's possible for ctx to be null since a window can be resized
+ * without a currently bound rendering context.
  */
 void
 _mesa_resize_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb,
@@ -377,6 +399,45 @@ _mesa_update_framebuffer_visual(struct gl_framebuffer *fb)
 }
 
 
+/**
+ * Helper function for _mesa_update_framebuffer().
+ * Set the actual depth renderbuffer for the given framebuffer.
+ * Take care of reference counts, etc.
+ */
+static void
+set_depth_renderbuffer(struct gl_framebuffer *fb,
+                       struct gl_renderbuffer *rb)
+{
+   if (fb->_DepthBuffer) {
+      fb->_DepthBuffer->RefCount--;
+      if (fb->_DepthBuffer->RefCount <= 0) {
+         fb->_DepthBuffer->Delete(fb->_DepthBuffer);
+      }
+   }
+   fb->_DepthBuffer = rb;
+   if (rb)
+      rb->RefCount++;
+}
+
+/**
+ * \sa set_depth_renderbuffer.
+ */
+static void
+set_stencil_renderbuffer(struct gl_framebuffer *fb,
+                         struct gl_renderbuffer *rb)
+{
+   if (fb->_StencilBuffer) {
+      fb->_StencilBuffer->RefCount--;
+      if (fb->_StencilBuffer->RefCount <= 0) {
+         fb->_StencilBuffer->Delete(fb->_StencilBuffer);
+      }
+   }
+   fb->_StencilBuffer = rb;
+   if (rb)
+      rb->RefCount++;
+}
+
+
 /**
  * Update state related to the current draw/read framebuffers.
  * Specifically, update these framebuffer fields:
@@ -440,5 +501,45 @@ _mesa_update_framebuffer(GLcontext *ctx)
       fb->_ColorReadBuffer
          = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer;
    }
+
+   /*
+    * Deal with GL_DEPTH_STENCIL renderbuffer(s) attached to the depth
+    * and/or stencil attachment points.
+    */
+   {
+      struct gl_renderbuffer *depthRb
+         = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
+      struct gl_renderbuffer *stencilRb
+         = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
+
+      if (depthRb && depthRb->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+         if (!fb->_DepthBuffer || fb->_DepthBuffer->Wrapped != depthRb) {
+            /* need to update wrapper */
+            struct gl_renderbuffer *wrapper
+               = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb);
+            set_depth_renderbuffer(fb, wrapper);
+            assert(fb->_DepthBuffer->Wrapped == depthRb);
+         }
+      }
+      else {
+         /* depthRb may be null */
+         set_depth_renderbuffer(fb, depthRb);
+      }
+
+      if (stencilRb && stencilRb->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+         if (!fb->_StencilBuffer || fb->_StencilBuffer->Wrapped != stencilRb) {
+            /* need to update wrapper */
+            struct gl_renderbuffer *wrapper
+               = _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb);
+            set_stencil_renderbuffer(fb, wrapper);
+            assert(fb->_StencilBuffer->Wrapped == stencilRb);
+         }
+      }
+      else {
+         /* stencilRb may be null */
+         set_stencil_renderbuffer(fb, stencilRb);
+      }
+   }
+
    compute_depth_max(fb);
 }
index 17978e7135a6ab9353f450571c43eb74941fbab6..32ce91c50e16e1ac0a52e4871fb4f31bcc445c35 100644 (file)
@@ -2243,6 +2243,11 @@ struct gl_framebuffer
    struct gl_renderbuffer *_ColorDrawBuffers[MAX_DRAW_BUFFERS][4];
    struct gl_renderbuffer *_ColorReadBuffer;
 
+   /** The Actual depth/stencil buffers to use.  May be wrappers around the
+    * depth/stencil buffers attached above. */
+   struct gl_renderbuffer *_DepthBuffer;
+   struct gl_renderbuffer *_StencilBuffer;
+
    /** Delete this framebuffer */
    void (*Delete)(struct gl_framebuffer *fb);
 };