check for framebuffer completeness, code clean-up
[mesa.git] / src / mesa / main / fbobject.c
index beaf4ed942c445ac0c98a1007ac44c4b283dc37c..4c9967e7d2ce14ee88533f9666a6127d5125d149 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.3
+ * Version:  6.5
  *
  * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
  *
@@ -289,7 +289,14 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,
          }
       }
       else if (format == GL_DEPTH) {
-         if (texImage->TexFormat->BaseFormat != GL_DEPTH_COMPONENT) {
+         if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) {
+            /* OK */
+         }
+         else if (ctx->Extensions.EXT_packed_depth_stencil &&
+                  att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+            /* OK */
+         }
+         else {
             att->Complete = GL_FALSE;
             return;
          }
@@ -313,14 +320,28 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,
          }
       }
       else if (format == GL_DEPTH) {
-         if (att->Renderbuffer->_BaseFormat != GL_DEPTH_COMPONENT) {
+         if (att->Renderbuffer->_BaseFormat == GL_DEPTH_COMPONENT) {
+            /* OK */
+         }
+         else if (ctx->Extensions.EXT_packed_depth_stencil &&
+                  att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+            /* OK */
+         }
+         else {
             att->Complete = GL_FALSE;
             return;
          }
       }
       else {
          assert(format == GL_STENCIL);
-         if (att->Renderbuffer->_BaseFormat != GL_STENCIL_INDEX) {
+         if (att->Renderbuffer->_BaseFormat == GL_STENCIL_INDEX) {
+            /* OK */
+         }
+         else if (ctx->Extensions.EXT_packed_depth_stencil &&
+                  att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+            /* OK */
+         }
+         else {
             att->Complete = GL_FALSE;
             return;
          }
@@ -348,6 +369,8 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
    GLuint w = 0, h = 0;
    GLint i;
 
+   assert(fb->Name != 0);
+
    numImages = 0;
    fb->Width = 0;
    fb->Height = 0;
@@ -387,6 +410,11 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
          h = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->Height;
          f = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->Format;
          numImages++;
+         if (f != GL_RGB && f != GL_RGBA && f != GL_DEPTH_COMPONENT) {
+            /* XXX need GL_DEPTH_STENCIL_EXT test? */
+            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
+            return;
+         }
       }
       else if (att->Type == GL_RENDERBUFFER_EXT) {
          w = att->Renderbuffer->Width;
@@ -443,6 +471,25 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
       }
    }
 
+   /* Check if any renderbuffer is attached more than once.
+    * Note that there's one exception: a GL_DEPTH_STENCIL renderbuffer can be
+    * bound to both the stencil and depth attachment points at the same time.
+    */
+   for (i = 0; i < BUFFER_COUNT - 1; i++) {
+      struct gl_renderbuffer *rb_i = fb->Attachment[i].Renderbuffer;
+      if (rb_i) {
+         GLint j;
+         for (j = i + 1; j < BUFFER_COUNT; j++) {
+            struct gl_renderbuffer *rb_j = fb->Attachment[j].Renderbuffer;
+            if (rb_i == rb_j && rb_i->_BaseFormat != GL_DEPTH_STENCIL_EXT) {
+               fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT;
+               return;
+            }
+         }
+      }
+   }
+
+
    if (numImages == 0) {
       fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
       return;
@@ -585,7 +632,7 @@ _mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers)
  * Given an internal format token for a render buffer, return the
  * corresponding base format.
  * \return one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX, GL_DEPTH_COMPONENT
- *  or zero if error.
+ *  GL_DEPTH_STENCIL_EXT or zero if error.
  */
 static GLenum
 base_internal_format(GLcontext *ctx, GLenum internalFormat)
@@ -620,6 +667,12 @@ base_internal_format(GLcontext *ctx, GLenum internalFormat)
    case GL_DEPTH_COMPONENT24:
    case GL_DEPTH_COMPONENT32:
       return GL_DEPTH_COMPONENT;
+   case GL_DEPTH_STENCIL_EXT:
+   case GL_DEPTH24_STENCIL8_EXT:
+      if (ctx->Extensions.EXT_packed_depth_stencil)
+         return GL_DEPTH_STENCIL_EXT;
+      else
+         return 0;
    /* XXX add floating point formats eventually */
    default:
       return 0;
@@ -722,6 +775,61 @@ _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
    case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
       *params = ctx->CurrentRenderbuffer->InternalFormat;
       return;
+   case GL_RENDERBUFFER_RED_SIZE_EXT:
+      if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB ||
+          ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) {
+         *params = ctx->CurrentRenderbuffer->RedBits;
+      }
+      else {
+         *params = 0;
+      }
+      break;
+   case GL_RENDERBUFFER_GREEN_SIZE_EXT:
+      if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB ||
+          ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) {
+         *params = ctx->CurrentRenderbuffer->GreenBits;
+      }
+      else {
+         *params = 0;
+      }
+      break;
+   case GL_RENDERBUFFER_BLUE_SIZE_EXT:
+      if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB ||
+          ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) {
+         *params = ctx->CurrentRenderbuffer->BlueBits;
+      }
+      else {
+         *params = 0;
+      }
+      break;
+   case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
+      if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB ||
+          ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) {
+         *params = ctx->CurrentRenderbuffer->AlphaBits;
+      }
+      else {
+         *params = 0;
+      }
+      break;
+   case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
+      if (ctx->CurrentRenderbuffer->_BaseFormat == GL_DEPTH_COMPONENT ||
+          ctx->CurrentRenderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+         *params = ctx->CurrentRenderbuffer->DepthBits;
+      }
+      else {
+         *params = 0;
+      }
+      break;
+   case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
+      if (ctx->CurrentRenderbuffer->_BaseFormat == GL_STENCIL_INDEX ||
+          ctx->CurrentRenderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+         *params = ctx->CurrentRenderbuffer->StencilBits;
+      }
+      else {
+         *params = 0;
+      }
+      break;
+
    default:
       _mesa_error(ctx, GL_INVALID_ENUM,
                   "glGetRenderbufferParameterivEXT(target)");
@@ -752,8 +860,7 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
 
    if (target != GL_FRAMEBUFFER_EXT) {
-         _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glBindFramebufferEXT(target)");
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
       return;
    }
 
@@ -1110,6 +1217,7 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
    }
 
    if (ctx->DrawBuffer->Name == 0) {
+      /* Can't attach new renderbuffers to a window system framebuffer */
       _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
       return;
    }
@@ -1234,6 +1342,7 @@ _mesa_GenerateMipmapEXT(GLenum target)
    case GL_TEXTURE_2D:
    case GL_TEXTURE_3D:
    case GL_TEXTURE_CUBE_MAP:
+      /* OK, legal value */
       break;
    default:
       _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target)");