summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChad Versace <[email protected]>2011-11-10 10:19:20 -0800
committerChad Versace <[email protected]>2011-11-11 12:28:22 -0800
commitbf8ad170c5af58fe9f49b3ce0f92c4eda9e5d845 (patch)
treefa302a4714b846fd817c3a2e8d35885b3cb3aa4d
parent8727807f7e218bd161d92e34f6896f4451d14de0 (diff)
mesa: Fix glFramebufferTexture*() for depth and stencil attachments
This patch solves three bugs. 1. When a texture was attached to the GL_DEPTH_STENCIL_ATTACHMENT point, Mesa attached the texture only to the depth attachment point gl_framebuffer::Attachment[BUFFER_DEPTH] and failed to attach it to the stencil attachment point gl_framebuffer::Attachment[BUFFER_STENCIL] 2. When a texture was attached to the GL_DEPTH_ATTACHMENT point and then later attached to the GL_STENCIL_ATTACHMENT point, Mesa created two separate renderbuffer wrappers. This caused a GL error in glGetFramebufferAttachmentParameteriv(). 3. Same as 2, but with depth and stencil juxtaposed. Fixes Piglit test ARB_framebuffer_object/same-attachment-glFramebufferTexture2D-GL_DEPTH_STENCIL Note: This is a candidate for the stable branches. Reviewed-by: Eric Anholt <[email protected]> Signed-off-by: Chad Versace <[email protected]>
-rw-r--r--src/mesa/main/fbobject.c58
1 files changed, 55 insertions, 3 deletions
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index bcebf124001..f8b148cee8b 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -1939,7 +1939,29 @@ _mesa_CheckFramebufferStatusEXT(GLenum target)
return buffer->_Status;
}
-
+/**
+ * Replicate the src attachment point. Used by framebuffer_texture() when
+ * the same texture is attached at GL_DEPTH_ATTACHMENT and
+ * GL_STENCIL_ATTACHMENT.
+ */
+static void
+reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
+ gl_buffer_index dst,
+ gl_buffer_index src)
+{
+ struct gl_renderbuffer_attachment *dst_att = &fb->Attachment[dst];
+ struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src];
+
+ assert(src_att->Texture != NULL);
+ assert (src_att->Renderbuffer != NULL);
+
+ _mesa_reference_texobj(&dst_att->Texture, src_att->Texture);
+ _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer);
+ dst_att->Type = src_att->Type;
+ dst_att->Complete = src_att->Complete;
+ dst_att->TextureLevel = src_att->TextureLevel;
+ dst_att->Zoffset = src_att->Zoffset;
+}
/**
* Common code called by glFramebufferTexture1D/2D/3DEXT().
@@ -2041,8 +2063,34 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
_glthread_LOCK_MUTEX(fb->Mutex);
if (texObj) {
- _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget,
- level, zoffset);
+ if (attachment == GL_DEPTH_ATTACHMENT &&
+ texObj == fb->Attachment[BUFFER_STENCIL].Texture) {
+ /* The texture object is already attached to the stencil attachment
+ * point. Don't create a new renderbuffer; just reuse the stencil
+ * attachment's. This is required to prevent a GL error in
+ * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
+ */
+ reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
+ BUFFER_STENCIL);
+ } else if (attachment == GL_STENCIL_ATTACHMENT &&
+ texObj== fb->Attachment[BUFFER_DEPTH].Texture) {
+ /* As above, but with depth and stencil juxtasposed. */
+ reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
+ BUFFER_DEPTH);
+ } else {
+ _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget,
+ level, zoffset);
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+ /* Above we created a new renderbuffer and attached it to the
+ * depth attachment point. Now attach it to the stencil attachment
+ * point too.
+ */
+ assert(att == &fb->Attachment[BUFFER_DEPTH]);
+ reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
+ BUFFER_DEPTH);
+ }
+ }
+
/* Set the render-to-texture flag. We'll check this flag in
* glTexImage() and friends to determine if we need to revalidate
* any FBOs that might be rendering into this texture.
@@ -2055,6 +2103,10 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
}
else {
_mesa_remove_attachment(ctx, att);
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+ assert(att == &fb->Attachment[BUFFER_DEPTH]);
+ _mesa_remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
+ }
}
invalidate_framebuffer(fb);