Merge branch 'mesa_7_5_branch'
[mesa.git] / src / mesa / main / framebuffer.c
index b2ec679a5492cef8c2190761a726a88a41b5002f..dc79b8ca61ad763b4de571cdb379172843e1e2b7 100644 (file)
@@ -35,6 +35,7 @@
 #include "buffers.h"
 #include "context.h"
 #include "depthstencil.h"
+#include "macros.h"
 #include "mtypes.h"
 #include "fbobject.h"
 #include "framebuffer.h"
@@ -69,7 +70,7 @@ compute_depth_max(struct gl_framebuffer *fb)
    fb->_DepthMaxF = (GLfloat) fb->_DepthMax;
 
    /* Minimum resolvable depth value, for polygon offset */
-   fb->_MRD = 1.0 / fb->_DepthMaxF;
+   fb->_MRD = (GLfloat)1.0 / fb->_DepthMaxF;
 }
 
 
@@ -115,6 +116,7 @@ _mesa_new_framebuffer(GLcontext *ctx, GLuint name)
       fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT;
       fb->_ColorReadBufferIndex = BUFFER_COLOR0;
       fb->Delete = _mesa_destroy_framebuffer;
+      _glthread_INIT_MUTEX(fb->Mutex);
    }
    return fb;
 }
@@ -222,45 +224,32 @@ _mesa_reference_framebuffer(struct gl_framebuffer **ptr,
       /* no change */
       return;
    }
-   if (*ptr) {
-      _mesa_unreference_framebuffer(ptr);
-   }
-   assert(!*ptr);
-   assert(fb);
-   _glthread_LOCK_MUTEX(fb->Mutex);
-   fb->RefCount++;
-   _glthread_UNLOCK_MUTEX(fb->Mutex);
-   *ptr = fb;
-}
-
 
-/**
- * Undo/remove a reference to a framebuffer object.
- * Decrement the framebuffer object's reference count and delete it when
- * the refcount hits zero.
- * Note: we pass the address of a pointer and set it to NULL.
- */
-void
-_mesa_unreference_framebuffer(struct gl_framebuffer **fb)
-{
-   assert(fb);
-   if (*fb) {
+   if (*ptr) {
+      /* unreference old renderbuffer */
       GLboolean deleteFlag = GL_FALSE;
+      struct gl_framebuffer *oldFb = *ptr;
 
-      _glthread_LOCK_MUTEX((*fb)->Mutex);
-      ASSERT((*fb)->RefCount > 0);
-      (*fb)->RefCount--;
-      deleteFlag = ((*fb)->RefCount == 0);
-      _glthread_UNLOCK_MUTEX((*fb)->Mutex);
+      _glthread_LOCK_MUTEX(oldFb->Mutex);
+      ASSERT(oldFb->RefCount > 0);
+      oldFb->RefCount--;
+      deleteFlag = (oldFb->RefCount == 0);
+      _glthread_UNLOCK_MUTEX(oldFb->Mutex);
       
       if (deleteFlag)
-         (*fb)->Delete(*fb);
+         oldFb->Delete(oldFb);
 
-      *fb = NULL;
+      *ptr = NULL;
    }
-}
-
+   assert(!*ptr);
 
+   if (fb) {
+      _glthread_LOCK_MUTEX(fb->Mutex);
+      fb->RefCount++;
+      _glthread_UNLOCK_MUTEX(fb->Mutex);
+      *ptr = fb;
+   }
+}
 
 
 /**
@@ -418,14 +407,14 @@ _mesa_ResizeBuffersMESA( void )
 /**
  * Examine all the framebuffer's renderbuffers to update the Width/Height
  * fields of the framebuffer.  If we have renderbuffers with different
- * sizes, set the framebuffer's width and height to zero.
+ * sizes, set the framebuffer's width and height to the min size.
  * Note: this is only intended for user-created framebuffers, not
  * window-system framebuffes.
  */
 static void
-update_framebuffer_size(struct gl_framebuffer *fb)
+update_framebuffer_size(GLcontext *ctx, struct gl_framebuffer *fb)
 {
-   GLboolean haveSize = GL_FALSE;
+   GLuint minWidth = ~0, minHeight = ~0;
    GLuint i;
 
    /* user-created framebuffers only */
@@ -435,21 +424,19 @@ update_framebuffer_size(struct gl_framebuffer *fb)
       struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
       const struct gl_renderbuffer *rb = att->Renderbuffer;
       if (rb) {
-         if (haveSize) {
-            if (rb->Width != fb->Width && rb->Height != fb->Height) {
-               /* size mismatch! */
-               fb->Width = 0;
-               fb->Height = 0;
-               return;
-            }
-         }
-         else {
-            fb->Width = rb->Width;
-            fb->Height = rb->Height;
-            haveSize = GL_TRUE;
-         }
+         minWidth = MIN2(minWidth, rb->Width);
+         minHeight = MIN2(minHeight, rb->Height);
       }
    }
