summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2009-05-13 09:27:31 -0600
committerBrian Paul <brianp@vmware.com>2009-05-13 09:27:31 -0600
commit5568f2f601fbd974af402da92548904f6fafc6dc (patch)
tree41877fb0a4cb8ae26345d125db349b789e92e5e9
parent46b81b0cc883df0ef7d998be36ae6cbf80257cd2 (diff)
mesa: reference counting for gl_array_object
Every kind of object that can be shared by multiple contexts should be refcounted. (cherry picked from commit 1030bf0ded2a88a5e27f7a4d393c11cfde3d3c5a)
-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, 84 insertions, 13 deletions
diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c
index b04095fd16..ccb5b8e157 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)
@@ -129,6 +188,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);
@@ -226,7 +288,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");
@@ -236,11 +297,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 c7d66ec166..9c4036af5a 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 ed6b1062bd..50dc2def87 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1557,6 +1557,9 @@ struct gl_array_object
/** Name of the array object as received from glGenVertexArrayAPPLE. */
GLuint Name;
+ GLint RefCount;
+ _glthread_Mutex Mutex;
+
/** Conventional vertex arrays */
/*@{*/
struct gl_client_array Vertex;
diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c
index 106252e460..72b3e834b3 100644
--- a/src/mesa/main/varray.c
+++ b/src/mesa/main/varray.c
@@ -1050,7 +1050,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 */
}