mesa: fix attachment error checking for glGetFramebufferAttachmentParameteriv()
[mesa.git] / src / mesa / main / fbobject.c
index 8d44246618702de05c6eca96c694ffb224bf6806..48b9904642a8ba4177c3e1c9376c407aa23b71b1 100644 (file)
@@ -147,6 +147,8 @@ invalidate_framebuffer(struct gl_framebuffer *fb)
 /**
  * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
  * gl_renderbuffer_attachment object.
+ * This function is only used for user-created FB objects, not the
+ * default / window-system FB object.
  * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to
  * the depth buffer attachment point.
  */
@@ -156,6 +158,8 @@ _mesa_get_attachment(GLcontext *ctx, struct gl_framebuffer *fb,
 {
    GLuint i;
 
+   assert(fb->Name > 0);
+
    switch (attachment) {
    case GL_COLOR_ATTACHMENT0_EXT:
    case GL_COLOR_ATTACHMENT1_EXT:
@@ -194,6 +198,45 @@ _mesa_get_attachment(GLcontext *ctx, struct gl_framebuffer *fb,
 }
 
 
+/**
+ * As above, but only used for getting attachments of the default /
+ * window-system framebuffer (not user-created framebuffer objects).
+ */
+static struct gl_renderbuffer_attachment *
+_mesa_get_fb0_attachment(GLcontext *ctx, struct gl_framebuffer *fb,
+                         GLenum attachment)
+{
+   assert(fb->Name == 0);
+
+   switch (attachment) {
+   case GL_FRONT_LEFT:
+      return &fb->Attachment[BUFFER_FRONT_LEFT];
+   case GL_FRONT_RIGHT:
+      return &fb->Attachment[BUFFER_FRONT_RIGHT];
+   case GL_BACK_LEFT:
+      return &fb->Attachment[BUFFER_BACK_LEFT];
+   case GL_BACK_RIGHT:
+      return &fb->Attachment[BUFFER_BACK_RIGHT];
+   case GL_AUX0:
+      if (fb->Visual.numAuxBuffers == 1) {
+         return &fb->Attachment[BUFFER_AUX0];
+      }
+      return NULL;
+   case GL_DEPTH_BUFFER:
+      /* fall-through / new in GL 3.0 */
+   case GL_DEPTH_ATTACHMENT_EXT:
+      return &fb->Attachment[BUFFER_DEPTH];
+   case GL_STENCIL_BUFFER:
+      /* fall-through / new in GL 3.0 */
+   case GL_STENCIL_ATTACHMENT_EXT:
+      return &fb->Attachment[BUFFER_STENCIL];
+   default:
+      return NULL;
+   }
+}
+
+
+
 /**
  * Remove any texture or renderbuffer attached to the given attachment
  * point.  Update reference counts, etc.
@@ -393,7 +436,9 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,
 
       if (format == GL_COLOR) {
          if (baseFormat != GL_RGB &&
-             baseFormat != GL_RGBA) {
+             baseFormat != GL_RGBA &&
+            (!ctx->Extensions.ARB_framebuffer_object ||
+             baseFormat != GL_ALPHA)) {
             att_incomplete("bad format");
             att->Complete = GL_FALSE;
             return;
@@ -572,7 +617,8 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
          f = texImg->_BaseFormat;
          numImages++;
          if (f != GL_RGB && f != GL_RGBA && f != GL_DEPTH_COMPONENT
-             && f != GL_DEPTH_STENCIL_EXT) {
+             && f != GL_DEPTH_STENCIL_EXT
+            && (!ctx->Extensions.ARB_framebuffer_object || f != GL_ALPHA)) {
             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
             fbo_incomplete("texture attachment incomplete", -1);
             return;
@@ -629,30 +675,32 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
       }
    }
 
-#if !FEATURE_OES_framebuffer_object
-   /* Check that all DrawBuffers are present */
-   for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
-      if (fb->ColorDrawBuffer[j] != GL_NONE) {
-         const struct gl_renderbuffer_attachment *att
-            = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
-         assert(att);
-         if (att->Type == GL_NONE) {
-            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
-            fbo_incomplete("missing drawbuffer", j);
-            return;
-         }
+#if FEATURE_GL
+   if (ctx->API == API_OPENGL) {
+      /* Check that all DrawBuffers are present */
+      for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
+        if (fb->ColorDrawBuffer[j] != GL_NONE) {
+           const struct gl_renderbuffer_attachment *att
+              = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
+           assert(att);
+           if (att->Type == GL_NONE) {
+              fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
+              fbo_incomplete("missing drawbuffer", j);
+              return;
+           }
+        }
       }
-   }
 
-   /* Check that the ReadBuffer is present */
-   if (fb->ColorReadBuffer != GL_NONE) {
-      const struct gl_renderbuffer_attachment *att
-         = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer);
-      assert(att);
-      if (att->Type == GL_NONE) {
-         fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
+      /* Check that the ReadBuffer is present */
+      if (fb->ColorReadBuffer != GL_NONE) {
+        const struct gl_renderbuffer_attachment *att
+           = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer);
+        assert(att);
+        if (att->Type == GL_NONE) {
+           fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
             fbo_incomplete("missing readbuffer", -1);
-         return;
+           return;
+        }
       }
    }
 #else
@@ -887,6 +935,7 @@ _mesa_base_fbo_format(GLcontext *ctx, GLenum internalFormat)
    case GL_RGB10_A2:
    case GL_RGBA12:
    case GL_RGBA16:
+   case GL_RGBA16_SNORM:
       return GL_RGBA;
    case GL_STENCIL_INDEX:
    case GL_STENCIL_INDEX1_EXT:
@@ -1012,9 +1061,10 @@ renderbuffer_storage(GLenum target, GLenum internalFormat,
     */
 }
 
+
 #if FEATURE_OES_EGL_image
 void GLAPIENTRY
-_mesa_EGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image)
+_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
 {
    struct gl_renderbuffer *rb;
    GET_CURRENT_CONTEXT(ctx);
@@ -1027,13 +1077,15 @@ _mesa_EGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image)
    }
 
    if (target != GL_RENDERBUFFER) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "EGLImageTargetRenderbufferStorageOES");
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "EGLImageTargetRenderbufferStorageOES");
       return;
    }
 
    rb = ctx->CurrentRenderbuffer;
    if (!rb) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "EGLImageTargetRenderbufferStorageOES");
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "EGLImageTargetRenderbufferStorageOES");
       return;
    }
 
