}
+/**
+ * Depending on the position and generic0 attributes enable flags select
+ * the one that is used for both attributes.
+ * The generic0 attribute takes precedence.
+ */
+static inline void
+update_attribute_map_mode(const struct gl_context *ctx,
+ struct gl_vertex_array_object *vao)
+{
+ /*
+ * There is no need to change the mapping away from the
+ * identity mapping if we are not in compat mode.
+ */
+ if (ctx->API != API_OPENGL_COMPAT)
+ return;
+ /* The generic0 attribute superseeds the position attribute */
+ const GLbitfield enabled = vao->_Enabled;
+ if (enabled & VERT_BIT_GENERIC0)
+ vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_GENERIC0;
+ else if (enabled & VERT_BIT_POS)
+ vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_POSITION;
+ else
+ vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_IDENTITY;
+}
+
+
/**
* Sets the BufferBindingIndex field for the vertex attribute given by
* attribIndex.
*/
-static void
-vertex_attrib_binding(struct gl_context *ctx,
- struct gl_vertex_array_object *vao,
- GLuint attribIndex,
- GLuint bindingIndex)
+void
+_mesa_vertex_attrib_binding(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ gl_vert_attrib attribIndex,
+ GLuint bindingIndex)
{
struct gl_array_attributes *array = &vao->VertexAttrib[attribIndex];
+ assert(!vao->SharedAndImmutable);
if (array->BufferBindingIndex != bindingIndex) {
- const GLbitfield64 array_bit = VERT_BIT(attribIndex);
+ const GLbitfield array_bit = VERT_BIT(attribIndex);
if (_mesa_is_bufferobj(vao->BufferBinding[bindingIndex].BufferObj))
vao->VertexAttribBufferMask |= array_bit;
-
- FLUSH_VERTICES(ctx, _NEW_ARRAY);
+ else
+ vao->VertexAttribBufferMask &= ~array_bit;
vao->BufferBinding[array->BufferBindingIndex]._BoundArrays &= ~array_bit;
vao->BufferBinding[bindingIndex]._BoundArrays |= array_bit;
array->BufferBindingIndex = bindingIndex;
- vao->NewArrays |= array_bit;
+ vao->NewArrays |= vao->_Enabled & array_bit;
+ if (vao == ctx->Array.VAO)
+ ctx->NewState |= _NEW_ARRAY;
}
}
struct gl_buffer_object *vbo,
GLintptr offset, GLsizei stride)
{
+ assert(index < ARRAY_SIZE(vao->BufferBinding));
+ assert(!vao->SharedAndImmutable);
struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[index];
if (binding->BufferObj != vbo ||
binding->Offset != offset ||
binding->Stride != stride) {
- FLUSH_VERTICES(ctx, _NEW_ARRAY);
-
_mesa_reference_buffer_object(ctx, &binding->BufferObj, vbo);
binding->Offset = offset;
else
vao->VertexAttribBufferMask |= binding->_BoundArrays;
- vao->NewArrays |= binding->_BoundArrays;
+ vao->NewArrays |= vao->_Enabled & binding->_BoundArrays;
+ if (vao == ctx->Array.VAO)
+ ctx->NewState |= _NEW_ARRAY;
}
}
{
struct gl_vertex_buffer_binding *binding =
&vao->BufferBinding[bindingIndex];
+ assert(!vao->SharedAndImmutable);
if (binding->InstanceDivisor != divisor) {
- FLUSH_VERTICES(ctx, _NEW_ARRAY);
binding->InstanceDivisor = divisor;
- vao->NewArrays |= binding->_BoundArrays;
+ vao->NewArrays |= vao->_Enabled & binding->_BoundArrays;
+ if (vao == ctx->Array.VAO)
+ ctx->NewState |= _NEW_ARRAY;
}
}
* \param doubles Double values not reduced to floats
* \param relativeOffset Offset of the first element relative to the binding
* offset.
- * \param flush_verties Should \c FLUSH_VERTICES be invoked before updating
- * state?
*/
void
_mesa_update_array_format(struct gl_context *ctx,
struct gl_vertex_array_object *vao,
- GLuint attrib, GLint size, GLenum type,
+ gl_vert_attrib attrib, GLint size, GLenum type,
GLenum format, GLboolean normalized,
GLboolean integer, GLboolean doubles,
GLuint relativeOffset)
struct gl_array_attributes *const array = &vao->VertexAttrib[attrib];
GLint elementSize;
+ assert(!vao->SharedAndImmutable);
assert(size <= 4);
elementSize = _mesa_bytes_per_vertex_attrib(size, type);
array->RelativeOffset = relativeOffset;
array->_ElementSize = elementSize;
- vao->NewArrays |= VERT_BIT(attrib);
- ctx->NewState |= _NEW_ARRAY;
+ vao->NewArrays |= vao->_Enabled & VERT_BIT(attrib);
+ if (vao == ctx->Array.VAO)
+ ctx->NewState |= _NEW_ARRAY;
}
/**
return;
}
- if (ctx->API == API_OPENGL_CORE && ctx->Version >= 44 &&
+ if (_mesa_is_desktop_gl(ctx) && ctx->Version >= 44 &&
stride > ctx->Const.MaxVertexAttribStride) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s(stride=%d > "
"GL_MAX_VERTEX_ATTRIB_STRIDE)", func, stride);
normalized, integer, doubles, 0);
/* Reset the vertex attrib binding */
- vertex_attrib_binding(ctx, vao, attrib, attrib);
+ _mesa_vertex_attrib_binding(ctx, vao, attrib, attrib);
/* The Stride and Ptr fields are not set by update_array_format() */
struct gl_array_attributes *array = &vao->VertexAttrib[attrib];
array->Stride = stride;
+ /* For updating the pointer we would need to add the vao->NewArrays flag
+ * to the VAO. But but that is done already unconditionally in
+ * _mesa_update_array_format called above.
+ */
+ assert((vao->NewArrays | ~vao->_Enabled) & VERT_BIT(attrib));
array->Ptr = ptr;
/* Update the vertex buffer binding */
const GLvoid *ptr)
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
update_array(ctx, VERT_ATTRIB_POS, GL_RGBA, 4, size, type, stride,
GL_FALSE, GL_FALSE, GL_FALSE, ptr);
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
-
GLenum format = GL_RGBA;
GLbitfield legalTypes = (ctx->API == API_OPENGLES)
? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
_mesa_NormalPointer_no_error(GLenum type, GLsizei stride, const GLvoid *ptr )
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
update_array(ctx, VERT_ATTRIB_NORMAL, GL_RGBA, 3, 3, type, stride, GL_TRUE,
GL_FALSE, GL_FALSE, ptr);
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
-
GLenum format = GL_RGBA;
const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
const GLvoid *ptr)
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
update_array(ctx, VERT_ATTRIB_COLOR0, format, BGRA_OR_4, size,
GET_CURRENT_CONTEXT(ctx);
const GLint sizeMin = (ctx->API == API_OPENGLES) ? 4 : 3;
- FLUSH_VERTICES(ctx, 0);
-
GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
? (UNSIGNED_BYTE_BIT | HALF_BIT | FLOAT_BIT | FIXED_ES_BIT)
_mesa_FogCoordPointer_no_error(GLenum type, GLsizei stride, const GLvoid *ptr)
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
update_array(ctx, VERT_ATTRIB_FOG, GL_RGBA, 1, 1, type, stride, GL_FALSE,
GL_FALSE, GL_FALSE, ptr);
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
-
GLenum format = GL_RGBA;
const GLbitfield legalTypes = (HALF_BIT | FLOAT_BIT | DOUBLE_BIT);
_mesa_IndexPointer_no_error(GLenum type, GLsizei stride, const GLvoid *ptr)
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
update_array(ctx, VERT_ATTRIB_COLOR_INDEX, GL_RGBA, 1, 1, type, stride,
GL_FALSE, GL_FALSE, GL_FALSE, ptr);
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
-
GLenum format = GL_RGBA;
const GLbitfield legalTypes = (UNSIGNED_BYTE_BIT | SHORT_BIT | INT_BIT |
FLOAT_BIT | DOUBLE_BIT);
GLsizei stride, const GLvoid *ptr)
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
update_array(ctx, VERT_ATTRIB_COLOR1, format, BGRA_OR_4, size, type,
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
-
GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
SHORT_BIT | UNSIGNED_SHORT_BIT |
{
GET_CURRENT_CONTEXT(ctx);
const GLuint unit = ctx->Array.ActiveTexture;
- FLUSH_VERTICES(ctx, 0);
update_array(ctx, VERT_ATTRIB_TEX(unit), GL_RGBA, 4, size, type,
stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr);
const GLint sizeMin = (ctx->API == API_OPENGLES) ? 2 : 1;
const GLuint unit = ctx->Array.ActiveTexture;
- FLUSH_VERTICES(ctx, 0);
-
GLenum format = GL_RGBA;
const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
/* this is the same type that glEdgeFlag uses */
const GLboolean integer = GL_FALSE;
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
update_array(ctx, VERT_ATTRIB_EDGEFLAG, GL_RGBA, 1, 1, GL_UNSIGNED_BYTE,
stride, GL_FALSE, integer, GL_FALSE, ptr);
const GLboolean integer = GL_FALSE;
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
-
GLenum format = GL_RGBA;
const GLbitfield legalTypes = UNSIGNED_BYTE_BIT;
const GLvoid *ptr)
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
update_array(ctx, VERT_ATTRIB_POINT_SIZE, GL_RGBA, 1, 1, type, stride,
GL_FALSE, GL_FALSE, GL_FALSE, ptr);
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
-
GLenum format = GL_RGBA;
if (ctx->API != API_OPENGLES) {
_mesa_error(ctx, GL_INVALID_OPERATION,
void
_mesa_enable_vertex_array_attrib(struct gl_context *ctx,
struct gl_vertex_array_object *vao,
- unsigned attrib)
+ gl_vert_attrib attrib)
{
assert(attrib < ARRAY_SIZE(vao->VertexAttrib));
+ assert(!vao->SharedAndImmutable);
if (!vao->VertexAttrib[attrib].Enabled) {
/* was disabled, now being enabled */
- FLUSH_VERTICES(ctx, _NEW_ARRAY);
vao->VertexAttrib[attrib].Enabled = GL_TRUE;
- vao->_Enabled |= VERT_BIT(attrib);
- vao->NewArrays |= VERT_BIT(attrib);
+ const GLbitfield array_bit = VERT_BIT(attrib);
+ vao->_Enabled |= array_bit;
+ vao->NewArrays |= array_bit;
+
+ if (vao == ctx->Array.VAO)
+ ctx->NewState |= _NEW_ARRAY;
+
+ /* Update the map mode if needed */
+ if (array_bit & (VERT_BIT_POS|VERT_BIT_GENERIC0))
+ update_attribute_map_mode(ctx, vao);
}
}
}
-static void
-disable_vertex_array_attrib(struct gl_context *ctx,
- struct gl_vertex_array_object *vao,
- GLuint index)
+void
+_mesa_disable_vertex_array_attrib(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ gl_vert_attrib attrib)
{
- assert(VERT_ATTRIB_GENERIC(index) < ARRAY_SIZE(vao->VertexAttrib));
+ assert(attrib < ARRAY_SIZE(vao->VertexAttrib));
+ assert(!vao->SharedAndImmutable);
- if (vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) {
+ if (vao->VertexAttrib[attrib].Enabled) {
/* was enabled, now being disabled */
- FLUSH_VERTICES(ctx, _NEW_ARRAY);
- vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_FALSE;
- vao->_Enabled &= ~VERT_BIT_GENERIC(index);
- vao->NewArrays |= VERT_BIT_GENERIC(index);
+ vao->VertexAttrib[attrib].Enabled = GL_FALSE;
+ const GLbitfield array_bit = VERT_BIT(attrib);
+ vao->_Enabled &= ~array_bit;
+ vao->NewArrays |= array_bit;
+
+ if (vao == ctx->Array.VAO)
+ ctx->NewState |= _NEW_ARRAY;
+
+ /* Update the map mode if needed */
+ if (array_bit & (VERT_BIT_POS|VERT_BIT_GENERIC0))
+ update_attribute_map_mode(ctx, vao);
}
}
return;
}
- disable_vertex_array_attrib(ctx, ctx->Array.VAO, index);
+ const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
+ _mesa_disable_vertex_array_attrib(ctx, ctx->Array.VAO, attrib);
}
_mesa_DisableVertexAttribArray_no_error(GLuint index)
{
GET_CURRENT_CONTEXT(ctx);
- disable_vertex_array_attrib(ctx, ctx->Array.VAO, index);
+ const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
+ _mesa_disable_vertex_array_attrib(ctx, ctx->Array.VAO, attrib);
}
return;
}
- disable_vertex_array_attrib(ctx, vao, index);
+ const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
+ _mesa_disable_vertex_array_attrib(ctx, vao, attrib);
}
{
GET_CURRENT_CONTEXT(ctx);
struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
- disable_vertex_array_attrib(ctx, vao, index);
+ const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
+ _mesa_disable_vertex_array_attrib(ctx, vao, attrib);
}
GLint defstride; /* default stride */
GLint c, f;
- FLUSH_VERTICES(ctx, 0);
-
f = sizeof(GLfloat);
c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
-
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
-
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "glUnlockArrays\n");
}
+static void
+primitive_restart_index(struct gl_context *ctx, GLuint index)
+{
+ ctx->Array.RestartIndex = index;
+}
+
+
/**
* GL_NV_primitive_restart and GL 3.1
*/
+void GLAPIENTRY
+_mesa_PrimitiveRestartIndex_no_error(GLuint index)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ primitive_restart_index(ctx, index);
+}
+
+
void GLAPIENTRY
_mesa_PrimitiveRestartIndex(GLuint index)
{
return;
}
- if (ctx->Array.RestartIndex != index) {
- FLUSH_VERTICES(ctx, 0);
- ctx->Array.RestartIndex = index;
- }
+ primitive_restart_index(ctx, index);
}
{
GET_CURRENT_CONTEXT(ctx);
- const GLuint genericIndex = VERT_ATTRIB_GENERIC(index);
+ const gl_vert_attrib genericIndex = VERT_ATTRIB_GENERIC(index);
struct gl_vertex_array_object * const vao = ctx->Array.VAO;
assert(genericIndex < ARRAY_SIZE(vao->VertexAttrib));
* VertexAttribBinding(index, index);
* VertexBindingDivisor(index, divisor);"
*/
- vertex_attrib_binding(ctx, vao, genericIndex, genericIndex);
+ _mesa_vertex_attrib_binding(ctx, vao, genericIndex, genericIndex);
vertex_binding_divisor(ctx, vao, genericIndex, divisor);
}
{
GET_CURRENT_CONTEXT(ctx);
- const GLuint genericIndex = VERT_ATTRIB_GENERIC(index);
+ const gl_vert_attrib genericIndex = VERT_ATTRIB_GENERIC(index);
struct gl_vertex_array_object * const vao = ctx->Array.VAO;
if (!ctx->Extensions.ARB_instanced_arrays) {
* VertexAttribBinding(index, index);
* VertexBindingDivisor(index, divisor);"
*/
- vertex_attrib_binding(ctx, vao, genericIndex, genericIndex);
+ _mesa_vertex_attrib_binding(ctx, vao, genericIndex, genericIndex);
vertex_binding_divisor(ctx, vao, genericIndex, divisor);
}
return;
}
- if (((ctx->API == API_OPENGL_CORE && ctx->Version >= 44) || _mesa_is_gles31(ctx)) &&
+ if (((_mesa_is_desktop_gl(ctx) && ctx->Version >= 44) || _mesa_is_gles31(ctx)) &&
stride > ctx->Const.MaxVertexAttribStride) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s(stride=%d > "
"GL_MAX_VERTEX_ATTRIB_STRIDE)", func, stride);
continue;
}
- if (ctx->API == API_OPENGL_CORE && ctx->Version >= 44 &&
+ if (_mesa_is_desktop_gl(ctx) && ctx->Version >= 44 &&
strides[i] > ctx->Const.MaxVertexAttribStride) {
_mesa_error(ctx, GL_INVALID_VALUE,
"%s(strides[%u]=%d > "
}
}
- FLUSH_VERTICES(ctx, 0);
-
_mesa_update_array_format(ctx, ctx->Array.VAO,
VERT_ATTRIB_GENERIC(attribIndex), size, type,
format, normalized, integer, doubles,
}
}
- FLUSH_VERTICES(ctx, 0);
-
_mesa_update_array_format(ctx, vao, VERT_ATTRIB_GENERIC(attribIndex), size,
type, format, normalized, integer, doubles,
relativeOffset);
assert(VERT_ATTRIB_GENERIC(attribIndex) < ARRAY_SIZE(vao->VertexAttrib));
- vertex_attrib_binding(ctx, vao,
- VERT_ATTRIB_GENERIC(attribIndex),
- VERT_ATTRIB_GENERIC(bindingIndex));
+ _mesa_vertex_attrib_binding(ctx, vao,
+ VERT_ATTRIB_GENERIC(attribIndex),
+ VERT_ATTRIB_GENERIC(bindingIndex));
}
_mesa_VertexAttribBinding_no_error(GLuint attribIndex, GLuint bindingIndex)
{
GET_CURRENT_CONTEXT(ctx);
- vertex_attrib_binding(ctx, ctx->Array.VAO,
- VERT_ATTRIB_GENERIC(attribIndex),
- VERT_ATTRIB_GENERIC(bindingIndex));
+ _mesa_vertex_attrib_binding(ctx, ctx->Array.VAO,
+ VERT_ATTRIB_GENERIC(attribIndex),
+ VERT_ATTRIB_GENERIC(bindingIndex));
}
GET_CURRENT_CONTEXT(ctx);
struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
- vertex_attrib_binding(ctx, vao,
- VERT_ATTRIB_GENERIC(attribIndex),
- VERT_ATTRIB_GENERIC(bindingIndex));
+ _mesa_vertex_attrib_binding(ctx, vao,
+ VERT_ATTRIB_GENERIC(attribIndex),
+ VERT_ATTRIB_GENERIC(bindingIndex));
}
}
+void GLAPIENTRY
+_mesa_VertexArrayBindingDivisor_no_error(GLuint vaobj, GLuint bindingIndex,
+ GLuint divisor)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
+ vertex_binding_divisor(ctx, vao, VERT_ATTRIB_GENERIC(bindingIndex), divisor);
+}
+
+
void GLAPIENTRY
_mesa_VertexArrayBindingDivisor(GLuint vaobj, GLuint bindingIndex,
GLuint divisor)
}
-/**
- * Copy one client vertex array to another.
- */
-void
-_mesa_copy_client_array(struct gl_context *ctx,
- struct gl_vertex_array *dst,
- struct gl_vertex_array *src)
-{
- dst->Size = src->Size;
- dst->Type = src->Type;
- dst->Format = src->Format;
- dst->StrideB = src->StrideB;
- dst->Ptr = src->Ptr;
- dst->Normalized = src->Normalized;
- dst->Integer = src->Integer;
- dst->Doubles = src->Doubles;
- dst->InstanceDivisor = src->InstanceDivisor;
- dst->_ElementSize = src->_ElementSize;
- _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
-}
-
void
_mesa_copy_vertex_attrib_array(struct gl_context *ctx,
struct gl_array_attributes *dst,
dst->Ptr = src->Ptr;
dst->Enabled = src->Enabled;
dst->_ElementSize = src->_ElementSize;
+ dst->_EffBufferBindingIndex = src->_EffBufferBindingIndex;
+ dst->_EffRelativeOffset = src->_EffRelativeOffset;
}
void
dst->Stride = src->Stride;
dst->InstanceDivisor = src->InstanceDivisor;
dst->_BoundArrays = src->_BoundArrays;
+ dst->_EffBoundArrays = src->_EffBoundArrays;
+ dst->_EffOffset = src->_EffOffset;
_mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
}
fprintf(stderr, "Array Object %u\n", vao->Name);
- unsigned i;
+ gl_vert_attrib i;
for (i = 0; i < VERT_ATTRIB_MAX; ++i) {
const struct gl_array_attributes *array = &vao->VertexAttrib[i];
if (!array->Enabled)
{
ctx->Array.DefaultVAO = _mesa_new_vao(ctx, 0);
_mesa_reference_vao(ctx, &ctx->Array.VAO, ctx->Array.DefaultVAO);
+ ctx->Array._EmptyVAO = _mesa_new_vao(ctx, ~0u);
+ _mesa_reference_vao(ctx, &ctx->Array._DrawVAO, ctx->Array._EmptyVAO);
ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */
ctx->Array.Objects = _mesa_NewHashTable();