Do proper framebuffer refcounting in _mesa_make_current().
authorBrian <brian@yutani.localnet.net>
Mon, 26 Feb 2007 18:37:37 +0000 (11:37 -0700)
committerBrian <brian@yutani.localnet.net>
Mon, 26 Feb 2007 18:37:37 +0000 (11:37 -0700)
Also, added DeletePending field to gl_framebuffer used when a window has been
deleted, but there still may be rendering contexts attached to the
gl_framebuffer object.

src/mesa/main/context.c
src/mesa/main/framebuffer.c
src/mesa/main/mtypes.h

index 9b3759b6c821cc8b973d845e1d091dfc0b3ab4e9..1245c10cc2c32f67d1424a539fce891a72e4e053 100644 (file)
@@ -95,6 +95,7 @@
 #include "fbobject.h"
 #include "feedback.h"
 #include "fog.h"
+#include "framebuffer.h"
 #include "get.h"
 #include "glthread.h"
 #include "glapioffsets.h"
@@ -1666,6 +1667,8 @@ void
 _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
                     GLframebuffer *readBuffer )
 {
+   GET_CURRENT_CONTEXT(oldCtx);
+
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(newCtx, "_mesa_make_current()\n");
 
@@ -1690,6 +1693,15 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
    _glapi_set_context((void *) newCtx);
    ASSERT(_mesa_get_current_context() == newCtx);
 
+   if (oldCtx) {
+      if (oldCtx->WinSysDrawBuffer) {
+         _mesa_dereference_framebuffer(&oldCtx->WinSysDrawBuffer);
+      }
+      if (oldCtx->WinSysReadBuffer) {
+         _mesa_dereference_framebuffer(&oldCtx->WinSysReadBuffer);
+      }
+   }
+         
    if (!newCtx) {
       _glapi_set_dispatch(NULL);  /* none current */
    }
@@ -1703,6 +1715,8 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
          ASSERT(readBuffer->Name == 0);
          newCtx->WinSysDrawBuffer = drawBuffer;
          newCtx->WinSysReadBuffer = readBuffer;
+         drawBuffer->RefCount++;
+         readBuffer->RefCount++;
 
          /*
           * Only set the context's Draw/ReadBuffer fields if they're NULL
index 465197401b7b8ab0b99f852890a07505863916b7..d061d22d9b82e0679d88cb432ebfefaa68ba51a4 100644 (file)
@@ -166,6 +166,8 @@ _mesa_initialize_framebuffer(struct gl_framebuffer *fb, const GLvisual *visual)
 
    _glthread_INIT_MUTEX(fb->Mutex);
 
+   fb->RefCount = 1;
+
    /* save the visual */
    fb->Visual = *visual;
 
@@ -198,7 +200,6 @@ void
 _mesa_destroy_framebuffer(struct gl_framebuffer *fb)
 {
    if (fb) {
-      _glthread_DESTROY_MUTEX(fb->Mutex);
       _mesa_free_framebuffer_data(fb);
       _mesa_free(fb);
    }
@@ -216,6 +217,8 @@ _mesa_free_framebuffer_data(struct gl_framebuffer *fb)
 
    assert(fb);
 
+   _glthread_DESTROY_MUTEX(fb->Mutex);
+
    for (i = 0; i < BUFFER_COUNT; i++) {
       struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
       if (att->Renderbuffer) {
@@ -605,21 +608,25 @@ update_color_draw_buffers(GLcontext *ctx, struct gl_framebuffer *fb)
       GLbitfield bufferMask = fb->_ColorDrawBufferMask[output];
       GLuint count = 0;
       GLuint i;
-      /* We need the inner loop here because glDrawBuffer(GL_FRONT_AND_BACK)
-       * can specify writing to two or four color buffers (for example).
-       */
-      for (i = 0; bufferMask && i < BUFFER_COUNT; i++) {
-         const GLuint bufferBit = 1 << i;
-         if (bufferBit & bufferMask) {
-            struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
-            if (rb) {
-               fb->_ColorDrawBuffers[output][count] = rb;
-               count++;
-            }
-            else {
-               /*_mesa_warning(ctx, "DrawBuffer names a missing buffer!\n");*/
+      if (!fb->DeletePending) {
+         /* We need the inner loop here because glDrawBuffer(GL_FRONT_AND_BACK)
+          * can specify writing to two or four color buffers (for example).
+          */
+         for (i = 0; bufferMask && i < BUFFER_COUNT; i++) {
+            const GLuint bufferBit = 1 << i;
+            if (bufferBit & bufferMask) {
+               struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
+               if (rb) {
+                  fb->_ColorDrawBuffers[output][count] = rb;
+                  count++;
+               }
+               else {
+                  /*
+                  _mesa_warning(ctx, "DrawBuffer names a missing buffer!\n");
+                  */
+               }
+               bufferMask &= ~bufferBit;
             }
-            bufferMask &= ~bufferBit;
          }
       }
       fb->_NumColorDrawBuffers[output] = count;
@@ -635,7 +642,7 @@ static void
 update_color_read_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
 {
    (void) ctx;
-   if (fb->_ColorReadBufferIndex == -1) {
+   if (fb->_ColorReadBufferIndex == -1 || fb->DeletePending) {
       fb->_ColorReadBuffer = NULL; /* legal! */
    }
    else {
index e8f0f45d3990eb094872f6e75da432c3caf71796..422d176c25abc56dcd9969fb5ed943f0575a8c94 100644 (file)
@@ -2243,6 +2243,7 @@ struct gl_framebuffer
    _glthread_Mutex Mutex;                 /**< for thread safety */
    GLuint Name;      /* if zero, this is a window system framebuffer */
    GLint RefCount;
+   GLboolean DeletePending;
 
    GLvisual Visual;    /**< The framebuffer's visual.
                              Immutable if this is a window system buffer.