+
+   if (minWidth != ~0) {
+      fb->Width = minWidth;
+      fb->Height = minHeight;
+   }
+   else {
+      fb->Width = 0;
+      fb->Height = 0;
+   }
 }
 
 
@@ -469,7 +456,7 @@ _mesa_update_draw_buffer_bounds(GLcontext *ctx)
 
    if (buffer->Name) {
       /* user-created framebuffer size depends on the renderbuffers */
-      update_framebuffer_size(buffer);
+      update_framebuffer_size(ctx, buffer);
    }
 
    buffer->_Xmin = 0;
@@ -544,6 +531,7 @@ _mesa_update_framebuffer_visual(struct gl_framebuffer *fb)
             fb->Visual.rgbBits = fb->Visual.redBits
                + fb->Visual.greenBits + fb->Visual.blueBits;
             fb->Visual.floatMode = GL_FALSE;
+            fb->Visual.samples = rb->NumSamples;
             break;
          }
          else if (rb->_BaseFormat == GL_COLOR_INDEX) {
@@ -793,8 +781,9 @@ update_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
       /* This is a user-created framebuffer.
        * Completeness only matters for user-created framebuffers.
        */
-      _mesa_test_framebuffer_completeness(ctx, fb);
-      _mesa_update_framebuffer_visual(fb);
+      if (fb->_Status != GL_FRAMEBUFFER_COMPLETE) {
+         _mesa_test_framebuffer_completeness(ctx, fb);
+      }
    }
 
    /* Strictly speaking, we don't need to update the draw-state
@@ -828,7 +817,7 @@ _mesa_update_framebuffer(GLcontext *ctx)
 
 /**
  * Check if the renderbuffer for a read operation (glReadPixels, glCopyPixels,
- * glCopyTex[Sub]Image, etc. exists.
+ * glCopyTex[Sub]Image, etc) exists.
  * \param format  a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA,
  *                GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL.
  * \return GL_TRUE if buffer exists, GL_FALSE otherwise
@@ -836,8 +825,12 @@ _mesa_update_framebuffer(GLcontext *ctx)
 GLboolean
 _mesa_source_buffer_exists(GLcontext *ctx, GLenum format)
 {
-   const struct gl_renderbuffer_attachment *att
-      = ctx->ReadBuffer->Attachment;
+   const struct gl_renderbuffer_attachment *att = ctx->ReadBuffer->Attachment;
+
+   /* If we don't know the framebuffer status, update it now */
+   if (ctx->ReadBuffer->_Status == 0) {
+      _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
+   }
 
    if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
       return GL_FALSE;
@@ -861,10 +854,8 @@ _mesa_source_buffer_exists(GLcontext *ctx, GLenum format)
       if (ctx->ReadBuffer->_ColorReadBuffer == NULL) {
          return GL_FALSE;
       }
-      /* XXX enable this post 6.5 release:
       ASSERT(ctx->ReadBuffer->_ColorReadBuffer->RedBits > 0 ||
              ctx->ReadBuffer->_ColorReadBuffer->IndexBits > 0);
-      */
       break;
    case GL_DEPTH:
    case GL_DEPTH_COMPONENT:
@@ -902,13 +893,17 @@ _mesa_source_buffer_exists(GLcontext *ctx, GLenum format)
 
 /**
  * As above, but for drawing operations.
- * XXX code do some code merging w/ above function.
+ * XXX could do some code merging w/ above function.
  */
 GLboolean
 _mesa_dest_buffer_exists(GLcontext *ctx, GLenum format)
 {
-   const struct gl_renderbuffer_attachment *att
-      = ctx->ReadBuffer->Attachment;
+   const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;
+
+   /* If we don't know the framebuffer status, update it now */
+   if (ctx->DrawBuffer->_Status == 0) {
+      _mesa_test_framebuffer_completeness(ctx, ctx->DrawBuffer);
+   }
 
    if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
       return GL_FALSE;
@@ -929,7 +924,7 @@ _mesa_dest_buffer_exists(GLcontext *ctx, GLenum format)
    case GL_BGRA:
    case GL_ABGR_EXT:
    case GL_COLOR_INDEX:
-      /* nothing special */
+      /* Nothing special since GL_DRAW_BUFFER could be GL_NONE. */
       /* Could assert that colorbuffer has RedBits > 0 */
       break;
    case GL_DEPTH:
@@ -956,7 +951,7 @@ _mesa_dest_buffer_exists(GLcontext *ctx, GLenum format)
       break;
    default:
       _mesa_problem(ctx,
-                    "Unexpected format 0x%x in _mesa_source_buffer_exists",
+                    "Unexpected format 0x%x in _mesa_dest_buffer_exists",
                     format);
       return GL_FALSE;
    }