From 1030bf0ded2a88a5e27f7a4d393c11cfde3d3c5a Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 7 May 2009 13:52:26 -0600 Subject: [PATCH] mesa: reference counting for gl_array_object Every kind of object that can be shared by multiple contexts should be refcounted. --- src/mesa/main/arrayobj.c | 67 +++++++++++++++++++++++++++++++++++++--- src/mesa/main/arrayobj.h | 23 +++++++++----- src/mesa/main/mtypes.h | 3 +- src/mesa/main/varray.c | 4 +-- 4 files changed, 83 insertions(+), 14 deletions(-) diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c index 2646c12ccc1..71f4216bd31 100644 --- a/src/mesa/main/arrayobj.c +++ b/src/mesa/main/arrayobj.c @@ -94,10 +94,69 @@ void _mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj ) { (void) ctx; + _glthread_DESTROY_MUTEX(obj->Mutex); _mesa_free(obj); } +/** + * Set ptr to arrayObj w/ reference counting. + */ +void +_mesa_reference_array_object(GLcontext *ctx, + struct gl_array_object **ptr, + struct gl_array_object *arrayObj) +{ + if (*ptr == arrayObj) + return; + + if (*ptr) { + /* Unreference the old array object */ + GLboolean deleteFlag = GL_FALSE; + struct gl_array_object *oldObj = *ptr; + + _glthread_LOCK_MUTEX(oldObj->Mutex); + ASSERT(oldObj->RefCount > 0); + oldObj->RefCount--; +#if 0 + printf("ArrayObj %p %d DECR to %d\n", + (void *) oldObj, oldObj->Name, oldObj->RefCount); +#endif + deleteFlag = (oldObj->RefCount == 0); + _glthread_UNLOCK_MUTEX(oldObj->Mutex); + + if (deleteFlag) { + ASSERT(ctx->Driver.DeleteArrayObject); + ctx->Driver.DeleteArrayObject(ctx, oldObj); + } + + *ptr = NULL; + } + ASSERT(!*ptr); + + if (arrayObj) { + /* reference new array object */ + _glthread_LOCK_MUTEX(arrayObj->Mutex); + if (arrayObj->RefCount == 0) { + /* this array's being deleted (look just above) */ + /* Not sure this can every really happen. Warn if it does. */ + _mesa_problem(NULL, "referencing deleted array object"); + *ptr = NULL; + } + else { + arrayObj->RefCount++; +#if 0 + printf("ArrayObj %p %d INCR to %d\n", + (void *) arrayObj, arrayObj->Name, arrayObj->RefCount); +#endif + *ptr = arrayObj; + } + _glthread_UNLOCK_MUTEX(arrayObj->Mutex); + } +} + + + static void init_array(GLcontext *ctx, struct gl_client_array *array, GLint size, GLint type) @@ -130,6 +189,9 @@ _mesa_initialize_array_object( GLcontext *ctx, obj->Name = name; + _glthread_INIT_MUTEX(obj->Mutex); + obj->RefCount = 1; + /* Init the individual arrays */ init_array(ctx, &obj->Vertex, 4, GL_FLOAT); init_array(ctx, &obj->Normal, 3, GL_FLOAT); @@ -227,7 +289,6 @@ _mesa_BindVertexArrayAPPLE( GLuint id ) if (!newObj) { /* If this is a new array object id, allocate an array object now. */ - newObj = (*ctx->Driver.NewArrayObject)(ctx, id); if (!newObj) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindVertexArrayAPPLE"); @@ -237,11 +298,9 @@ _mesa_BindVertexArrayAPPLE( GLuint id ) } } - ctx->NewState |= _NEW_ARRAY; ctx->Array.NewState |= _NEW_ARRAY_ALL; - ctx->Array.ArrayObj = newObj; - + _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, newObj); /* Pass BindVertexArray call to device driver */ if (ctx->Driver.BindArrayObject && newObj) diff --git a/src/mesa/main/arrayobj.h b/src/mesa/main/arrayobj.h index c7d66ec1669..9c4036af5a7 100644 --- a/src/mesa/main/arrayobj.h +++ b/src/mesa/main/arrayobj.h @@ -41,17 +41,26 @@ * Internal functions */ -struct gl_array_object * _mesa_new_array_object( GLcontext *ctx, - GLuint name ); +extern struct gl_array_object * +_mesa_new_array_object( GLcontext *ctx, GLuint name ); -void _mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj ); +extern void +_mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj ); -void _mesa_initialize_array_object( GLcontext *ctx, - struct gl_array_object *obj, GLuint name ); +extern void +_mesa_reference_array_object(GLcontext *ctx, + struct gl_array_object **ptr, + struct gl_array_object *arrayObj); -void _mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj ); +extern void +_mesa_initialize_array_object( GLcontext *ctx, + struct gl_array_object *obj, GLuint name ); -void _mesa_remove_array_object( GLcontext *ctx, struct gl_array_object *obj ); +extern void +_mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj ); + +extern void +_mesa_remove_array_object( GLcontext *ctx, struct gl_array_object *obj ); diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index b24366d0fe3..d11df535f24 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1557,7 +1557,8 @@ struct gl_array_object /** Name of the array object as received from glGenVertexArrayAPPLE. */ GLuint Name; - /** XXX Need a refcount here */ + GLint RefCount; + _glthread_Mutex Mutex; /** Conventional vertex arrays */ /*@{*/ diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c index 4d153b1c0b2..a9c9162be1b 100644 --- a/src/mesa/main/varray.c +++ b/src/mesa/main/varray.c @@ -1039,7 +1039,7 @@ void _mesa_init_varray(GLcontext *ctx) { ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0); - ctx->Array.ArrayObj = ctx->Array.DefaultArrayObj; - + _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, + ctx->Array.DefaultArrayObj); ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */ } -- 2.30.2