mesa: add ASTC 2D LDR decoder
[mesa.git] / src / mesa / main / varray.c
index a08b11fcf8d6d8ce9b9b6e8102994b836ef1b5db..a3e1aebb76cd391e58a285637d62fd6650641489 100644 (file)
@@ -125,32 +125,61 @@ type_to_bit(const struct gl_context *ctx, GLenum type)
 }
 
 
+/**
+ * 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;
    }
 }
 
@@ -166,14 +195,14 @@ _mesa_bind_vertex_buffer(struct gl_context *ctx,
                          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;
@@ -184,7 +213,9 @@ _mesa_bind_vertex_buffer(struct gl_context *ctx,
       else
          vao->VertexAttribBufferMask |= binding->_BoundArrays;
 
-      vao->NewArrays |= binding->_BoundArrays;
+      vao->NewArrays |= vao->_Enabled & binding->_BoundArrays;
+      if (vao == ctx->Array.VAO)
+         ctx->NewState |= _NEW_ARRAY;
    }
 }
 
@@ -201,11 +232,13 @@ vertex_binding_divisor(struct gl_context *ctx,
 {
    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;
    }
 }
 
@@ -287,13 +320,11 @@ get_array_format(const struct gl_context *ctx, GLint sizeMax, GLint *size)
  * \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)
@@ -301,6 +332,7 @@ _mesa_update_array_format(struct gl_context *ctx,
    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);
@@ -315,8 +347,9 @@ _mesa_update_array_format(struct gl_context *ctx,
    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;
 }
 
 /**
@@ -490,7 +523,7 @@ validate_array(struct gl_context *ctx, const char *func,
       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);
@@ -563,11 +596,16 @@ update_array(struct gl_context *ctx,
                              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 */
@@ -582,7 +620,6 @@ _mesa_VertexPointer_no_error(GLint size, GLenum type, GLsizei stride,
                              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);
@@ -594,8 +631,6 @@ _mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *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)
@@ -619,7 +654,6 @@ void GLAPIENTRY
 _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);
@@ -631,8 +665,6 @@ _mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *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)
@@ -657,7 +689,6 @@ _mesa_ColorPointer_no_error(GLint size, GLenum type, 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_COLOR0, format, BGRA_OR_4, size,
@@ -671,8 +702,6 @@ _mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
    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)
@@ -699,7 +728,6 @@ void GLAPIENTRY
 _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);
@@ -711,8 +739,6 @@ _mesa_FogCoordPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
 {
    GET_CURRENT_CONTEXT(ctx);
 
-   FLUSH_VERTICES(ctx, 0);
-
    GLenum format = GL_RGBA;
    const GLbitfield legalTypes = (HALF_BIT | FLOAT_BIT | DOUBLE_BIT);
 
@@ -731,7 +757,6 @@ void GLAPIENTRY
 _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);
