mesa: document sRGBDecode field
[mesa.git] / src / mesa / main / fbobject.c
index 0425fb619c0b9f32aa5de95cfe685a10d9cd2228..f31d8b36db8ffbde680bc3753636b7bbe2cbcac6 100644 (file)
@@ -40,6 +40,8 @@
 #include "framebuffer.h"
 #include "hash.h"
 #include "macros.h"
+#include "mfeatures.h"
+#include "mtypes.h"
 #include "renderbuffer.h"
 #include "state.h"
 #include "teximage.h"
@@ -402,13 +404,16 @@ fbo_incomplete(const char *msg, int index)
 /**
  * Is the given base format a legal format for a color renderbuffer?
  */
-static GLboolean
-is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat)
+GLboolean
+_mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat)
 {
    switch (baseFormat) {
    case GL_RGB:
    case GL_RGBA:
       return GL_TRUE;
+   case GL_LUMINANCE:
+   case GL_LUMINANCE_ALPHA:
+   case GL_INTENSITY:
    case GL_ALPHA:
       return ctx->Extensions.ARB_framebuffer_object;
    case GL_RED:
@@ -485,7 +490,7 @@ test_attachment_completeness(const struct gl_context *ctx, GLenum format,
       baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
 
       if (format == GL_COLOR) {
-         if (!is_legal_color_format(ctx, baseFormat)) {
+         if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
             att_incomplete("bad format");
             att->Complete = GL_FALSE;
             return;
@@ -539,8 +544,7 @@ test_attachment_completeness(const struct gl_context *ctx, GLenum format,
          return;
       }
       if (format == GL_COLOR) {
-         if (baseFormat != GL_RGB &&
-             baseFormat != GL_RGBA) {
+         if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
             att_incomplete("bad renderbuffer color format");
             att->Complete = GL_FALSE;
             return;
@@ -617,6 +621,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
    for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
       struct gl_renderbuffer_attachment *att;
       GLenum f;
+      gl_format mesaFormat;
 
       /*
        * XXX for ARB_fbo, only check color buffers that are named by
@@ -663,8 +668,9 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
          minHeight = MIN2(minHeight, texImg->Height);
          maxHeight = MAX2(maxHeight, texImg->Height);
          f = texImg->_BaseFormat;
+         mesaFormat = texImg->TexFormat;
          numImages++;
-         if (!is_legal_color_format(ctx, f) &&
+         if (!_mesa_is_legal_color_format(ctx, f) &&
              !is_legal_depth_format(ctx, f)) {
             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
             fbo_incomplete("texture attachment incomplete", -1);
@@ -677,6 +683,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
          minHeight = MIN2(minHeight, att->Renderbuffer->Height);
          maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
          f = att->Renderbuffer->InternalFormat;
+         mesaFormat = att->Renderbuffer->Format;
          numImages++;
       }
       else {
@@ -689,6 +696,9 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
          numSamples = att->Renderbuffer->NumSamples;
       }
 
+      /* check if integer color */
+      fb->_IntegerColor = _mesa_is_format_integer_color(mesaFormat);
+
       /* Error-check width, height, format, samples
        */
       if (numImages == 1) {
@@ -784,7 +794,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
       fb->Height = minHeight;
 
       /* finally, update the visual info for the framebuffer */
-      _mesa_update_framebuffer_visual(fb);
+      _mesa_update_framebuffer_visual(ctx, fb);
    }
 }
 
@@ -950,67 +960,42 @@ _mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers)
 
 
 /**
- * Given an internal format token for a render buffer, return the
+ * Given an internal format token for a renderbuffer, return the
  * corresponding base format.
- * This is very similar to _mesa_base_tex_format() but the set of valid
- * internal formats is somewhat different.
- *
- * \return one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX, GL_DEPTH_COMPONENT
- *  GL_DEPTH_STENCIL_EXT or zero if error.
- *
- * XXX in the future when we support red-only and red-green formats
- * we'll also return GL_RED and GL_RG.
  */
 GLenum
 _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat)
 {
+   GLenum baseFormat;
+
    switch (internalFormat) {
-   case GL_ALPHA:
-   case GL_ALPHA4:
-   case GL_ALPHA8:
-   case GL_ALPHA12:
-   case GL_ALPHA16:
-      return GL_ALPHA;
-   case GL_RGB:
-   case GL_R3_G3_B2:
-   case GL_RGB4:
-   case GL_RGB5:
-   case GL_RGB8:
-   case GL_RGB10:
-   case GL_RGB12:
-   case GL_RGB16:
-      return GL_RGB;
-   case GL_RGBA:
-   case GL_RGBA2:
-   case GL_RGBA4:
-   case GL_RGB5_A1:
-   case GL_RGBA8:
-   case GL_RGB10_A2:
-   case GL_RGBA12:
-   case GL_RGBA16:
    case GL_RGBA16_SNORM:
+      /* This is used internally by Mesa for accum buffers. */
       return GL_RGBA;
    case GL_STENCIL_INDEX:
    case GL_STENCIL_INDEX1_EXT:
    case GL_STENCIL_INDEX4_EXT:
    case GL_STENCIL_INDEX8_EXT:
    case GL_STENCIL_INDEX16_EXT:
+      /* This is not a valid texture internalFormat, but valid for
+       * renderbuffers.
+       */
       return GL_STENCIL_INDEX;
    case GL_DEPTH_COMPONENT:
    case GL_DEPTH_COMPONENT16:
    case GL_DEPTH_COMPONENT24:
    case GL_DEPTH_COMPONENT32:
+      /* This is an override of _mesa_base_tex_format's check that
+       * ARB_depth_texture is present.  We allow depth RBs without it.
+       */
       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;
    }
+
+   baseFormat = _mesa_base_tex_format(ctx, internalFormat);
+   if (baseFormat < 0)
+      return 0;
+
+   return baseFormat;
 }
 
 
@@ -1046,6 +1031,14 @@ renderbuffer_storage(GLenum target, GLenum internalFormat,
       return;
    }
 
+   if (baseFormat != GL_DEPTH_COMPONENT &&
+       baseFormat != GL_STENCIL_INDEX &&
+       baseFormat != GL_DEPTH_STENCIL &&
+       !_mesa_is_legal_color_format(ctx, baseFormat)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat)", func);
+      return;
+   }
+
    if (width < 1 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
       _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func);
       return;
@@ -1163,8 +1156,17 @@ get_component_bits(GLenum pname, GLenum baseFormat, gl_format format)
    switch (pname) {
    case GL_RENDERBUFFER_RED_SIZE_EXT:
    case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
+      if (baseFormat == GL_RGB || baseFormat == GL_RGBA ||
+         baseFormat == GL_RG || baseFormat == GL_RED)
+         return _mesa_get_format_bits(format, pname);
+      else
+         return 0;
    case GL_RENDERBUFFER_GREEN_SIZE_EXT:
    case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
+      if (baseFormat == GL_RGB || baseFormat == GL_RGBA || baseFormat == GL_RG)
+         return _mesa_get_format_bits(format, pname);
+      else
+         return 0;
    case GL_RENDERBUFFER_BLUE_SIZE_EXT:
    case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
       if (baseFormat == GL_RGB || baseFormat == GL_RGBA)
@@ -1173,7 +1175,8 @@ get_component_bits(GLenum pname, GLenum baseFormat, gl_format format)
          return 0;
    case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
    case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
-      if (baseFormat == GL_RGBA || baseFormat == GL_ALPHA)
+      if (baseFormat == GL_RGBA || baseFormat == GL_ALPHA ||
+         baseFormat == GL_LUMINANCE_ALPHA)
          return _mesa_get_format_bits(format, pname);
       else
          return 0;
@@ -1904,6 +1907,13 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
                      " renderbuffer %u)", renderbuffer);
         return;
       }
+      else if (rb == &DummyRenderbuffer) {
+         /* This is what NVIDIA does */
+        _mesa_error(ctx, GL_INVALID_VALUE,
+                    "glFramebufferRenderbufferEXT(renderbuffer %u)",
+                     renderbuffer);
+        return;
+      }
    }
    else {
       /* remove renderbuffer attachment */
@@ -1931,7 +1941,7 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
    /* Some subsequent GL commands may depend on the framebuffer's visual
     * after the binding is updated.  Update visual info now.
     */
-   _mesa_update_framebuffer_visual(fb);
+   _mesa_update_framebuffer_visual(ctx, fb);
 }
 
 
@@ -2005,7 +2015,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
 
    switch (pname) {
    case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
-      *params = att->Type;
+      *params = buffer->Name == 0 ? GL_FRAMEBUFFER_DEFAULT : att->Type;
       return;
    case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
       if (att->Type == GL_RENDERBUFFER_EXT) {
@@ -2015,8 +2025,8 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
         *params = att->Texture->Name;
       }
       else {
-        _mesa_error(ctx, GL_INVALID_ENUM,
-                    "glGetFramebufferAttachmentParameterivEXT(pname)");
+         assert(att->Type == GL_NONE);
+         *params = 0;
       }
       return;
    case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
@@ -2137,6 +2147,7 @@ _mesa_GenerateMipmapEXT(GLenum target)
       /* OK, legal value */
       break;
    default:
+      /* XXX need to implement GL_TEXTURE_1D_ARRAY and GL_TEXTURE_2D_ARRAY */
       _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target)");
       return;
    }
@@ -2148,6 +2159,13 @@ _mesa_GenerateMipmapEXT(GLenum target)
       return;
    }
 
+   if (texObj->Target == GL_TEXTURE_CUBE_MAP &&
+       !_mesa_cube_complete(texObj)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glGenerateMipmap(incomplete cube map)");
+      return;
+   }
+
    _mesa_lock_texture(ctx, texObj);
    if (target == GL_TEXTURE_CUBE_MAP) {
       GLuint face;