@@ -1043,6 +1095,7 @@ _mesa_EGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image)
 }
 #endif
 
+
 /**
  * Helper function for _mesa_GetRenderbufferParameterivEXT() and
  * _mesa_GetFramebufferAttachmentParameterivEXT()
@@ -1111,6 +1164,26 @@ _mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
 }
 
 
+/**
+ * OpenGL ES version of glRenderBufferStorage.
+ */
+void GLAPIENTRY
+_es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
+                          GLsizei width, GLsizei height)
+{
+   switch (internalFormat) {
+   case GL_RGB565:
+      /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */
+      /* choose a closest format */
+      internalFormat = GL_RGB5;
+      break;
+   default:
+      break;
+   }
+
+   renderbuffer_storage(target, internalFormat, width, height, 0);
+}
+
 
 void GLAPIENTRY
 _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
@@ -1784,10 +1857,10 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
       rb = NULL;
    }
 
-   if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+   if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
+       rb && rb->Format != MESA_FORMAT_NONE) {
       /* make sure the renderbuffer is a depth/stencil format */
-      const GLenum baseFormat =
-         _mesa_get_format_base_format(att->Renderbuffer->Format);
+      const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
       if (baseFormat != GL_DEPTH_STENCIL) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glFramebufferRenderbufferEXT(renderbuffer"
@@ -1848,12 +1921,14 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
    }
 
    if (buffer->Name == 0) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glGetFramebufferAttachmentParameterivEXT");
-      return;
+      /* the default / window-system FBO */
+      att = _mesa_get_fb0_attachment(ctx, buffer, attachment);
+   }
+   else {
+      /* user-created framebuffer FBO */
+      att = _mesa_get_attachment(ctx, buffer, attachment);
    }
 
-   att = _mesa_get_attachment(ctx, buffer, attachment);
    if (att == NULL) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                   "glGetFramebufferAttachmentParameterivEXT(attachment)");