@@ -743,8 +768,6 @@ _mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *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);
@@ -766,7 +789,6 @@ _mesa_SecondaryColorPointer_no_error(GLint size, GLenum type,
                                      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,
@@ -780,8 +802,6 @@ _mesa_SecondaryColorPointer(GLint size, GLenum 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 |
@@ -808,7 +828,6 @@ _mesa_TexCoordPointer_no_error(GLint size, GLenum type, GLsizei stride,
 {
    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);
@@ -823,8 +842,6 @@ _mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
    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)
@@ -851,7 +868,6 @@ _mesa_EdgeFlagPointer_no_error(GLsizei stride, const GLvoid *ptr)
    /* 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);
@@ -865,8 +881,6 @@ _mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
    const GLboolean integer = GL_FALSE;
    GET_CURRENT_CONTEXT(ctx);
 
-   FLUSH_VERTICES(ctx, 0);
-
    GLenum format = GL_RGBA;
    const GLbitfield legalTypes = UNSIGNED_BYTE_BIT;
 
@@ -887,7 +901,6 @@ _mesa_PointSizePointerOES_no_error(GLenum type, GLsizei stride,
                                    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);
@@ -899,8 +912,6 @@ _mesa_PointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *ptr)
 {
    GET_CURRENT_CONTEXT(ctx);
 
-   FLUSH_VERTICES(ctx, 0);
-
    GLenum format = GL_RGBA;
    if (ctx->API != API_OPENGLES) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
@@ -1062,16 +1073,24 @@ _mesa_VertexAttribLPointer(GLuint index, GLint size, GLenum type,
 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);
    }
 }
 
@@ -1099,6 +1118,15 @@ _mesa_EnableVertexAttribArray(GLuint index)
 }
 
 
+void GLAPIENTRY
+_mesa_EnableVertexAttribArray_no_error(GLuint index)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   _mesa_enable_vertex_array_attrib(ctx, ctx->Array.VAO,
+                                    VERT_ATTRIB_GENERIC(index));
+}
+
+
 void GLAPIENTRY
 _mesa_EnableVertexArrayAttrib(GLuint vaobj, GLuint index)
 {
@@ -1120,25 +1148,36 @@ _mesa_EnableVertexArrayAttrib(GLuint vaobj, GLuint index)
 }
 
 
-static void
-disable_vertex_array_attrib(struct gl_context *ctx,
-                            struct gl_vertex_array_object *vao,
-                            GLuint index,
-                            const char *func)
+void GLAPIENTRY
+_mesa_EnableVertexArrayAttrib_no_error(GLuint vaobj, GLuint index)
 {
-   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
-      return;
-   }
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
+   _mesa_enable_vertex_array_attrib(ctx, vao, VERT_ATTRIB_GENERIC(index));
+}
 
-   assert(VERT_ATTRIB_GENERIC(index) < ARRAY_SIZE(vao->VertexAttrib));
 
-   if (vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) {
+void
+_mesa_disable_vertex_array_attrib(struct gl_context *ctx,
+                                  struct gl_vertex_array_object *vao,
+                                  gl_vert_attrib attrib)
+{
+   assert(attrib < ARRAY_SIZE(vao->VertexAttrib));
+   assert(!vao->SharedAndImmutable);
+
+   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);
    }
 }
 
@@ -1147,8 +1186,23 @@ void GLAPIENTRY
 _mesa_DisableVertexAttribArray(GLuint index)
 {
    GET_CURRENT_CONTEXT(ctx);
-   disable_vertex_array_attrib(ctx, ctx->Array.VAO, index,
-                               "glDisableVertexAttribArray");
+
+   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glDisableVertexAttribArray(index)");
+      return;
+   }
+
+   const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
+   _mesa_disable_vertex_array_attrib(ctx, ctx->Array.VAO, attrib);
+}
+
+
+void GLAPIENTRY
+_mesa_DisableVertexAttribArray_no_error(GLuint index)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
+   _mesa_disable_vertex_array_attrib(ctx, ctx->Array.VAO, attrib);
 }
 
 
@@ -1169,7 +1223,23 @@ _mesa_DisableVertexArrayAttrib(GLuint vaobj, GLuint index)
    if (!vao)
       return;
 
-   disable_vertex_array_attrib(ctx, vao, index, "glDisableVertexArrayAttrib");
+   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glDisableVertexArrayAttrib(index)");
+      return;
+   }
+
+   const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
+   _mesa_disable_vertex_array_attrib(ctx, vao, attrib);
+}
+
+
+void GLAPIENTRY
+_mesa_DisableVertexArrayAttrib_no_error(GLuint vaobj, GLuint index)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
+   const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
+   _mesa_disable_vertex_array_attrib(ctx, vao, attrib);
 }
 
 
@@ -1353,6 +1423,29 @@ _mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
    }
 }
 
+void GLAPIENTRY
+_mesa_GetVertexAttribLui64vARB(GLuint index, GLenum pname, GLuint64EXT *params)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
+      const GLuint64 *v =
+         (const GLuint64 *)get_current_attrib(ctx, index,
+                                              "glGetVertexAttribLui64vARB");
+      if (v != NULL) {
+         params[0] = v[0];
+         params[1] = v[1];
+         params[2] = v[2];
+         params[3] = v[3];
+      }
+   }
+   else {
+      params[0] = (GLuint64) get_vertex_array_attrib(ctx, ctx->Array.VAO,
+                                                     index, pname,
+                                                     "glGetVertexAttribLui64vARB");
+   }
+}
+
 
 /** GL 3.0 */
 void GLAPIENTRY
@@ -1601,8 +1694,6 @@ _mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
    GLint defstride;                /* default stride */
    GLint c, f;
 
-   FLUSH_VERTICES(ctx, 0);
-
    f = sizeof(GLfloat);
    c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
 
@@ -1772,8 +1863,6 @@ _mesa_LockArraysEXT(GLint first, GLsizei count)
 {
    GET_CURRENT_CONTEXT(ctx);
 
-   FLUSH_VERTICES(ctx, 0);
-
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
 
@@ -1802,8 +1891,6 @@ _mesa_UnlockArraysEXT( void )
 {
    GET_CURRENT_CONTEXT(ctx);
 
-   FLUSH_VERTICES(ctx, 0);
-
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glUnlockArrays\n");
 
@@ -1861,9 +1948,24 @@ _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
 }
 
 
+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)
 {
@@ -1874,10 +1976,7 @@ _mesa_PrimitiveRestartIndex(GLuint index)
       return;
    }
 
-   if (ctx->Array.RestartIndex != index) {
-      FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
-      ctx->Array.RestartIndex = index;
-   }
+   primitive_restart_index(ctx, index);
 }
 
 
@@ -1886,7 +1985,7 @@ _mesa_VertexAttribDivisor_no_error(GLuint index, GLuint 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;
 
    assert(genericIndex < ARRAY_SIZE(vao->VertexAttrib));
@@ -1902,7 +2001,7 @@ _mesa_VertexAttribDivisor_no_error(GLuint index, GLuint divisor)
     *       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);
 }
 
