mesa: include stdio.h where needed
[mesa.git] / src / mesa / main / varray.c
index 39e5ad30ab839be8ab1d471d96d8f05a1cc7ec8c..42e7f89b264f1bfe6eb7708ed4a4a33b0afbd1c6 100644 (file)
@@ -24,6 +24,9 @@
  */
 
 
+#include <stdio.h>
+#include <inttypes.h>  /* for PRId64 macro */
+
 #include "glheader.h"
 #include "imports.h"
 #include "bufferobj.h"
 /** Used to indicate which GL datatypes are accepted by each of the
  * glVertex/Color/Attrib/EtcPointer() functions.
  */
-#define BOOL_BIT             0x1
-#define BYTE_BIT             0x2
-#define UNSIGNED_BYTE_BIT    0x4
-#define SHORT_BIT            0x8
-#define UNSIGNED_SHORT_BIT   0x10
-#define INT_BIT              0x20
-#define UNSIGNED_INT_BIT     0x40
-#define HALF_BIT             0x80
-#define FLOAT_BIT            0x100
-#define DOUBLE_BIT           0x200
-#define FIXED_ES_BIT         0x400
-#define FIXED_GL_BIT         0x800
-#define UNSIGNED_INT_2_10_10_10_REV_BIT 0x1000
-#define INT_2_10_10_10_REV_BIT 0x2000
+#define BOOL_BIT                          (1 << 0)
+#define BYTE_BIT                          (1 << 1)
+#define UNSIGNED_BYTE_BIT                 (1 << 2)
+#define SHORT_BIT                         (1 << 3)
+#define UNSIGNED_SHORT_BIT                (1 << 4)
+#define INT_BIT                           (1 << 5)
+#define UNSIGNED_INT_BIT                  (1 << 6)
+#define HALF_BIT                          (1 << 7)
+#define FLOAT_BIT                         (1 << 8)
+#define DOUBLE_BIT                        (1 << 9)
+#define FIXED_ES_BIT                      (1 << 10)
+#define FIXED_GL_BIT                      (1 << 11)
+#define UNSIGNED_INT_2_10_10_10_REV_BIT   (1 << 12)
+#define INT_2_10_10_10_REV_BIT            (1 << 13)
+#define UNSIGNED_INT_10F_11F_11F_REV_BIT  (1 << 14)
+#define ALL_TYPE_BITS                    ((1 << 15) - 1)
 
 
 /** Convert GL datatype enum into a <type>_BIT value seen above */
@@ -96,6 +101,8 @@ type_to_bit(const struct gl_context *ctx, GLenum type)
       return UNSIGNED_INT_2_10_10_10_REV_BIT;
    case GL_INT_2_10_10_10_REV:
       return INT_2_10_10_10_REV_BIT;
+   case GL_UNSIGNED_INT_10F_11F_11F_REV:
+      return UNSIGNED_INT_10F_11F_11F_REV_BIT;
    default:
       return 0;
    }
@@ -109,20 +116,20 @@ static void
 vertex_attrib_binding(struct gl_context *ctx, GLuint attribIndex,
                       GLuint bindingIndex)
 {
-   struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
-   struct gl_vertex_attrib_array *array = &arrayObj->VertexAttrib[attribIndex];
+   struct gl_vertex_array_object *vao = ctx->Array.VAO;
+   struct gl_vertex_attrib_array *array = &vao->VertexAttrib[attribIndex];
 
    if (array->VertexBinding != bindingIndex) {
       const GLbitfield64 array_bit = VERT_BIT(attribIndex);
 
       FLUSH_VERTICES(ctx, _NEW_ARRAY);
 
-      arrayObj->VertexBinding[array->VertexBinding]._BoundArrays &= ~array_bit;
-      arrayObj->VertexBinding[bindingIndex]._BoundArrays |= array_bit;
+      vao->VertexBinding[array->VertexBinding]._BoundArrays &= ~array_bit;
+      vao->VertexBinding[bindingIndex]._BoundArrays |= array_bit;
 
       array->VertexBinding = bindingIndex;
 
-      arrayObj->NewArrays |= array_bit;
+      vao->NewArrays |= array_bit;
    }
 }
 
