commit e6a9381f78605072cab52447fce35eaa98c1e75c Author: Brian Date: Mon Feb 26 11:37:37 2007 -0700 Do proper framebuffer refcounting in _mesa_make_current(). 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. diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 9b3759b..1245c10 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -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, G _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, G 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 diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c index 4651974..d061d22 100644 --- a/src/mesa/main/framebuffer.c +++ b/src/mesa/main/framebuffer.c @@ -166,6 +166,8 @@ _mesa_initialize_framebuffer(struct gl_f _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_fr 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 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 { diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index e8f0f45..422d176 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -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.