@@ -1917,7 +2016,7 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint 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) {
@@ -1944,7 +2043,7 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor)
     *       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);
 }
 
@@ -2035,7 +2134,7 @@ vertex_array_vertex_buffer_err(struct gl_context *ctx,
       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);
@@ -2189,7 +2288,7 @@ vertex_array_vertex_buffers(struct gl_context *ctx,
             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 > "
@@ -2379,8 +2478,6 @@ vertex_attrib_format(GLuint attribIndex, GLint size, GLenum type,
       }
    }
 
-   FLUSH_VERTICES(ctx, 0);
-
    _mesa_update_array_format(ctx, ctx->Array.VAO,
                              VERT_ATTRIB_GENERIC(attribIndex), size, type,
                              format, normalized, integer, doubles,
@@ -2469,8 +2566,6 @@ vertex_array_attrib_format(GLuint vaobj, GLuint attribIndex, GLint size,
       }
    }
 
-   FLUSH_VERTICES(ctx, 0);
-
    _mesa_update_array_format(ctx, vao, VERT_ATTRIB_GENERIC(attribIndex), size,
                              type, format, normalized, integer, doubles,
                              relativeOffset);
@@ -2546,9 +2641,19 @@ vertex_array_attrib_binding(struct gl_context *ctx,
 
    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));
+}
+
+
+void GLAPIENTRY
+_mesa_VertexAttribBinding_no_error(GLuint attribIndex, GLuint bindingIndex)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   _mesa_vertex_attrib_binding(ctx, ctx->Array.VAO,
+                               VERT_ATTRIB_GENERIC(attribIndex),
+                               VERT_ATTRIB_GENERIC(bindingIndex));
 }
 
 
@@ -2575,6 +2680,19 @@ _mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
 }
 
 
+void GLAPIENTRY
+_mesa_VertexArrayAttribBinding_no_error(GLuint vaobj, GLuint attribIndex,
+                                        GLuint bindingIndex)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
+   _mesa_vertex_attrib_binding(ctx, vao,
+                               VERT_ATTRIB_GENERIC(attribIndex),
+                               VERT_ATTRIB_GENERIC(bindingIndex));
+}
+
+
 void GLAPIENTRY
 _mesa_VertexArrayAttribBinding(GLuint vaobj, GLuint attribIndex, GLuint bindingIndex)
 {
@@ -2626,6 +2744,15 @@ vertex_array_binding_divisor(struct gl_context *ctx,
 }
 
 
+void GLAPIENTRY
+_mesa_VertexBindingDivisor_no_error(GLuint bindingIndex, GLuint divisor)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   vertex_binding_divisor(ctx, ctx->Array.VAO,
+                          VERT_ATTRIB_GENERIC(bindingIndex), divisor);
+}
+
+
 void GLAPIENTRY
 _mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
 {
@@ -2649,6 +2776,17 @@ _mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
 }
 
 
+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)
@@ -2671,27 +2809,6 @@ _mesa_VertexArrayBindingDivisor(GLuint vaobj, GLuint bindingIndex,
 }
 
 
-/**
- * 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,
@@ -2709,6 +2826,8 @@ _mesa_copy_vertex_attrib_array(struct gl_context *ctx,
    dst->Ptr            = src->Ptr;
    dst->Enabled        = src->Enabled;
    dst->_ElementSize   = src->_ElementSize;
+   dst->_EffBufferBindingIndex = src->_EffBufferBindingIndex;
+   dst->_EffRelativeOffset = src->_EffRelativeOffset;
 }
 
 void
@@ -2720,6 +2839,8 @@ _mesa_copy_vertex_buffer_binding(struct gl_context *ctx,
    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);
 }
@@ -2734,7 +2855,7 @@ _mesa_print_arrays(struct gl_context *ctx)
 
    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)
@@ -2762,6 +2883,8 @@ _mesa_init_varray(struct gl_context *ctx)
 {
    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();