@@ -136,8 +143,8 @@ bind_vertex_buffer(struct gl_context *ctx, GLuint index,
                    struct gl_buffer_object *vbo,
                    GLintptr offset, GLsizei stride)
 {
-   struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
-   struct gl_vertex_buffer_binding *binding = &arrayObj->VertexBinding[index];
+   struct gl_vertex_array_object *vao = ctx->Array.VAO;
+   struct gl_vertex_buffer_binding *binding = &vao->VertexBinding[index];
 
    if (binding->BufferObj != vbo ||
        binding->Offset != offset ||
@@ -150,7 +157,7 @@ bind_vertex_buffer(struct gl_context *ctx, GLuint index,
       binding->Offset = offset;
       binding->Stride = stride;
 
-      arrayObj->NewArrays |= binding->_BoundArrays;
+      vao->NewArrays |= binding->_BoundArrays;
    }
 }
 
@@ -163,15 +170,62 @@ static void
 vertex_binding_divisor(struct gl_context *ctx, GLuint bindingIndex,
                        GLuint divisor)
 {
-   struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+   struct gl_vertex_array_object *vao = ctx->Array.VAO;
    struct gl_vertex_buffer_binding *binding =
-      &arrayObj->VertexBinding[bindingIndex];
+      &vao->VertexBinding[bindingIndex];
 
    if (binding->InstanceDivisor != divisor) {
       FLUSH_VERTICES(ctx, _NEW_ARRAY);
       binding->InstanceDivisor = divisor;
-      arrayObj->NewArrays |= binding->_BoundArrays;
+      vao->NewArrays |= binding->_BoundArrays;
+   }
+}
+
+
+/**
+ * Examine the API profile and extensions to determine which types are legal
+ * for vertex arrays.  This is called once from update_array_format().
+ */
+static GLbitfield
+get_legal_types_mask(const struct gl_context *ctx)
+{
+   GLbitfield legalTypesMask = ALL_TYPE_BITS;
+
+   if (_mesa_is_gles(ctx)) {
+      legalTypesMask &= ~(FIXED_GL_BIT |
+                          DOUBLE_BIT |
+                          UNSIGNED_INT_10F_11F_11F_REV_BIT);
+
+      /* GL_INT and GL_UNSIGNED_INT data is not allowed in OpenGL ES until
+       * 3.0.  The 2_10_10_10 types are added in OpenGL ES 3.0 or
+       * GL_OES_vertex_type_10_10_10_2.  GL_HALF_FLOAT data is not allowed
+       * until 3.0 or with the GL_OES_vertex_half float extension, which isn't
+       * quite as trivial as we'd like because it uses a different enum value
+       * for GL_HALF_FLOAT_OES.
+       */
+      if (ctx->Version < 30) {
+         legalTypesMask &= ~(UNSIGNED_INT_BIT |
+                             INT_BIT |
+                             UNSIGNED_INT_2_10_10_10_REV_BIT |
+                             INT_2_10_10_10_REV_BIT |
+                             HALF_BIT);
+      }
+   }
+   else {
+      legalTypesMask &= ~FIXED_ES_BIT;
+
+      if (!ctx->Extensions.ARB_ES2_compatibility)
+         legalTypesMask &= ~FIXED_GL_BIT;
+
+      if (!ctx->Extensions.ARB_vertex_type_2_10_10_10_rev)
+         legalTypesMask &= ~(UNSIGNED_INT_2_10_10_10_REV_BIT |
+                             INT_2_10_10_10_REV_BIT);
+
+      if (!ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev)
+         legalTypesMask &= ~UNSIGNED_INT_10F_11F_11F_REV_BIT;
    }
+
+   return legalTypesMask;
 }
 
 
@@ -202,40 +256,25 @@ update_array_format(struct gl_context *ctx,
 {
    struct gl_vertex_attrib_array *array;
    GLbitfield typeBit;
-   GLuint elementSize;
+   GLint elementSize;
    GLenum format = GL_RGBA;
 
-   if (_mesa_is_gles(ctx)) {
-      legalTypesMask &= ~(FIXED_GL_BIT | DOUBLE_BIT);
-
-      /* GL_INT and GL_UNSIGNED_INT data is not allowed in OpenGL ES until
-       * 3.0.  The 2_10_10_10 types are added in OpenGL ES 3.0 or
-       * GL_OES_vertex_type_10_10_10_2.  GL_HALF_FLOAT data is not allowed
-       * until 3.0 or with the GL_OES_vertex_half float extension, which isn't
-       * quite as trivial as we'd like because it uses a different enum value
-       * for GL_HALF_FLOAT_OES.
+   if (ctx->Array.LegalTypesMask == 0 || ctx->Array.LegalTypesMaskAPI != ctx->API) {
+      /* Compute the LegalTypesMask only once, unless the context API has
+       * changed, in which case we want to compute it again.  We can't do this
+       * in _mesa_init_varrays() below because extensions are not yet enabled
+       * at that point.
        */
-      if (ctx->Version < 30) {
-         legalTypesMask &= ~(UNSIGNED_INT_BIT
-                             | INT_BIT
-                             | UNSIGNED_INT_2_10_10_10_REV_BIT
-                             | INT_2_10_10_10_REV_BIT
-                             | HALF_BIT);
-      }
+      ctx->Array.LegalTypesMask = get_legal_types_mask(ctx);
+      ctx->Array.LegalTypesMaskAPI = ctx->API;
+   }
 
+   legalTypesMask &= ctx->Array.LegalTypesMask;
+
+   if (_mesa_is_gles(ctx) && sizeMax == BGRA_OR_4) {
       /* BGRA ordering is not supported in ES contexts.
        */
-      if (sizeMax == BGRA_OR_4)
-         sizeMax = 4;
-   } else {
-      legalTypesMask &= ~FIXED_ES_BIT;
-
-      if (!ctx->Extensions.ARB_ES2_compatibility)
-         legalTypesMask &= ~FIXED_GL_BIT;
-
-      if (!ctx->Extensions.ARB_vertex_type_2_10_10_10_rev)
-         legalTypesMask &= ~(UNSIGNED_INT_2_10_10_10_REV_BIT |
-                             INT_2_10_10_10_REV_BIT);
+      sizeMax = 4;
    }
 
    typeBit = type_to_bit(ctx, type);
@@ -309,15 +348,21 @@ update_array_format(struct gl_context *ctx,
                   "%s(relativeOffset=%d > "
                   "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET)",
                   func, relativeOffset);
-      return GL_FALSE;
+      return false;
+   }
+
+   if (ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev &&
+         type == GL_UNSIGNED_INT_10F_11F_11F_REV && size != 3) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size);
+      return false;
    }
 
