/*
* Mesa 3-D graphics library
- * Version: 6.5
+ * Version: 7.2
*
- * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
* (C) Copyright IBM Corporation 2006
*
* Permission is hereby granted, free of charge, to any person obtaining a
#include "bufferobj.h"
#endif
#include "arrayobj.h"
-#include "dispatch.h"
+#include "glapi/dispatch.h"
/**
}
+/**
+ * For all the vertex arrays in the array object, unbind any pointers
+ * to any buffer objects (VBOs).
+ * This is done just prior to array object destruction.
+ */
+static void
+unbind_array_object_vbos(GLcontext *ctx, struct gl_array_object *obj)
+{
+ GLuint i;
+
+ _mesa_reference_buffer_object(ctx, &obj->Vertex.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->Normal.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->Color.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->SecondaryColor.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->FogCoord.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->Index.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->EdgeFlag.BufferObj, NULL);
+
+ for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++)
+ _mesa_reference_buffer_object(ctx, &obj->TexCoord[i].BufferObj, NULL);
+
+ for (i = 0; i < VERT_ATTRIB_MAX; i++)
+ _mesa_reference_buffer_object(ctx, &obj->VertexAttrib[i].BufferObj,NULL);
+}
+
+
/**
* Allocate and initialize a new vertex array object.
*
struct gl_array_object *
_mesa_new_array_object( GLcontext *ctx, GLuint name )
{
- struct gl_array_object *obj = MALLOC_STRUCT(gl_array_object);
+ struct gl_array_object *obj = CALLOC_STRUCT(gl_array_object);
if (obj)
_mesa_initialize_array_object(ctx, obj, name);
return obj;
_mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj )
{
(void) ctx;
+ unbind_array_object_vbos(ctx, obj);
+ _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)
+{
+ array->Size = size;
+ array->Type = type;
+ array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */
+ array->Stride = 0;
+ array->StrideB = 0;
+ array->Ptr = NULL;
+ array->Enabled = GL_FALSE;
+ array->Normalized = GL_FALSE;
+#if FEATURE_ARB_vertex_buffer_object
+ /* Vertex array buffers */
+ array->BufferObj = ctx->Array.NullBufferObj;
+#endif
+}
+
+
+/**
+ * Initialize a gl_array_object's arrays.
+ */
void
_mesa_initialize_array_object( GLcontext *ctx,
struct gl_array_object *obj,
obj->Name = name;
- /* Vertex arrays */
- obj->Vertex.Size = 4;
- obj->Vertex.Type = GL_FLOAT;
- obj->Vertex.Stride = 0;
- obj->Vertex.StrideB = 0;
- obj->Vertex.Ptr = NULL;
- obj->Vertex.Enabled = GL_FALSE;
- obj->Normal.Type = GL_FLOAT;
- obj->Normal.Stride = 0;
- obj->Normal.StrideB = 0;
- obj->Normal.Ptr = NULL;
- obj->Normal.Enabled = GL_FALSE;
- obj->Color.Size = 4;
- obj->Color.Type = GL_FLOAT;
- obj->Color.Stride = 0;
- obj->Color.StrideB = 0;
- obj->Color.Ptr = NULL;
- obj->Color.Enabled = GL_FALSE;
- obj->SecondaryColor.Size = 4;
- obj->SecondaryColor.Type = GL_FLOAT;
- obj->SecondaryColor.Stride = 0;
- obj->SecondaryColor.StrideB = 0;
- obj->SecondaryColor.Ptr = NULL;
- obj->SecondaryColor.Enabled = GL_FALSE;
- obj->FogCoord.Size = 1;
- obj->FogCoord.Type = GL_FLOAT;
- obj->FogCoord.Stride = 0;
- obj->FogCoord.StrideB = 0;
- obj->FogCoord.Ptr = NULL;
- obj->FogCoord.Enabled = GL_FALSE;
- obj->Index.Type = GL_FLOAT;
- obj->Index.Stride = 0;
- obj->Index.StrideB = 0;
- obj->Index.Ptr = NULL;
- obj->Index.Enabled = GL_FALSE;
- for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
- obj->TexCoord[i].Size = 4;
- obj->TexCoord[i].Type = GL_FLOAT;
- obj->TexCoord[i].Stride = 0;
- obj->TexCoord[i].StrideB = 0;
- obj->TexCoord[i].Ptr = NULL;
- obj->TexCoord[i].Enabled = GL_FALSE;
+ _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);
+ init_array(ctx, &obj->Color, 4, GL_FLOAT);
+ init_array(ctx, &obj->SecondaryColor, 4, GL_FLOAT);
+ init_array(ctx, &obj->FogCoord, 1, GL_FLOAT);
+ init_array(ctx, &obj->Index, 1, GL_FLOAT);
+ for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
+ init_array(ctx, &obj->TexCoord[i], 4, GL_FLOAT);
}
- obj->EdgeFlag.Stride = 0;
- obj->EdgeFlag.StrideB = 0;
- obj->EdgeFlag.Ptr = NULL;
- obj->EdgeFlag.Enabled = GL_FALSE;
+ init_array(ctx, &obj->EdgeFlag, 1, GL_BOOL);
for (i = 0; i < VERT_ATTRIB_MAX; i++) {
- obj->VertexAttrib[i].Size = 4;
- obj->VertexAttrib[i].Type = GL_FLOAT;
- obj->VertexAttrib[i].Stride = 0;
- obj->VertexAttrib[i].StrideB = 0;
- obj->VertexAttrib[i].Ptr = NULL;
- obj->VertexAttrib[i].Enabled = GL_FALSE;
- obj->VertexAttrib[i].Normalized = GL_FALSE;
+ init_array(ctx, &obj->VertexAttrib[i], 4, GL_FLOAT);
}
-#if FEATURE_ARB_vertex_buffer_object
- /* Vertex array buffers */
- obj->Vertex.BufferObj = ctx->Array.NullBufferObj;
- obj->Normal.BufferObj = ctx->Array.NullBufferObj;
- obj->Color.BufferObj = ctx->Array.NullBufferObj;
- obj->SecondaryColor.BufferObj = ctx->Array.NullBufferObj;
- obj->FogCoord.BufferObj = ctx->Array.NullBufferObj;
- obj->Index.BufferObj = ctx->Array.NullBufferObj;
- for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
- obj->TexCoord[i].BufferObj = ctx->Array.NullBufferObj;
- }
- obj->EdgeFlag.BufferObj = ctx->Array.NullBufferObj;
- for (i = 0; i < VERT_ATTRIB_MAX; i++) {
- obj->VertexAttrib[i].BufferObj = ctx->Array.NullBufferObj;
- }
+#if FEATURE_point_size_array
+ init_array(ctx, &obj->PointSize, 1, GL_FLOAT);
#endif
}
return; /* rebinding the same array object- no change */
/*
- * Get pointer to new array object (newBufObj)
+ * Get pointer to new array object (newObj)
*/
if (id == 0) {
/* The spec says there is no array object named 0, but we use
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");
}
}
-
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)
if ( obj != NULL ) {
ASSERT( obj->Name == ids[i] );
-
/* If the array object is currently bound, the spec says "the binding
* for that object reverts to zero and the default vertex array
* becomes current."
CALL_BindVertexArrayAPPLE( ctx->Exec, (0) );
}
-#if FEATURE_ARB_vertex_buffer_object
- /* Unbind any buffer objects that might be bound to arrays in
- * this array object.
- */
- _mesa_unbind_buffer_object( ctx, obj->Vertex.BufferObj );
- _mesa_unbind_buffer_object( ctx, obj->Normal.BufferObj );
- _mesa_unbind_buffer_object( ctx, obj->Color.BufferObj );
- _mesa_unbind_buffer_object( ctx, obj->SecondaryColor.BufferObj );
- _mesa_unbind_buffer_object( ctx, obj->FogCoord.BufferObj );
- _mesa_unbind_buffer_object( ctx, obj->Index.BufferObj );
- for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
- _mesa_unbind_buffer_object( ctx, obj->TexCoord[i].BufferObj );
- }
- _mesa_unbind_buffer_object( ctx, obj->EdgeFlag.BufferObj );
- for (i = 0; i < VERT_ATTRIB_MAX; i++) {
- _mesa_unbind_buffer_object( ctx, obj->VertexAttrib[i].BufferObj );
- }
-#endif
-
/* The ID is immediately freed for re-use */
_mesa_remove_array_object(ctx, obj);
- ctx->Driver.DeleteArrayObject(ctx, obj);
+
+ /* Unreference the array object.
+ * If refcount hits zero, the object will be deleted.
+ */
+ _mesa_reference_array_object(ctx, &obj, NULL);
}
}