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.
This commit is contained in:
Brian
2007-02-26 11:37:37 -07:00
parent 344c3f7379
commit e6a9381f78
3 changed files with 38 additions and 16 deletions
+14
View 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
+23 -16
View 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++;
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;
}
else {
/*_mesa_warning(ctx, "DrawBuffer names a missing buffer!\n");*/
}
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 {
+1
View 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.