-   ASSERT(size <= 4);
+   assert(size <= 4);
 
    elementSize = _mesa_bytes_per_vertex_attrib(size, type);
    assert(elementSize != -1);
 
-   array = &ctx->Array.ArrayObj->VertexAttrib[attrib];
+   array = &ctx->Array.VAO->VertexAttrib[attrib];
    array->Size = size;
    array->Type = type;
    array->Format = format;
@@ -326,7 +371,7 @@ update_array_format(struct gl_context *ctx,
    array->RelativeOffset = relativeOffset;
    array->_ElementSize = elementSize;
 
-   ctx->Array.ArrayObj->NewArrays |= VERT_BIT(attrib);
+   ctx->Array.VAO->NewArrays |= VERT_BIT(attrib);
    ctx->NewState |= _NEW_ARRAY;
 
    return true;
@@ -372,19 +417,21 @@ update_array(struct gl_context *ctx,
     * The check for VBOs is handled below.
     */
    if (ctx->API == API_OPENGL_CORE
-       && (ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj)) {
+       && (ctx->Array.VAO == ctx->Array.DefaultVAO)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no array object bound)",
                   func);
       return;
    }
 
-   if (!update_array_format(ctx, func, attrib, legalTypesMask, sizeMin, sizeMax,
-                            size, type, normalized, integer, 0)) {
+   if (stride < 0) {
+      _mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride );
       return;
    }
 
-   if (stride < 0) {
-      _mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride );
+   if (ctx->API == API_OPENGL_CORE && ctx->Version >= 44 &&
+       stride > ctx->Const.MaxVertexAttribStride) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride=%d > "
+                  "GL_MAX_VERTEX_ATTRIB_STRIDE)", func, stride);
       return;
    }
 
@@ -400,17 +447,22 @@ update_array(struct gl_context *ctx,
     *       to the ARRAY_BUFFER buffer object binding point (see section
     *       2.9.6), and the pointer argument is not NULL."
     */
-   if (ptr != NULL && ctx->Array.ArrayObj->ARBsemantics &&
+   if (ptr != NULL && ctx->Array.VAO->ARBsemantics &&
        !_mesa_is_bufferobj(ctx->Array.ArrayBufferObj)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-VBO array)", func);
       return;
    }
 
+   if (!update_array_format(ctx, func, attrib, legalTypesMask, sizeMin,
+                            sizeMax, size, type, normalized, integer, 0)) {
+      return;
+   }
+
    /* Reset the vertex attrib binding */
    vertex_attrib_binding(ctx, attrib, attrib);
 
    /* The Stride and Ptr fields are not set by update_array_format() */
-   array = &ctx->Array.ArrayObj->VertexAttrib[attrib];
+   array = &ctx->Array.VAO->VertexAttrib[attrib];
    array->Stride = stride;
    array->Ptr = (const GLvoid *) ptr;
 
@@ -557,8 +609,8 @@ void GLAPIENTRY
 _mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
 {
    const GLbitfield legalTypes = UNSIGNED_BYTE_BIT;
-   /* see table 2.4 edits in GL_EXT_gpu_shader4 spec: */
-   const GLboolean integer = GL_TRUE;
+   /* this is the same type that glEdgeFlag uses */
+   const GLboolean integer = GL_FALSE;
    GET_CURRENT_CONTEXT(ctx);
 
    FLUSH_VERTICES(ctx, 0);
@@ -605,10 +657,11 @@ _mesa_VertexAttribPointer(GLuint index, GLint size, GLenum type,
                                   HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
                                   FIXED_ES_BIT | FIXED_GL_BIT |
                                   UNSIGNED_INT_2_10_10_10_REV_BIT |
-                                  INT_2_10_10_10_REV_BIT);
+                                  INT_2_10_10_10_REV_BIT |
+                                  UNSIGNED_INT_10F_11F_11F_REV_BIT);
    GET_CURRENT_CONTEXT(ctx);
 
-   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
+   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)");
       return;
    }
