/** * Generate a set of unique array object IDs and store them in \c arrays. * Helper for _mesa_GenVertexArrays[APPLE]() functions below. * \param n Number of IDs to generate. * \param arrays Array of \c n locations to store the IDs. * \param vboOnly Will arrays have to reside in VBOs? */ static void gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays) { GLuint first; GLint i; ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenVertexArraysAPPLE"); return; } if (!arrays) { return; } first = _mesa_HashFindFreeKeyBlock(ctx->Array.Objects, n); /* Allocate new, empty array objects and return identifiers */ for (i = 0; i < n; i++) { struct gl_array_object *obj; GLuint name = first + i; obj = (*ctx->Driver.NewArrayObject)( ctx, name ); if (!obj) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenVertexArraysAPPLE"); return; } save_array_object(ctx, obj); arrays[i] = first + i; } }
/** * 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); }
/** * Generate a set of unique array object IDs and store them in \c arrays. * Helper for _mesa_GenVertexArrays[APPLE]() and _mesa_CreateVertexArrays() * below. * * \param n Number of IDs to generate. * \param arrays Array of \c n locations to store the IDs. * \param create Indicates that the objects should also be created. * \param func The name of the GL entry point. */ static void gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays, bool create, const char *func) { GLuint first; GLint i; if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); return; } if (!arrays) { return; } first = _mesa_HashFindFreeKeyBlock(ctx->Array.Objects, n); /* For the sake of simplicity we create the array objects in both * the Gen* and Create* cases. The only difference is the value of * EverBound, which is set to true in the Create* case. */ for (i = 0; i < n; i++) { struct gl_vertex_array_object *obj; GLuint name = first + i; obj = _mesa_new_vao(ctx, name); if (!obj) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); return; } obj->EverBound = create; save_array_object(ctx, obj); arrays[i] = first + i; } }
/** * 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_vertex_array_object * const oldObj = ctx->Array.VAO; struct gl_vertex_array_object *newObj = NULL; 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.DefaultVAO; } else { /* non-default array object */ newObj = _mesa_lookup_vao(ctx, id); if (!newObj) { if (genRequired) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBindVertexArray(non-gen name)"); return; } /* For APPLE version, generate a new array object now */ newObj = _mesa_new_vao(ctx, id); if (!newObj) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindVertexArrayAPPLE"); return; } save_array_object(ctx, newObj); } if (!newObj->EverBound) { /* 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->EverBound = GL_TRUE; } } if (ctx->Array.DrawMethod == DRAW_ARRAYS) { /* The _DrawArrays pointer is pointing at the VAO being unbound and * that VAO may be in the process of being deleted. If it's not going * to be deleted, this will have no effect, because the pointer needs * to be updated by the VBO module anyway. * * Before the VBO module can update the pointer, we have to set it * to NULL for drivers not to set up arrays which are not bound, * or to prevent a crash if the VAO being unbound is going to be * deleted. */ ctx->Array._DrawArrays = NULL; ctx->Array.DrawMethod = DRAW_NONE; } ctx->NewState |= _NEW_ARRAY; _mesa_reference_vao(ctx, &ctx->Array.VAO, newObj); }