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:
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user