@@ -636,7 +689,7 @@ _mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type,
    const GLboolean integer = GL_TRUE;
    GET_CURRENT_CONTEXT(ctx);
 
-   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
+   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribIPointer(index)");
       return;
    }
@@ -651,25 +704,25 @@ _mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type,
 void GLAPIENTRY
 _mesa_EnableVertexAttribArray(GLuint index)
 {
-   struct gl_array_object *arrayObj;
+   struct gl_vertex_array_object *vao;
    GET_CURRENT_CONTEXT(ctx);
 
-   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
+   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "glEnableVertexAttribArrayARB(index)");
       return;
    }
 
-   arrayObj = ctx->Array.ArrayObj;
+   vao = ctx->Array.VAO;
 
-   ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->_VertexAttrib));
+   assert(VERT_ATTRIB_GENERIC(index) < ARRAY_SIZE(vao->VertexAttrib));
 
-   if (!arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) {
+   if (!vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) {
       /* was disabled, now being enabled */
       FLUSH_VERTICES(ctx, _NEW_ARRAY);
-      arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_TRUE;
-      arrayObj->_Enabled |= VERT_BIT_GENERIC(index);
-      arrayObj->NewArrays |= VERT_BIT_GENERIC(index);
+      vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_TRUE;
+      vao->_Enabled |= VERT_BIT_GENERIC(index);
+      vao->NewArrays |= VERT_BIT_GENERIC(index);
    }
 }
 
@@ -677,25 +730,25 @@ _mesa_EnableVertexAttribArray(GLuint index)
 void GLAPIENTRY
 _mesa_DisableVertexAttribArray(GLuint index)
 {
-   struct gl_array_object *arrayObj;
+   struct gl_vertex_array_object *vao;
    GET_CURRENT_CONTEXT(ctx);
 
-   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
+   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "glDisableVertexAttribArrayARB(index)");
       return;
    }
 
-   arrayObj = ctx->Array.ArrayObj;
+   vao = ctx->Array.VAO;
 
-   ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->_VertexAttrib));
+   assert(VERT_ATTRIB_GENERIC(index) < ARRAY_SIZE(vao->VertexAttrib));
 
-   if (arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) {
+   if (vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) {
       /* was enabled, now being disabled */
       FLUSH_VERTICES(ctx, _NEW_ARRAY);
-      arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_FALSE;
-      arrayObj->_Enabled &= ~VERT_BIT_GENERIC(index);
-      arrayObj->NewArrays |= VERT_BIT_GENERIC(index);
+      vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_FALSE;
+      vao->_Enabled &= ~VERT_BIT_GENERIC(index);
+      vao->NewArrays |= VERT_BIT_GENERIC(index);
    }
 }
 
@@ -709,23 +762,23 @@ static GLuint
 get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
                   const char *caller)
 {
-   const struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+   const struct gl_vertex_array_object *vao = ctx->Array.VAO;
    const struct gl_vertex_attrib_array *array;
 
-   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
+   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
       _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", caller, index);
       return 0;
    }
 
-   ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->VertexAttrib));
+   assert(VERT_ATTRIB_GENERIC(index) < ARRAY_SIZE(vao->VertexAttrib));
 
-   array = &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)];
+   array = &vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)];
 
    switch (pname) {
    case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
       return array->Enabled;
    case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
-      return array->Size;
+      return (array->Format == GL_BGRA) ? GL_BGRA : array->Size;
    case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
       return array->Stride;
    case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
@@ -733,7 +786,7 @@ get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
    case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
       return array->Normalized;
    case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
-      return arrayObj->VertexBinding[array->VertexBinding].BufferObj->Name;
+      return vao->VertexBinding[array->VertexBinding].BufferObj->Name;
    case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
       if ((_mesa_is_desktop_gl(ctx)
            && (ctx->Version >= 30 || ctx->Extensions.EXT_gpu_shader4))
@@ -744,7 +797,7 @@ get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
    case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB:
       if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_instanced_arrays)
           || _mesa_is_gles3(ctx)) {
-         return arrayObj->VertexBinding[array->VertexBinding].InstanceDivisor;
+         return vao->VertexBinding[array->VertexBinding].InstanceDivisor;
       }
       goto error;
    case GL_VERTEX_ATTRIB_BINDING:
@@ -771,24 +824,18 @@ static const GLfloat *
 get_current_attrib(struct gl_context *ctx, GLuint index, const char *function)
 {
    if (index == 0) {
-      /* In OpenGL 3.1 attribute 0 becomes non-magic, just like in OpenGL ES
-       * 2.0.  Note that we cannot just check for API_OPENGL_CORE here because
-       * that will erroneously allow this usage in a 3.0 forward-compatible
-       * context too.
-       */
-      if ((ctx->API != API_OPENGL_CORE || ctx->Version < 31)
-          && ctx->API != API_OPENGLES2) {
+      if (_mesa_attr_zero_aliases_vertex(ctx)) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(index==0)", function);
         return NULL;
       }
    }
-   else if (index >= ctx->Const.VertexProgram.MaxAttribs) {
+   else if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                  "%s(index>=GL_MAX_VERTEX_ATTRIBS)", function);
       return NULL;
    }
 
-   ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->_VertexAttrib));
+   assert(VERT_ATTRIB_GENERIC(index) < ARRAY_SIZE(ctx->Array.VAO->VertexAttrib));
 
    FLUSH_CURRENT(ctx, 0);
    return ctx->Current.Attrib[VERT_ATTRIB_GENERIC(index)];
@@ -900,7 +947,7 @@ _mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer)
 {
    GET_CURRENT_CONTEXT(ctx);
 
-   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
+   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)");
       return;
    }
@@ -910,9 +957,9 @@ _mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer)
       return;
    }
 
-   ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->_VertexAttrib));
+   assert(VERT_ATTRIB_GENERIC(index) < ARRAY_SIZE(ctx->Array.VAO->VertexAttrib));
 
-   *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr;
+   *pointer = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr;
 }
 
 
@@ -1210,7 +1257,7 @@ _mesa_MultiDrawArrays( GLenum mode, const GLint *first,
 
    for (i = 0; i < primcount; i++) {
       if (count[i] > 0) {
-         CALL_DrawArrays(ctx->Exec, (mode, first[i], count[i]));
+         CALL_DrawArrays(ctx->CurrentDispatch, (mode, first[i], count[i]));
       }
    }
 }
@@ -1230,7 +1277,7 @@ _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
    for ( i = 0 ; i < primcount ; i++ ) {
       if ( count[i] > 0 ) {
          GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
-        CALL_DrawArrays(ctx->Exec, ( m, first[i], count[i] ));
+        CALL_DrawArrays(ctx->CurrentDispatch, ( m, first[i], count[i] ));
       }
    }
 }
@@ -1252,7 +1299,8 @@ _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
    for ( i = 0 ; i < primcount ; i++ ) {
       if ( count[i] > 0 ) {
          GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
-        CALL_DrawElements(ctx->Exec, ( m, count[i], type, indices[i] ));
+        CALL_DrawElements(ctx->CurrentDispatch, ( m, count[i], type,
+                                                   indices[i] ));
       }
    }
 }
@@ -1295,13 +1343,13 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor)
       return;
    }
 
-   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
+   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribDivisor(index = %u)",
                   index);
       return;
    }
 
-   ASSERT(genericIndex < Elements(ctx->Array.ArrayObj->VertexAttrib));
+   assert(genericIndex < ARRAY_SIZE(ctx->Array.VAO->VertexAttrib));
 
    /* The ARB_vertex_attrib_binding spec says:
     *
@@ -1351,9 +1399,10 @@ void GLAPIENTRY
 _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
                        GLsizei stride)
 {
+   GET_CURRENT_CONTEXT(ctx);
+   const struct gl_vertex_array_object *vao = ctx->Array.VAO;
    struct gl_buffer_object *vbo;
 
-   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    /* The ARB_vertex_attrib_binding spec says:
@@ -1362,7 +1411,7 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
     *     is bound."
     */
    if (ctx->API == API_OPENGL_CORE &&
-       ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) {
+       ctx->Array.VAO == ctx->Array.DefaultVAO) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glBindVertexBuffer(No array object bound)");
       return;
@@ -1388,7 +1437,8 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
     */
    if (offset < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glBindVertexBuffer(offset=%lld < 0)", (long long)offset);
+                  "glBindVertexBuffer(offset=%" PRId64 " < 0)",
+                  (int64_t) offset);
       return;
    }
 
