Fix some renderbuffer reference counting issues. Also fixes a mem leak.

This commit is contained in:
Brian
2007-03-25 10:39:36 -06:00
parent 6fda763989
commit 42aaa548a1
6 changed files with 56 additions and 93 deletions

View File

@@ -422,18 +422,6 @@ xmesa_delete_framebuffer(struct gl_framebuffer *fb)
XMesaDestroyImage( b->rowimage ); XMesaDestroyImage( b->rowimage );
} }
/* Note that XMesaBuffer renderbuffers normally have a refcount of 2
* (creation + binding) so we need to explicitly delete/unbind them here.
*/
if (b->frontxrb) {
_mesa_unreference_renderbuffer((struct gl_renderbuffer **) &b->frontxrb);
ASSERT(b->frontxrb == NULL);
}
if (b->backxrb) {
_mesa_unreference_renderbuffer((struct gl_renderbuffer **) &b->backxrb);
ASSERT(b->backxrb == NULL);
}
_mesa_free_framebuffer_data(fb); _mesa_free_framebuffer_data(fb);
_mesa_free(fb); _mesa_free(fb);
} }

View File

@@ -559,7 +559,7 @@ _mesa_IsRenderbufferEXT(GLuint renderbuffer)
void GLAPIENTRY void GLAPIENTRY
_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
{ {
struct gl_renderbuffer *newRb, *oldRb; struct gl_renderbuffer *newRb;
GET_CURRENT_CONTEXT(ctx); GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -593,21 +593,16 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
} }
ASSERT(newRb->AllocStorage); ASSERT(newRb->AllocStorage);
_mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb); _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
newRb->RefCount = 1; /* referenced by hash table */
} }
newRb->RefCount++;
} }
else { else {
newRb = NULL; newRb = NULL;
} }
oldRb = ctx->CurrentRenderbuffer;
if (oldRb) {
_mesa_unreference_renderbuffer(&oldRb);
}
ASSERT(newRb != &DummyRenderbuffer); ASSERT(newRb != &DummyRenderbuffer);
ctx->CurrentRenderbuffer = newRb; _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
} }
@@ -632,14 +627,15 @@ _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
_mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
} }
/* remove from hash table immediately, to free the ID */ /* Remove from hash table immediately, to free the ID.
* But the object will not be freed until it's no longer
* referenced anywhere else.
*/
_mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]); _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
if (rb != &DummyRenderbuffer) { if (rb != &DummyRenderbuffer) {
/* But the object will not be freed until it's no longer /* no longer referenced by hash table */
* bound in any context. _mesa_reference_renderbuffer(&rb, NULL);
*/
_mesa_unreference_renderbuffer(&rb);
} }
} }
} }

View File

@@ -69,42 +69,6 @@ compute_depth_max(struct gl_framebuffer *fb)
} }
/**
* Set the framebuffer's _DepthBuffer field, taking care of
* reference counts, etc.
*/
static void
set_depth_renderbuffer(struct gl_framebuffer *fb,
struct gl_renderbuffer *rb)
{
if (fb->_DepthBuffer) {
_mesa_unreference_renderbuffer(&fb->_DepthBuffer);
}
fb->_DepthBuffer = rb;
if (rb) {
rb->RefCount++;
}
}
/**
* Set the framebuffer's _StencilBuffer field, taking care of
* reference counts, etc.
*/
static void
set_stencil_renderbuffer(struct gl_framebuffer *fb,
struct gl_renderbuffer *rb)
{
if (fb->_StencilBuffer) {
_mesa_unreference_renderbuffer(&fb->_StencilBuffer);
}
fb->_StencilBuffer = rb;
if (rb) {
rb->RefCount++;
}
}
/** /**
* Create and initialize a gl_framebuffer object. * Create and initialize a gl_framebuffer object.
* This is intended for creating _window_system_ framebuffers, not generic * This is intended for creating _window_system_ framebuffers, not generic
@@ -223,7 +187,7 @@ _mesa_free_framebuffer_data(struct gl_framebuffer *fb)
for (i = 0; i < BUFFER_COUNT; i++) { for (i = 0; i < BUFFER_COUNT; i++) {
struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
if (att->Renderbuffer) { if (att->Renderbuffer) {
_mesa_unreference_renderbuffer(&att->Renderbuffer); _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
} }
if (att->Texture) { if (att->Texture) {
/* render to texture */ /* render to texture */
@@ -239,9 +203,9 @@ _mesa_free_framebuffer_data(struct gl_framebuffer *fb)
att->Texture = NULL; att->Texture = NULL;
} }
/* unbind depth/stencil to decr ref counts */ /* unbind _Depth/_StencilBuffer to decr ref counts */
set_depth_renderbuffer(fb, NULL); _mesa_reference_renderbuffer(&fb->_DepthBuffer, NULL);
set_stencil_renderbuffer(fb, NULL); _mesa_reference_renderbuffer(&fb->_StencilBuffer, NULL);
} }
@@ -569,13 +533,13 @@ _mesa_update_depth_buffer(GLcontext *ctx,
/* need to update wrapper */ /* need to update wrapper */
struct gl_renderbuffer *wrapper struct gl_renderbuffer *wrapper
= _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb); = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb);
set_depth_renderbuffer(fb, wrapper); _mesa_reference_renderbuffer(&fb->_DepthBuffer, wrapper);
ASSERT(fb->_DepthBuffer->Wrapped == depthRb); ASSERT(fb->_DepthBuffer->Wrapped == depthRb);
} }
} }
else { else {
/* depthRb may be null */ /* depthRb may be null */
set_depth_renderbuffer(fb, depthRb); _mesa_reference_renderbuffer(&fb->_DepthBuffer, depthRb);
} }
} }
@@ -610,13 +574,13 @@ _mesa_update_stencil_buffer(GLcontext *ctx,
/* need to update wrapper */ /* need to update wrapper */
struct gl_renderbuffer *wrapper struct gl_renderbuffer *wrapper
= _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb); = _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb);
set_stencil_renderbuffer(fb, wrapper); _mesa_reference_renderbuffer(&fb->_StencilBuffer, wrapper);
ASSERT(fb->_StencilBuffer->Wrapped == stencilRb); ASSERT(fb->_StencilBuffer->Wrapped == stencilRb);
} }
} }
else { else {
/* stencilRb may be null */ /* stencilRb may be null */
set_stencil_renderbuffer(fb, stencilRb); _mesa_reference_renderbuffer(&fb->_StencilBuffer, stencilRb);
} }
} }

