/** * Helper for _mesa_BindVertexArray() and _mesa_BindVertexArrayAPPLE(). * \param genRequired specifies behavour when id was not generated with * glGenVertexArrays(). */ static void bind_vertex_array(struct gl_context *ctx, GLuint id, GLboolean genRequired) { struct gl_array_object * const oldObj = ctx->Array.ArrayObj; struct gl_array_object *newObj = NULL; ASSERT_OUTSIDE_BEGIN_END(ctx); ASSERT(oldObj != NULL); if ( oldObj->Name == id ) return; /* rebinding the same array object- no change */ /* * Get pointer to new array object (newObj) */ if (id == 0) { /* The spec says there is no array object named 0, but we use * one internally because it simplifies things. */ newObj = ctx->Array.DefaultArrayObj; } else { /* non-default array object */ newObj = lookup_arrayobj(ctx, id); if (!newObj) { if (genRequired) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBindVertexArray(id)"); return; } /* For APPLE version, generate a new array object now */ newObj = (*ctx->Driver.NewArrayObject)(ctx, id); if (!newObj) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindVertexArrayAPPLE"); return; } save_array_object(ctx, newObj); } if (!newObj->_Used) { /* The "Interactions with APPLE_vertex_array_object" section of the * GL_ARB_vertex_array_object spec says: * * "The first bind call, either BindVertexArray or * BindVertexArrayAPPLE, determines the semantic of the object." */ newObj->ARBsemantics = genRequired; newObj->_Used = GL_TRUE; } } ctx->NewState |= _NEW_ARRAY; ctx->Array.NewState |= VERT_BIT_ALL; _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, newObj); /* Pass BindVertexArray call to device driver */ if (ctx->Driver.BindArrayObject && newObj) ctx->Driver.BindArrayObject(ctx, newObj); }
/** * Delete a set of array objects. * * \param n Number of array objects to delete. * \param ids Array of \c n array object IDs. */ void GLAPIENTRY _mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids) { GET_CURRENT_CONTEXT(ctx); GLsizei i; ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteVertexArrayAPPLE(n)"); return; } _glthread_LOCK_MUTEX(ctx->Shared->Mutex); for (i = 0; i < n; i++) { struct gl_array_object *obj = lookup_arrayobj(ctx, ids[i]); 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." */ if ( obj == ctx->Array.ArrayObj ) { 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. */ unbind_buffer_object( ctx, obj->Vertex.BufferObj ); unbind_buffer_object( ctx, obj->Normal.BufferObj ); unbind_buffer_object( ctx, obj->Color.BufferObj ); unbind_buffer_object( ctx, obj->SecondaryColor.BufferObj ); unbind_buffer_object( ctx, obj->FogCoord.BufferObj ); unbind_buffer_object( ctx, obj->Index.BufferObj ); for (i = 0; i < MAX_TEXTURE_UNITS; i++) { unbind_buffer_object( ctx, obj->TexCoord[i].BufferObj ); } unbind_buffer_object( ctx, obj->EdgeFlag.BufferObj ); for (i = 0; i < VERT_ATTRIB_MAX; i++) { 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); } } _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); }
/** * Determine if ID is the name of an array object. * * \param id ID of the potential array object. * \return \c GL_TRUE if \c id is the name of a array object, * \c GL_FALSE otherwise. */ GLboolean GLAPIENTRY _mesa_IsVertexArrayAPPLE( GLuint id ) { struct gl_array_object * obj; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); if (id == 0) return GL_FALSE; obj = lookup_arrayobj(ctx, id); return (obj != NULL) ? GL_TRUE : GL_FALSE; }
/** * Bind a new array. * * \todo * The binding could be done more efficiently by comparing the non-NULL * pointers in the old and new objects. The only arrays that are "dirty" are * the ones that are non-NULL in either object. */ void GLAPIENTRY _mesa_BindVertexArrayAPPLE( GLuint id ) { GET_CURRENT_CONTEXT(ctx); struct gl_array_object * const oldObj = ctx->Array.ArrayObj; struct gl_array_object *newObj = NULL; ASSERT_OUTSIDE_BEGIN_END(ctx); ASSERT(oldObj != NULL); if ( oldObj->Name == id ) return; /* rebinding the same array object- no change */ /* * Get pointer to new array object (newBufObj) */ if (id == 0) { /* The spec says there is no array object named 0, but we use * one internally because it simplifies things. */ newObj = ctx->Array.DefaultArrayObj; } else { /* non-default array object */ newObj = lookup_arrayobj(ctx, 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"); return; } _mesa_save_array_object(ctx, newObj); } } ctx->NewState |= _NEW_ARRAY; ctx->Array.NewState |= _NEW_ARRAY_ALL; ctx->Array.ArrayObj = newObj; /* Pass BindVertexArray call to device driver */ if (ctx->Driver.BindArrayObject && newObj) (*ctx->Driver.BindArrayObject)( ctx, newObj ); }
/** * Delete a set of array objects. * * \param n Number of array objects to delete. * \param ids Array of \c n array object IDs. */ void GLAPIENTRY _mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids) { GET_CURRENT_CONTEXT(ctx); GLsizei i; ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteVertexArrayAPPLE(n)"); return; } for (i = 0; i < n; i++) { struct gl_array_object *obj = lookup_arrayobj(ctx, ids[i]); 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." */ if ( obj == ctx->Array.ArrayObj ) { CALL_BindVertexArrayAPPLE( ctx->Exec, (0) ); } /* The ID is immediately freed for re-use */ remove_array_object(ctx, obj); /* Unreference the array object. * If refcount hits zero, the object will be deleted. */ _mesa_reference_array_object(ctx, &obj, NULL); } } }