@@ -1398,7 +1448,16 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
       return;
    }
 
-   if (buffer != 0) {
+   if (ctx->API == API_OPENGL_CORE && ctx->Version >= 44 &&
+       stride > ctx->Const.MaxVertexAttribStride) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glBindVertexBuffer(stride=%d > "
+                  "GL_MAX_VERTEX_ATTRIB_STRIDE)", stride);
+      return;
+   }
+
+   if (buffer == vao->VertexBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj->Name) {
+      vbo = vao->VertexBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj;
+   } else if (buffer != 0) {
       vbo = _mesa_lookup_bufferobj(ctx, buffer);
 
       /* From the GL_ARB_vertex_attrib_array spec:
@@ -1428,6 +1487,134 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
 }
 
 
+void GLAPIENTRY
+_mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
+                        const GLintptr *offsets, const GLsizei *strides)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_vertex_array_object * const vao = ctx->Array.VAO;
+   GLuint i;
+
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   /* The ARB_vertex_attrib_binding spec says:
+    *
+    *    "An INVALID_OPERATION error is generated if no
+    *     vertex array object is bound."
+    */
+   if (ctx->API == API_OPENGL_CORE &&
+       ctx->Array.VAO == ctx->Array.DefaultVAO) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glBindVertexBuffers(No array object bound)");
+      return;
+   }
+
+   /* The ARB_multi_bind spec says:
+    *
+    *    "An INVALID_OPERATION error is generated if <first> + <count>
+    *     is greater than the value of MAX_VERTEX_ATTRIB_BINDINGS."
+    */
+   if (first + count > ctx->Const.MaxVertexAttribBindings) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glBindVertexBuffers(first=%u + count=%d > the value of "
+                  "GL_MAX_VERTEX_ATTRIB_BINDINGS=%u)",
+                  first, count, ctx->Const.MaxVertexAttribBindings);
+      return;
+   }
+
+   if (!buffers) {
+      /**
+       * The ARB_multi_bind spec says:
+       *
+       *    "If <buffers> is NULL, each affected vertex buffer binding point
+       *     from <first> through <first>+<count>-1 will be reset to have no
+       *     bound buffer object.  In this case, the offsets and strides
+       *     associated with the binding points are set to default values,
+       *     ignoring <offsets> and <strides>."
+       */
+      struct gl_buffer_object *vbo = ctx->Shared->NullBufferObj;
+
+      for (i = 0; i < count; i++)
+         bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(first + i), vbo, 0, 16);
+
+      return;
+   }
+
+   /* Note that the error semantics for multi-bind commands differ from
+    * those of other GL commands.
+    *
+    * The Issues section in the ARB_multi_bind spec says:
+    *
+    *    "(11) Typically, OpenGL specifies that if an error is generated by
+    *          a command, that command has no effect.  This is somewhat
+    *          unfortunate for multi-bind commands, because it would require
+    *          a first pass to scan the entire list of bound objects for
+    *          errors and then a second pass to actually perform the
+    *          bindings.  Should we have different error semantics?
+    *
+    *       RESOLVED:  Yes.  In this specification, when the parameters for
+    *       one of the <count> binding points are invalid, that binding
+    *       point is not updated and an error will be generated.  However,
+    *       other binding points in the same command will be updated if
+    *       their parameters are valid and no other error occurs."
+    */
+
+   _mesa_begin_bufferobj_lookups(ctx);
+
+   for (i = 0; i < count; i++) {
+      struct gl_buffer_object *vbo;
+
+      /* The ARB_multi_bind spec says:
+       *
+       *    "An INVALID_VALUE error is generated if any value in
+       *     <offsets> or <strides> is negative (per binding)."
+       */
+      if (offsets[i] < 0) {
+         _mesa_error(ctx, GL_INVALID_VALUE,
+                     "glBindVertexBuffers(offsets[%u]=%" PRId64 " < 0)",
+                     i, (int64_t) offsets[i]);
+         continue;
+      }
+
+      if (strides[i] < 0) {
+         _mesa_error(ctx, GL_INVALID_VALUE,
+                     "glBindVertexBuffers(strides[%u]=%d < 0)",
+                     i, strides[i]);
+         continue;
+      }
+
+      if (ctx->API == API_OPENGL_CORE && ctx->Version >= 44 &&
+          strides[i] > ctx->Const.MaxVertexAttribStride) {
+         _mesa_error(ctx, GL_INVALID_VALUE,
+                     "glBindVertexBuffers(strides[%u]=%d > "
+                     "GL_MAX_VERTEX_ATTRIB_STRIDE)", i, strides[i]);
+         continue;
+      }
+
+      if (buffers[i]) {
+         struct gl_vertex_buffer_binding *binding =
+            &vao->VertexBinding[VERT_ATTRIB_GENERIC(first + i)];
+
+         if (buffers[i] == binding->BufferObj->Name)
+            vbo = binding->BufferObj;
+         else
+            vbo = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i,
+                                                    "glBindVertexBuffers");
+
+         if (!vbo)
+            continue;
+      } else {
+         vbo = ctx->Shared->NullBufferObj;
+      }
+
+      bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(first + i), vbo,
+                         offsets[i], strides[i]);
+   }
+
+   _mesa_end_bufferobj_lookups(ctx);
+}
+
+
 void GLAPIENTRY
 _mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type,
                          GLboolean normalized, GLuint relativeOffset)
