summaryrefslogtreecommitdiff
path: root/src/mesa/main/arrayobj.c
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2009-05-07 13:52:26 -0600
committerBrian Paul <brianp@vmware.com>2009-05-07 14:34:09 -0600
commit1030bf0ded2a88a5e27f7a4d393c11cfde3d3c5a (patch)
tree6a99a5ef383290ec8cf494931f9434a736e30885 /src/mesa/main/arrayobj.c
parent9bb6684799f00fabc313ee50be671454e498d8a9 (diff)
mesa: reference counting for gl_array_object
Every kind of object that can be shared by multiple contexts should be refcounted.
Diffstat (limited to 'src/mesa/main/arrayobj.c')
-rw-r--r--src/mesa/main/arrayobj.c67
1 files changed, 63 insertions, 4 deletions
diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c
index 2646c12ccc..71f4216bd3 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)