Merge branch 'xa_branch'
[mesa.git] / src / mesa / main / fbobject.c
index 64f135e21dd498cf9d7bfe51abe326dccef149eb..8cc3fd49a34262a83bfe04994ec7d43757159949 100644 (file)
@@ -78,9 +78,32 @@ static struct gl_renderbuffer DummyRenderbuffer;
 static struct gl_framebuffer IncompleteFramebuffer;
 
 
-#define IS_CUBE_FACE(TARGET) \
-   ((TARGET) >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && \
-    (TARGET) <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
+static INLINE GLboolean
+is_cube_face(GLenum target)
+{
+   return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
+           target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
+}
+
+
+/**
+ * Is the given FBO a user-created FBO?
+ */
+static INLINE GLboolean
+is_user_fbo(const struct gl_framebuffer *fb)
+{
+   return fb->Name != 0;
+}
+
+
+/**
+ * Is the given FBO a window system FBO (like an X window)?
+ */
+static INLINE GLboolean
+is_winsys_fbo(const struct gl_framebuffer *fb)
+{
+   return fb->Name == 0;
+}
 
 
 static void
@@ -196,7 +219,7 @@ _mesa_get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
 {
    GLuint i;
 
-   assert(fb->Name > 0);
+   assert(is_user_fbo(fb));
 
    switch (attachment) {
    case GL_COLOR_ATTACHMENT0_EXT:
@@ -244,7 +267,7 @@ static struct gl_renderbuffer_attachment *
 _mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
                          GLenum attachment)
 {
-   assert(fb->Name == 0);
+   assert(is_winsys_fbo(fb));
 
    switch (attachment) {
    case GL_FRONT_LEFT:
@@ -418,18 +441,16 @@ _mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
          case GL_RG:
             fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
             return;
-         case GL_RGB:
+
+         default:
             switch (rb->Format) {
+            /* XXX This list is likely incomplete. */
             case MESA_FORMAT_RGB9_E5_FLOAT:
                fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
                return;
             default:;
+               /* render buffer format is supported by software rendering */
             }
-            break;
-
-         default:
-            /* render buffer format is supported by software rendering */
-            ;
          }
       }
    }
@@ -671,7 +692,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
    GLint i;
    GLuint j;
 
-   assert(fb->Name != 0);
+   assert(is_user_fbo(fb));
 
    numImages = 0;
    fb->Width = 0;
@@ -797,7 +818,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
    }
 
 #if FEATURE_GL