@@ -1438,7 +1625,8 @@ _mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type,
                                    HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
                                    FIXED_GL_BIT |
                                    UNSIGNED_INT_2_10_10_10_REV_BIT |
-                                   INT_2_10_10_10_REV_BIT);
+                                   INT_2_10_10_10_REV_BIT |
+                                   UNSIGNED_INT_10F_11F_11F_REV_BIT);
 
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -1451,7 +1639,7 @@ _mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type,
     *     - ..."
     */
    if (ctx->API == API_OPENGL_CORE &&
-       ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) {
+       ctx->Array.VAO == ctx->Array.DefaultVAO) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glVertexAttribFormat(No array object bound)");
       return;
@@ -1462,7 +1650,7 @@ _mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type,
     *   "The error INVALID_VALUE is generated if index is greater than or equal
     *     to the value of MAX_VERTEX_ATTRIBS."
     */
-   if (attribIndex >= ctx->Const.VertexProgram.MaxAttribs) {
+   if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "glVertexAttribFormat(attribindex=%u > "
                   "GL_MAX_VERTEX_ATTRIBS)",
@@ -1498,7 +1686,7 @@ _mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type,
     *     - ..."
     */
    if (ctx->API == API_OPENGL_CORE &&
-       ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) {
+       ctx->Array.VAO == ctx->Array.DefaultVAO) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glVertexAttribIFormat(No array object bound)");
       return;
@@ -1509,7 +1697,7 @@ _mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type,
     *   "The error INVALID_VALUE is generated if index is greater than
     *    or equal to the value of MAX_VERTEX_ATTRIBS."
     */
-   if (attribIndex >= ctx->Const.VertexProgram.MaxAttribs) {
+   if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "glVertexAttribIFormat(attribindex=%u > "
                   "GL_MAX_VERTEX_ATTRIBS)",
@@ -1546,7 +1734,7 @@ _mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type,
     * that this is an oversight.
     */
    if (ctx->API == API_OPENGL_CORE &&
-       ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) {
+       ctx->Array.VAO == ctx->Array.DefaultVAO) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glVertexAttribLFormat(No array object bound)");
       return;
@@ -1557,7 +1745,7 @@ _mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type,
     *   "The error INVALID_VALUE is generated if <attribindex> is greater than
     *    or equal to the value of MAX_VERTEX_ATTRIBS."
     */
-   if (attribIndex >= ctx->Const.VertexProgram.MaxAttribs) {
+   if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "glVertexAttribLFormat(attribindex=%u > "
                   "GL_MAX_VERTEX_ATTRIBS)",
@@ -1586,7 +1774,7 @@ _mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
     *     is bound."
     */
    if (ctx->API == API_OPENGL_CORE &&
-       ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) {
+       ctx->Array.VAO == ctx->Array.DefaultVAO) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glVertexAttribBinding(No array object bound)");
       return;
@@ -1599,7 +1787,7 @@ _mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
     *     MAX_VERTEX_ATTRIB_BINDINGS, otherwise the error INVALID_VALUE
     *     is generated."
     */
-   if (attribIndex >= ctx->Const.VertexProgram.MaxAttribs) {
+   if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "glVertexAttribBinding(attribindex=%u >= "
                   "GL_MAX_VERTEX_ATTRIBS)",
@@ -1615,8 +1803,8 @@ _mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
       return;
    }
 
-   ASSERT(VERT_ATTRIB_GENERIC(attribIndex) <
-          Elements(ctx->Array.ArrayObj->VertexAttrib));
+   assert(VERT_ATTRIB_GENERIC(attribIndex) <
+          ARRAY_SIZE(ctx->Array.VAO->VertexAttrib));
 
    vertex_attrib_binding(ctx, VERT_ATTRIB_GENERIC(attribIndex),
                          VERT_ATTRIB_GENERIC(bindingIndex));
@@ -1640,7 +1828,7 @@ _mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
     *     is bound."
     */
    if (ctx->API == API_OPENGL_CORE &&
-       ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) {
+       ctx->Array.VAO == ctx->Array.DefaultVAO) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glVertexBindingDivisor(No array object bound)");
       return;
@@ -1683,7 +1871,6 @@ _mesa_copy_client_array(struct gl_context *ctx,
    dst->InstanceDivisor = src->InstanceDivisor;
    dst->_ElementSize = src->_ElementSize;
    _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
-   dst->_MaxElement = src->_MaxElement;
 }
 
 void
@@ -1724,14 +1911,13 @@ static void
 print_array(const char *name, GLint index, const struct gl_client_array *array)
 {
    if (index >= 0)
-      printf("  %s[%d]: ", name, index);
+      fprintf(stderr, "  %s[%d]: ", name, index);
    else
-      printf("  %s: ", name);
-   printf("Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %lu), MaxElem=%u\n",
+      fprintf(stderr, "  %s: ", name);
+   fprintf(stderr, "Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %lu)\n",
          array->Ptr, array->Type, array->Size,
          array->_ElementSize, array->StrideB,
-         array->BufferObj->Name, (unsigned long) array->BufferObj->Size,
-         array->_MaxElement);
+         array->BufferObj->Name, (unsigned long) array->BufferObj->Size);
 }
 
 
@@ -1741,25 +1927,22 @@ print_array(const char *name, GLint index, const struct gl_client_array *array)
 void
 _mesa_print_arrays(struct gl_context *ctx)
 {
-   struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+   struct gl_vertex_array_object *vao = ctx->Array.VAO;
    GLuint i;
 
-   _mesa_update_array_object_max_element(ctx, arrayObj);
-
-   printf("Array Object %u\n", arrayObj->Name);
-   if (arrayObj->_VertexAttrib[VERT_ATTRIB_POS].Enabled)
-      print_array("Vertex", -1, &arrayObj->_VertexAttrib[VERT_ATTRIB_POS]);
-   if (arrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled)
-      print_array("Normal", -1, &arrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL]);
-   if (arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled)
-      print_array("Color", -1, &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0]);
+   printf("Array Object %u\n", vao->Name);
+   if (vao->_VertexAttrib[VERT_ATTRIB_POS].Enabled)
+      print_array("Vertex", -1, &vao->_VertexAttrib[VERT_ATTRIB_POS]);
+   if (vao->_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled)
+      print_array("Normal", -1, &vao->_VertexAttrib[VERT_ATTRIB_NORMAL]);
+   if (vao->_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled)
+      print_array("Color", -1, &vao->_VertexAttrib[VERT_ATTRIB_COLOR0]);
    for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)
-      if (arrayObj->_VertexAttrib[VERT_ATTRIB_TEX(i)].Enabled)
-         print_array("TexCoord", i, &arrayObj->_VertexAttrib[VERT_ATTRIB_TEX(i)]);
+      if (vao->_VertexAttrib[VERT_ATTRIB_TEX(i)].Enabled)
+         print_array("TexCoord", i, &vao->_VertexAttrib[VERT_ATTRIB_TEX(i)]);
    for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++)
