mesa: reference counting for gl_array_object
Every kind of object that can be shared by multiple contexts should be refcounted.
This commit is contained in:
@@ -94,10 +94,69 @@ void
|
|||||||
_mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj )
|
_mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj )
|
||||||
{
|
{
|
||||||
(void) ctx;
|
(void) ctx;
|
||||||
|
_glthread_DESTROY_MUTEX(obj->Mutex);
|
||||||
_mesa_free(obj);
|
_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
|
static void
|
||||||
init_array(GLcontext *ctx,
|
init_array(GLcontext *ctx,
|
||||||
struct gl_client_array *array, GLint size, GLint type)
|
struct gl_client_array *array, GLint size, GLint type)
|
||||||
@@ -130,6 +189,9 @@ _mesa_initialize_array_object( GLcontext *ctx,
|
|||||||
|
|
||||||
obj->Name = name;
|
obj->Name = name;
|
||||||
|
|
||||||
|
_glthread_INIT_MUTEX(obj->Mutex);
|
||||||
|
obj->RefCount = 1;
|
||||||
|
|
||||||
/* Init the individual arrays */
|
/* Init the individual arrays */
|
||||||
init_array(ctx, &obj->Vertex, 4, GL_FLOAT);
|
init_array(ctx, &obj->Vertex, 4, GL_FLOAT);
|
||||||
init_array(ctx, &obj->Normal, 3, GL_FLOAT);
|
init_array(ctx, &obj->Normal, 3, GL_FLOAT);
|
||||||
@@ -227,7 +289,6 @@ _mesa_BindVertexArrayAPPLE( GLuint id )
|
|||||||
if (!newObj) {
|
if (!newObj) {
|
||||||
/* If this is a new array object id, allocate an array object now.
|
/* If this is a new array object id, allocate an array object now.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
newObj = (*ctx->Driver.NewArrayObject)(ctx, id);
|
newObj = (*ctx->Driver.NewArrayObject)(ctx, id);
|
||||||
if (!newObj) {
|
if (!newObj) {
|
||||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindVertexArrayAPPLE");
|
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindVertexArrayAPPLE");
|
||||||
@@ -237,11 +298,9 @@ _mesa_BindVertexArrayAPPLE( GLuint id )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ctx->NewState |= _NEW_ARRAY;
|
ctx->NewState |= _NEW_ARRAY;
|
||||||
ctx->Array.NewState |= _NEW_ARRAY_ALL;
|
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 */
|
/* Pass BindVertexArray call to device driver */
|
||||||
if (ctx->Driver.BindArrayObject && newObj)
|
if (ctx->Driver.BindArrayObject && newObj)
|
||||||
|
@@ -41,17 +41,26 @@
|
|||||||
* Internal functions
|
* Internal functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct gl_array_object * _mesa_new_array_object( GLcontext *ctx,
|
extern struct gl_array_object *
|
||||||
GLuint name );
|
_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,
|
extern void
|
||||||
struct gl_array_object *obj, GLuint name );
|
_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 );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1557,7 +1557,8 @@ struct gl_array_object
|
|||||||
/** Name of the array object as received from glGenVertexArrayAPPLE. */
|
/** Name of the array object as received from glGenVertexArrayAPPLE. */
|
||||||
GLuint Name;
|
GLuint Name;
|
||||||
|
|
||||||
/** XXX Need a refcount here */
|
GLint RefCount;
|
||||||
|
_glthread_Mutex Mutex;
|
||||||
|
|
||||||
/** Conventional vertex arrays */
|
/** Conventional vertex arrays */
|
||||||
/*@{*/
|
/*@{*/
|
||||||
|
@@ -1039,7 +1039,7 @@ void
|
|||||||
_mesa_init_varray(GLcontext *ctx)
|
_mesa_init_varray(GLcontext *ctx)
|
||||||
{
|
{
|
||||||
ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0);
|
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 */
|
ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user