-   if (ctx->API == API_OPENGL) {
+   if (ctx->API == API_OPENGL && !ctx->Extensions.ARB_ES2_compatibility) {
       /* Check that all DrawBuffers are present */
       for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
         if (fb->ColorDrawBuffer[j] != GL_NONE) {
@@ -970,10 +991,11 @@ _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
                _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
             }
 
-            if (ctx->DrawBuffer->Name) {
+            if (is_user_fbo(ctx->DrawBuffer)) {
                detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
             }
-            if (ctx->ReadBuffer->Name && ctx->ReadBuffer != ctx->DrawBuffer) {
+            if (is_user_fbo(ctx->ReadBuffer)
+                && ctx->ReadBuffer != ctx->DrawBuffer) {
                detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
             }
 
@@ -1205,7 +1227,7 @@ invalidate_rb(GLuint key, void *data, void *userData)
    struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData;
 
    /* If this is a user-created FBO */
-   if (fb->Name) {
+   if (is_user_fbo(fb)) {
       GLuint i;
       for (i = 0; i < BUFFER_COUNT; i++) {
          struct gl_renderbuffer_attachment *att = fb->Attachment + i;
@@ -1534,7 +1556,7 @@ check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
    GLuint i;
    ASSERT(ctx->Driver.RenderTexture);
 
-   if (fb->Name == 0)
+   if (is_winsys_fbo(fb))
       return; /* can't render to texture with winsys framebuffers */
 
    for (i = 0; i < BUFFER_COUNT; i++) {
@@ -1554,7 +1576,7 @@ check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
 static void
 check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
 {
-   if (fb->Name == 0)
+   if (is_winsys_fbo(fb))
       return; /* can't render to texture with winsys framebuffers */
 
    if (ctx->Driver.FinishRenderTexture) {
@@ -1807,7 +1829,7 @@ _mesa_CheckFramebufferStatusEXT(GLenum target)
       return 0;
    }
 
-   if (buffer->Name == 0) {
+   if (is_winsys_fbo(buffer)) {
       /* The window system / default framebuffer is always complete */
       return GL_FRAMEBUFFER_COMPLETE_EXT;
    }
@@ -1845,7 +1867,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
    }
 
    /* check framebuffer binding */
-   if (fb->Name == 0) {
+   if (is_winsys_fbo(fb)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glFramebufferTexture%sEXT", caller);
       return;
@@ -1868,7 +1890,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
          }
          else {
             err = (texObj->Target == GL_TEXTURE_CUBE_MAP)
-                ? !IS_CUBE_FACE(textarget)
+                ? !is_cube_face(textarget)
                 : (texObj->Target != textarget);
          }
       }
@@ -1972,7 +1994,7 @@ _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
    if ((texture != 0) &&
        (textarget != GL_TEXTURE_2D) &&
        (textarget != GL_TEXTURE_RECTANGLE_ARB) &&
-       (!IS_CUBE_FACE(textarget))) {
+       (!is_cube_face(textarget))) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glFramebufferTexture2DEXT(textarget=0x%x)", textarget);
       return;
@@ -2036,7 +2058,7 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
       return;
    }
 
-   if (fb->Name == 0) {
+   if (is_winsys_fbo(fb)) {
       /* Can't attach new renderbuffers to a window system framebuffer */
       _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
       return;
@@ -2113,7 +2135,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
       return;
    }
 
-   if (buffer->Name == 0) {
+   if (is_winsys_fbo(buffer)) {
       /* the default / window-system FBO */
       att = _mesa_get_fb0_attachment(ctx, buffer, attachment);
    }
@@ -2145,7 +2167,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
 
    switch (pname) {
    case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
-      *params = buffer->Name == 0 ? GL_FRAMEBUFFER_DEFAULT : att->Type;
+      *params = is_winsys_fbo(buffer) ? GL_FRAMEBUFFER_DEFAULT : att->Type;
       return;
    case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
       if (att->Type == GL_RENDERBUFFER_EXT) {
@@ -2163,6 +2185,10 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
       if (att->Type == GL_TEXTURE) {
         *params = att->TextureLevel;
       }
+      else if (att->Type == GL_NONE) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glGetFramebufferAttachmentParameterivEXT(pname)");
+      }
       else {
         _mesa_error(ctx, GL_INVALID_ENUM,
                     "glGetFramebufferAttachmentParameterivEXT(pname)");
@@ -2177,6 +2203,10 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
             *params = 0;
          }
       }
+      else if (att->Type == GL_NONE) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glGetFramebufferAttachmentParameterivEXT(pname)");
+      }
       else {
         _mesa_error(ctx, GL_INVALID_ENUM,
                     "glGetFramebufferAttachmentParameterivEXT(pname)");
@@ -2191,6 +2221,10 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
             *params = 0;
          }
       }
+      else if (att->Type == GL_NONE) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glGetFramebufferAttachmentParameterivEXT(pname)");
+      }
       else {
         _mesa_error(ctx, GL_INVALID_ENUM,
                     "glGetFramebufferAttachmentParameterivEXT(pname)");
@@ -2201,6 +2235,10 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
          _mesa_error(ctx, GL_INVALID_ENUM,
                      "glGetFramebufferAttachmentParameterivEXT(pname)");
       }
+      else if (att->Type == GL_NONE) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glGetFramebufferAttachmentParameterivEXT(pname)");
+      }
       else {
          if (ctx->Extensions.EXT_framebuffer_sRGB && ctx->Const.sRGBCapable) {
             *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format);
@@ -2218,6 +2256,10 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
                      "glGetFramebufferAttachmentParameterivEXT(pname)");
          return;
       }
+      else if (att->Type == GL_NONE) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glGetFramebufferAttachmentParameterivEXT(pname)");
+      }
       else {
          gl_format format = att->Renderbuffer->Format;
          if (format == MESA_FORMAT_CI8 || format == MESA_FORMAT_S8) {
@@ -2239,6 +2281,10 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
          _mesa_error(ctx, GL_INVALID_ENUM,
                      "glGetFramebufferAttachmentParameterivEXT(pname)");
       }
+      else if (att->Type == GL_NONE) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glGetFramebufferAttachmentParameterivEXT(pname)");
+      }
       else if (att->Texture) {
          const struct gl_texture_image *texImage =
             _mesa_select_tex_image(ctx, att->Texture, att->Texture->Target,
@@ -2256,7 +2302,8 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
                                       att->Renderbuffer->Format);
       }
       else {
-         *params = 0;
+         _mesa_problem(ctx, "glGetFramebufferAttachmentParameterivEXT:"
+                       " invalid FBO attachment structure");
       }
       return;
    default:
@@ -2406,6 +2453,17 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
    if (mask & GL_COLOR_BUFFER_BIT) {
       colorReadRb = readFb->_ColorReadBuffer;
       colorDrawRb = drawFb->_ColorDrawBuffers[0];
+
+      /* From the EXT_framebuffer_object spec:
+       *
+       *     "If a buffer is specified in <mask> and does not exist in both
+       *     the read and draw framebuffers, the corresponding bit is silently
+       *     ignored."
+       */
+      if ((colorReadRb == NULL) || (colorDrawRb == NULL)) {
+        colorReadRb = colorDrawRb = NULL;
+        mask &= ~GL_COLOR_BUFFER_BIT;
+      }
    }
    else {
       colorReadRb = colorDrawRb = NULL;
@@ -2414,10 +2472,19 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
    if (mask & GL_STENCIL_BUFFER_BIT) {
       struct gl_renderbuffer *readRb = readFb->_StencilBuffer;
       struct gl_renderbuffer *drawRb = drawFb->_StencilBuffer;
-      if (!readRb ||
-          !drawRb ||
-          _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) != 
-          _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
+
+      /* From the EXT_framebuffer_object spec:
+       *
+       *     "If a buffer is specified in <mask> and does not exist in both
+       *     the read and draw framebuffers, the corresponding bit is silently
+       *     ignored."
+       */
+      if ((readRb == NULL) || (drawRb == NULL)) {
+        readRb = drawRb = NULL;
+        mask &= ~GL_STENCIL_BUFFER_BIT;
+      }
+      else if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
+              _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glBlitFramebufferEXT(stencil buffer size mismatch)");
          return;
@@ -2427,10 +2494,19 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
    if (mask & GL_DEPTH_BUFFER_BIT) {
       struct gl_renderbuffer *readRb = readFb->_DepthBuffer;
       struct gl_renderbuffer *drawRb = drawFb->_DepthBuffer;
-      if (!readRb ||
-          !drawRb ||
-          _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) != 
-          _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) {
+
+      /* From the EXT_framebuffer_object spec:
+       *
+       *     "If a buffer is specified in <mask> and does not exist in both
+       *     the read and draw framebuffers, the corresponding bit is silently
+       *     ignored."
+       */
+      if ((readRb == NULL) || (drawRb == NULL)) {
+        readRb = drawRb = NULL;
+        mask &= ~GL_DEPTH_BUFFER_BIT;
+      }
+      else if (_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
+              _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glBlitFramebufferEXT(depth buffer size mismatch)");
          return;