-      if (arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
-         print_array("Attrib", i, &arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(i)]);
-   printf("  _MaxElement = %u\n", arrayObj->_MaxElement);
+      if (vao->_VertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
+         print_array("Attrib", i, &vao->_VertexAttrib[VERT_ATTRIB_GENERIC(i)]);
 }
 
 
@@ -1769,9 +1952,8 @@ _mesa_print_arrays(struct gl_context *ctx)
 void 
 _mesa_init_varray(struct gl_context *ctx)
 {
-   ctx->Array.DefaultArrayObj = ctx->Driver.NewArrayObject(ctx, 0);
-   _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj,
-                                ctx->Array.DefaultArrayObj);
+   ctx->Array.DefaultVAO = ctx->Driver.NewArrayObject(ctx, 0);
+   _mesa_reference_vao(ctx, &ctx->Array.VAO, ctx->Array.DefaultVAO);
    ctx->Array.ActiveTexture = 0;   /* GL_ARB_multitexture */
 
    ctx->Array.Objects = _mesa_NewHashTable();
@@ -1784,9 +1966,9 @@ _mesa_init_varray(struct gl_context *ctx)
 static void
 delete_arrayobj_cb(GLuint id, void *data, void *userData)
 {
-   struct gl_array_object *arrayObj = (struct gl_array_object *) data;
+   struct gl_vertex_array_object *vao = (struct gl_vertex_array_object *) data;
    struct gl_context *ctx = (struct gl_context *) userData;
-   _mesa_delete_array_object(ctx, arrayObj);
+   _mesa_delete_vao(ctx, vao);
 }