summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2009-05-07 13:52:26 -0600
committerBrian Paul <[email protected]>2009-05-07 14:34:09 -0600
commit1030bf0ded2a88a5e27f7a4d393c11cfde3d3c5a (patch)
tree6a99a5ef383290ec8cf494931f9434a736e30885
parent9bb6684799f00fabc313ee50be671454e498d8a9 (diff)
mesa: reference counting for gl_array_object
Every kind of object that can be shared by multiple contexts should be refcounted.
-rw-r--r--src/mesa/main/arrayobj.c67
-rw-r--r--src/mesa/main/arrayobj.h23
-rw-r--r--src/mesa/main/mtypes.h3
-rw-r--r--src/mesa/main/varray.c4
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 */
}