View File

@@ -45,7 +45,7 @@ Delete_wrapper(struct gl_renderbuffer *rb)
/* Decrement reference count on the buffer we're wrapping and delete /* Decrement reference count on the buffer we're wrapping and delete
* it if refcount hits zero. * it if refcount hits zero.
*/ */
_mesa_unreference_renderbuffer(&rb->Wrapped); _mesa_reference_renderbuffer(&rb->Wrapped, NULL);
/* delete myself */ /* delete myself */
_mesa_delete_renderbuffer(rb); _mesa_delete_renderbuffer(rb);

View File

@@ -1473,7 +1473,7 @@ _mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
rb->ClassID = 0; rb->ClassID = 0;
rb->Name = name; rb->Name = name;
rb->RefCount = 1; rb->RefCount = 0;
rb->Delete = _mesa_delete_renderbuffer; rb->Delete = _mesa_delete_renderbuffer;
/* The rest of these should be set later by the caller of this function or /* The rest of these should be set later by the caller of this function or
@@ -2105,9 +2105,7 @@ _mesa_add_renderbuffer(struct gl_framebuffer *fb,
fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT; fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
fb->Attachment[bufferName].Complete = GL_TRUE; fb->Attachment[bufferName].Complete = GL_TRUE;
fb->Attachment[bufferName].Renderbuffer = rb; _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
rb->RefCount++;
} }
@@ -2125,40 +2123,57 @@ _mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName)
if (!rb) if (!rb)
return; return;
_mesa_unreference_renderbuffer(&rb); _mesa_reference_renderbuffer(&rb, NULL);
fb->Attachment[bufferName].Renderbuffer = NULL; fb->Attachment[bufferName].Renderbuffer = NULL;
} }
/** /**
* Decrement a renderbuffer object's reference count and delete it when * Set *ptr to point to rb. If *ptr points to another renderbuffer,
* the refcount hits zero. * dereference that buffer first. The new renderbuffer's refcount will
* Note: we pass the address of a pointer. * be incremented. The old renderbuffer's refcount will be decremented.
*/ */
void void
_mesa_unreference_renderbuffer(struct gl_renderbuffer **rb) _mesa_reference_renderbuffer(struct gl_renderbuffer **ptr,
struct gl_renderbuffer *rb)
{ {
assert(rb); assert(ptr);
if (*rb) { if (*ptr == rb) {
GLboolean deleteFlag = GL_FALSE; /* no change */
return;
}
_glthread_LOCK_MUTEX((*rb)->Mutex); if (*ptr) {
ASSERT((*rb)->RefCount > 0); /* Unreference the old renderbuffer */
(*rb)->RefCount--; GLboolean deleteFlag = GL_FALSE;
deleteFlag = ((*rb)->RefCount == 0); struct gl_renderbuffer *oldRb = *ptr;
_glthread_UNLOCK_MUTEX((*rb)->Mutex);
_glthread_LOCK_MUTEX(oldRb->Mutex);
ASSERT(oldRb->RefCount > 0);
oldRb->RefCount--;
/*printf("RB DECR %p to %d\n", (void*) oldRb, oldRb->RefCount);*/
deleteFlag = (oldRb->RefCount == 0);
_glthread_UNLOCK_MUTEX(oldRb->Mutex);
if (deleteFlag) if (deleteFlag)
(*rb)->Delete(*rb); oldRb->Delete(oldRb);
*rb = NULL; *ptr = NULL;
}
assert(!*ptr);
if (rb) {
/* reference new renderbuffer */
_glthread_LOCK_MUTEX(rb->Mutex);
rb->RefCount++;
/*printf("RB REF %p to %d\n", (void*)rb, rb->RefCount);*/
_glthread_UNLOCK_MUTEX(rb->Mutex);
*ptr = rb;
} }
} }
/** /**
* Create a new combined depth/stencil renderbuffer for implementing * Create a new combined depth/stencil renderbuffer for implementing
* the GL_EXT_packed_depth_stencil extension. * the GL_EXT_packed_depth_stencil extension.
@@ -2180,4 +2195,3 @@ _mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name)
return dsrb; return dsrb;
} }

View File

@@ -102,7 +102,8 @@ extern void
_mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName); _mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName);
extern void extern void
_mesa_unreference_renderbuffer(struct gl_renderbuffer **rb); _mesa_reference_renderbuffer(struct gl_renderbuffer **ptr,
struct gl_renderbuffer *rb);
extern struct gl_renderbuffer * extern struct gl_renderbuffer *
_mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name); _mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name);