Add implementation for Vertex Array Object state.

TRAC #23390

Signed-off-by: Shannon Woods
Signed-off-by: Geoff Lang
Authored-by: Jamie Madill
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 5694c02..a36779b 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -25,6 +25,7 @@
 #include "libGLESv2/renderer/IndexDataManager.h"
 #include "libGLESv2/renderer/RenderTarget.h"
 #include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/VertexArray.h"
 
 #include "libEGL/Surface.h"
 
@@ -147,6 +148,7 @@
     mTexture2DArrayZero.set(new Texture2DArray(mRenderer, 0));
 
     mState.activeSampler = 0;
+    bindVertexArray(0);
     bindArrayBuffer(0);
     bindElementArrayBuffer(0);
     bindTextureCubeMap(0);
@@ -231,6 +233,11 @@
         deleteQuery(mQueryMap.begin()->first);
     }
 
+    while (!mVertexArrayMap.empty())
+    {
+        deleteVertexArray(mVertexArrayMap.begin()->first);
+    }
+
     for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
     {
         for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)
@@ -248,7 +255,6 @@
     for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++)
     {
         mState.vertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues);
-        mState.vertexAttribute[attribIndex].mBoundBuffer.set(NULL);
     }
 
     for (int i = 0; i < QUERY_TYPE_COUNT; i++)
@@ -257,7 +263,6 @@
     }
 
     mState.arrayBuffer.set(NULL);
-    mState.elementArrayBuffer.set(NULL);
     mState.renderbuffer.set(NULL);
 
     mTexture2DZero.set(NULL);
@@ -687,14 +692,12 @@
 
 void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
 {
-    ASSERT(attribNum < MAX_VERTEX_ATTRIBS);
-    mState.vertexAttribute[attribNum].mArrayEnabled = enabled;
+    getCurrentVertexArray()->enableAttribute(attribNum, enabled);
 }
 
 const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum) const
 {
-    ASSERT(attribNum < MAX_VERTEX_ATTRIBS);
-    return mState.vertexAttribute[attribNum];
+    return getCurrentVertexArray()->getVertexAttribute(attribNum);
 }
 
 const VertexAttribCurrentValueData &Context::getVertexAttribCurrentValue(unsigned int attribNum) const
@@ -706,18 +709,12 @@
 void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized,
                                    bool pureInteger, GLsizei stride, const void *pointer)
 {
-    mState.vertexAttribute[attribNum].mBoundBuffer.set(boundBuffer);
-    mState.vertexAttribute[attribNum].mSize = size;
-    mState.vertexAttribute[attribNum].mType = type;
-    mState.vertexAttribute[attribNum].mNormalized = normalized;
-    mState.vertexAttribute[attribNum].mPureInteger = pureInteger;
-    mState.vertexAttribute[attribNum].mStride = stride;
-    mState.vertexAttribute[attribNum].mPointer = pointer;
+    getCurrentVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer);
 }
 
 const void *Context::getVertexAttribPointer(unsigned int attribNum) const
 {
-    return mState.vertexAttribute[attribNum].mPointer;
+    return getCurrentVertexArray()->getVertexAttribute(attribNum).mPointer;
 }
 
 void Context::setPackAlignment(GLint alignment)
@@ -775,6 +772,15 @@
     return mResourceManager->createRenderbuffer();
 }
 
+GLuint Context::createVertexArray()
+{
+    GLuint handle = mVertexArrayHandleAllocator.allocate();
+
+    mVertexArrayMap[handle] = new VertexArray(mRenderer, handle);
+
+    return handle;
+}
+
 // Returns an unused framebuffer name
 GLuint Context::createFramebuffer()
 {
@@ -844,6 +850,20 @@
     mResourceManager->deleteRenderbuffer(renderbuffer);
 }
 
+void Context::deleteVertexArray(GLuint vertexArray)
+{
+    auto vertexArrayObject = mVertexArrayMap.find(vertexArray);
+
+    if (vertexArrayObject != mVertexArrayMap.end())
+    {
+        detachVertexArray(vertexArray);
+
+        mVertexArrayHandleAllocator.release(vertexArrayObject->first);
+        delete vertexArrayObject->second;
+        mVertexArrayMap.erase(vertexArrayObject);
+    }
+}
+
 void Context::deleteFramebuffer(GLuint framebuffer)
 {
     FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
@@ -909,6 +929,20 @@
     return mResourceManager->getRenderbuffer(handle);
 }
 
+VertexArray *Context::getVertexArray(GLuint handle) const
+{
+    auto vertexArray = mVertexArrayMap.find(handle);
+
+    if (vertexArray == mVertexArrayMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return vertexArray->second;
+    }
+}
+
 Framebuffer *Context::getReadFramebuffer()
 {
     return getFramebuffer(mState.readFramebuffer);
@@ -919,6 +953,13 @@
     return mBoundDrawFramebuffer;
 }
 
+VertexArray *Context::getCurrentVertexArray() const
+{
+    VertexArray *vao = getVertexArray(mState.vertexArray);
+    ASSERT(vao != NULL);
+    return vao;
+}
+
 void Context::bindArrayBuffer(unsigned int buffer)
 {
     mResourceManager->checkBufferAllocation(buffer);
@@ -930,7 +971,7 @@
 {
     mResourceManager->checkBufferAllocation(buffer);
 
-    mState.elementArrayBuffer.set(getBuffer(buffer));
+    getCurrentVertexArray()->setElementArrayBuffer(getBuffer(buffer));
 }
 
 void Context::bindTexture2D(GLuint texture)
@@ -990,6 +1031,16 @@
     mState.renderbuffer.set(getRenderbuffer(renderbuffer));
 }
 
+void Context::bindVertexArray(GLuint vertexArray)
+{
+    if (!getVertexArray(vertexArray))
+    {
+        mVertexArrayMap[vertexArray] = new VertexArray(mRenderer, vertexArray);
+    }
+
+    mState.vertexArray = vertexArray;
+}
+
 void Context::bindGenericUniformBuffer(GLuint buffer)
 {
     mResourceManager->checkBufferAllocation(buffer);
@@ -1286,7 +1337,7 @@
 
 Buffer *Context::getElementArrayBuffer()
 {
-    return mState.elementArrayBuffer.get();
+    return getCurrentVertexArray()->getElementArrayBuffer();
 }
 
 ProgramBinary *Context::getCurrentProgramBinary()
@@ -1483,7 +1534,7 @@
       case GL_NUM_SHADER_BINARY_FORMATS:        *params = 0;                                    break;
       case GL_SHADER_BINARY_FORMATS:      /* no shader binary formats are supported */          break;
       case GL_ARRAY_BUFFER_BINDING:             *params = mState.arrayBuffer.id();              break;
-      case GL_ELEMENT_ARRAY_BUFFER_BINDING:     *params = mState.elementArrayBuffer.id();       break;
+      case GL_ELEMENT_ARRAY_BUFFER_BINDING:     *params = getCurrentVertexArray()->getElementArrayBufferId(); break;
       //case GL_FRAMEBUFFER_BINDING:            // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
       case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE:   *params = mState.drawFramebuffer;               break;
       case GL_READ_FRAMEBUFFER_BINDING_ANGLE:   *params = mState.readFramebuffer;               break;
@@ -2266,7 +2317,7 @@
 
     ProgramBinary *programBinary = getCurrentProgramBinary();
 
-    GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, mState.vertexAttribCurrentValues, first, count, instances);
+    GLenum err = mRenderer->applyVertexBuffer(programBinary, getCurrentVertexArray()->getVertexAttributes(), mState.vertexAttribCurrentValues, first, count, instances);
     if (err != GL_NO_ERROR)
     {
         return gl::error(err);
@@ -2298,7 +2349,8 @@
         return gl::error(GL_INVALID_OPERATION);
     }
 
-    if (!indices && !mState.elementArrayBuffer)
+    VertexArray *vao = getCurrentVertexArray();
+    if (!indices && !vao->getElementArrayBuffer())
     {
         return gl::error(GL_INVALID_OPERATION);
     }
@@ -2316,7 +2368,7 @@
     applyState(mode);
 
     rx::TranslatedIndexData indexInfo;
-    GLenum err = mRenderer->applyIndexBuffer(indices, mState.elementArrayBuffer.get(), count, mode, type, &indexInfo);
+    GLenum err = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo);
     if (err != GL_NO_ERROR)
     {
         return gl::error(err);
@@ -2325,7 +2377,7 @@
     ProgramBinary *programBinary = getCurrentProgramBinary();
 
     GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
-    err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, mState.vertexAttribCurrentValues, indexInfo.minIndex, vertexCount, instances);
+    err = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(), mState.vertexAttribCurrentValues, indexInfo.minIndex, vertexCount, instances);
     if (err != GL_NO_ERROR)
     {
         return gl::error(err);
@@ -2346,7 +2398,7 @@
 
     if (!skipDraw(mode))
     {
-        mRenderer->drawElements(mode, count, type, indices, mState.elementArrayBuffer.get(), indexInfo, instances);
+        mRenderer->drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances);
     }
 }
 
@@ -2666,17 +2718,10 @@
         mState.arrayBuffer.set(NULL);
     }
 
-    if (mState.elementArrayBuffer.id() == buffer)
+    // mark as freed among the vertex array objects
+    for (auto vaoIt = mVertexArrayMap.begin(); vaoIt != mVertexArrayMap.end(); vaoIt++)
     {
-        mState.elementArrayBuffer.set(NULL);
-    }
-
-    for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
-    {
-        if (mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer)
-        {
-            mState.vertexAttribute[attribute].mBoundBuffer.set(NULL);
-        }
+        vaoIt->second->detachBuffer(buffer);
     }
 }
 
@@ -2763,6 +2808,17 @@
     }
 }
 
+void Context::detachVertexArray(GLuint vertexArray)
+{
+    // [OpenGL ES 3.0.2] section 2.10 page 43:
+    // If a vertex array object that is currently bound is deleted, the binding
+    // for that object reverts to zero and the default vertex array becomes current.
+    if (mState.vertexArray == vertexArray)
+    {
+        bindVertexArray(0);
+    }
+}
+
 Texture *Context::getIncompleteTexture(TextureType type)
 {
     Texture *t = mIncompleteTextures[type].get();
@@ -2872,9 +2928,7 @@
 
 void Context::setVertexAttribDivisor(GLuint index, GLuint divisor)
 {
-    ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
-
-    mState.vertexAttribute[index].mDivisor = divisor;
+    getCurrentVertexArray()->setVertexAttribDivisor(index, divisor);
 }
 
 // keep list sorted in following order
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index 0230669..06656ed 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -67,6 +67,8 @@
 class Query;
 class ResourceManager;
 class Buffer;
+class VertexAttribute;
+class VertexArray;
 
 enum QueryType
 {
@@ -108,14 +110,13 @@
 
     unsigned int activeSampler;   // Active texture unit selector - GL_TEXTURE0
     BindingPointer<Buffer> arrayBuffer;
-    BindingPointer<Buffer> elementArrayBuffer;
     GLuint readFramebuffer;
     GLuint drawFramebuffer;
     BindingPointer<Renderbuffer> renderbuffer;
     GLuint currentProgram;
 
     VertexAttribCurrentValueData vertexAttribCurrentValues[MAX_VERTEX_ATTRIBS]; // From glVertexAttrib
-    VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS];
+    unsigned int vertexArray;
 
     BindingPointer<Texture> samplerTexture[TEXTURE_TYPE_COUNT][IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS];
     BindingPointer<Query> activeQuery[QUERY_TYPE_COUNT];
@@ -251,12 +252,14 @@
     GLuint createProgram();
     GLuint createTexture();
     GLuint createRenderbuffer();
+    GLuint createVertexArray();
 
     void deleteBuffer(GLuint buffer);
     void deleteShader(GLuint shader);
     void deleteProgram(GLuint program);
     void deleteTexture(GLuint texture);
     void deleteRenderbuffer(GLuint renderbuffer);
+    void deleteVertexArray(GLuint vertexArray);
 
     // Framebuffers are owned by the Context, so these methods do not pass through
     GLuint createFramebuffer();
@@ -279,6 +282,7 @@
     void bindReadFramebuffer(GLuint framebuffer);
     void bindDrawFramebuffer(GLuint framebuffer);
     void bindRenderbuffer(GLuint renderbuffer);
+    void bindVertexArray(GLuint vertexArray);
     void bindGenericUniformBuffer(GLuint buffer);
     void bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size);
     void bindGenericTransformFeedbackBuffer(GLuint buffer);
@@ -310,6 +314,7 @@
     Texture *getTexture(GLuint handle);
     Framebuffer *getFramebuffer(GLuint handle);
     Renderbuffer *getRenderbuffer(GLuint handle);
+    VertexArray *getVertexArray(GLuint handle) const;
     Query *getQuery(GLuint handle, bool create, GLenum type);
 
     Buffer *getArrayBuffer();
@@ -328,6 +333,7 @@
     Texture *getSamplerTexture(unsigned int sampler, TextureType type);
     Framebuffer *getReadFramebuffer();
     Framebuffer *getDrawFramebuffer();
+    VertexArray *getCurrentVertexArray() const;
 
     bool getFloatv(GLenum pname, GLfloat *params);
     bool getIntegerv(GLenum pname, GLint *params);
@@ -421,6 +427,7 @@
     void detachTexture(GLuint texture);
     void detachFramebuffer(GLuint framebuffer);
     void detachRenderbuffer(GLuint renderbuffer);
+    void detachVertexArray(GLuint vertexArray);
 
     Texture *getIncompleteTexture(TextureType type);
 
@@ -460,6 +467,10 @@
     QueryMap mQueryMap;
     HandleAllocator mQueryHandleAllocator;
 
+    typedef HASH_MAP<GLuint, VertexArray*> VertexArrayMap;
+    VertexArrayMap mVertexArrayMap;
+    HandleAllocator mVertexArrayHandleAllocator;
+
     std::vector<std::string> mExtensionStringList;
     const char *mCombinedExtensionsString;
     const char *mRendererString;
diff --git a/src/libGLESv2/VertexArray.cpp b/src/libGLESv2/VertexArray.cpp
new file mode 100644
index 0000000..d7ec7bf
--- /dev/null
+++ b/src/libGLESv2/VertexArray.cpp
@@ -0,0 +1,67 @@
+#include "precompiled.h"
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Implementation of the state class for mananging GLES 3 Vertex Array Objects.
+//
+
+#include "libGLESv2/VertexArray.h"
+#include "libGLESv2/Buffer.h"
+
+namespace gl
+{
+
+VertexArray::VertexArray(rx::Renderer *renderer, GLuint id)
+    : RefCountObject(id)
+{
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        mVertexAttributes[i].mBoundBuffer.set(NULL);
+    }
+    mElementArrayBuffer.set(NULL);
+}
+
+void VertexArray::detachBuffer(GLuint bufferName)
+{
+    for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
+    {
+        if (mVertexAttributes[attribute].mBoundBuffer.id() == bufferName)
+        {
+            mVertexAttributes[attribute].mBoundBuffer.set(NULL);
+        }
+    }
+
+    if (mElementArrayBuffer.id() == bufferName)
+    {
+        mElementArrayBuffer.set(NULL);
+    }
+}
+
+const VertexAttribute& VertexArray::getVertexAttribute(unsigned int attributeIndex) const
+{
+    ASSERT(attributeIndex < MAX_VERTEX_ATTRIBS);
+    return mVertexAttributes[attributeIndex];
+}
+
+void VertexArray::setVertexAttribDivisor(GLuint index, GLuint divisor)
+{
+    ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
+    mVertexAttributes[index].mDivisor = divisor;
+}
+
+void VertexArray::enableAttribute(unsigned int attributeIndex, bool enabledState)
+{
+    ASSERT(attributeIndex < gl::MAX_VERTEX_ATTRIBS);
+    mVertexAttributes[attributeIndex].mArrayEnabled = enabledState;
+}
+
+void VertexArray::setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type,
+                                    bool normalized, bool pureInteger, GLsizei stride, const void *pointer)
+{
+    ASSERT(attributeIndex < gl::MAX_VERTEX_ATTRIBS);
+    mVertexAttributes[attributeIndex].setState(boundBuffer, size, type, normalized, pureInteger, stride, pointer);
+}
+
+}
\ No newline at end of file
diff --git a/src/libGLESv2/VertexArray.h b/src/libGLESv2/VertexArray.h
new file mode 100644
index 0000000..a1f3039
--- /dev/null
+++ b/src/libGLESv2/VertexArray.h
@@ -0,0 +1,53 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This class contains prototypes for representing GLES 3 Vertex Array Objects:
+//
+//   The buffer objects that are to be used by the vertex stage of the GL are collected
+//   together to form a vertex array object. All state related to the definition of data used
+//   by the vertex processor is encapsulated in a vertex array object.
+//
+
+#ifndef LIBGLESV2_VERTEXARRAY_H_
+#define LIBGLESV2_VERTEXARRAY_H_
+
+#include "common/RefCountObject.h"
+#include "libGLESv2/constants.h"
+#include "libGLESv2/VertexAttribute.h"
+
+namespace rx
+{
+class Renderer;
+}
+
+namespace gl
+{
+class Buffer;
+
+class VertexArray : public RefCountObject
+{
+  public:
+    VertexArray(rx::Renderer *renderer, GLuint id);
+
+    const VertexAttribute& getVertexAttribute(unsigned int attributeIndex) const;
+    void detachBuffer(GLuint bufferName);
+    void setVertexAttribDivisor(GLuint index, GLuint divisor);
+    void enableAttribute(unsigned int attributeIndex, bool enabledState);
+    void setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type,
+                           bool normalized, bool pureInteger, GLsizei stride, const void *pointer);
+
+    const VertexAttribute* getVertexAttributes() const { return mVertexAttributes; }
+    Buffer *getElementArrayBuffer() const { return mElementArrayBuffer.get(); }
+    void setElementArrayBuffer(Buffer *elementArrayBuffer) { mElementArrayBuffer.set(elementArrayBuffer); }
+    GLuint getElementArrayBufferId() const { return mElementArrayBuffer.id(); }
+
+  private:
+    VertexAttribute mVertexAttributes[MAX_VERTEX_ATTRIBS];
+    BindingPointer<Buffer> mElementArrayBuffer;
+};
+
+}
+
+#endif // LIBGLESV2_VERTEXARRAY_H_
diff --git a/src/libGLESv2/VertexAttribute.h b/src/libGLESv2/VertexAttribute.h
index 80e780e..5f2a044 100644
--- a/src/libGLESv2/VertexAttribute.h
+++ b/src/libGLESv2/VertexAttribute.h
@@ -9,11 +9,10 @@
 #ifndef LIBGLESV2_VERTEXATTRIBUTE_H_
 #define LIBGLESV2_VERTEXATTRIBUTE_H_
 
-#include "common/RefCountObject.h"
+#include "libGLESv2/Buffer.h"
 
 namespace gl
 {
-class Buffer;
 
 class VertexAttribute
 {
@@ -47,6 +46,18 @@
         return mStride ? mStride : typeSize();
     }
 
+    void setState(gl::Buffer *boundBuffer, GLint size, GLenum type, bool normalized,
+                  bool pureInteger, GLsizei stride, const void *pointer)
+    {
+        mBoundBuffer.set(boundBuffer);
+        mSize = size;
+        mType = type;
+        mNormalized = normalized;
+        mPureInteger = pureInteger;
+        mStride = stride;
+        mPointer = pointer;
+    }
+
     // From glVertexAttribPointer
     GLenum mType;
     GLint mSize;
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index 72e35ab..e918362 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -21,6 +21,7 @@
 #include "libGLESv2/Texture.h"
 #include "libGLESv2/Query.h"
 #include "libGLESv2/Context.h"
+#include "libGLESv2/VertexArray.h"
 
 bool validImageSize(const gl::Context *context, GLint level, GLsizei width, GLsizei height, GLsizei depth)
 {
diff --git a/src/libGLESv2/libGLESv2.vcxproj b/src/libGLESv2/libGLESv2.vcxproj
index 34f4e50..4c71dd8 100644
--- a/src/libGLESv2/libGLESv2.vcxproj
+++ b/src/libGLESv2/libGLESv2.vcxproj
@@ -313,6 +313,7 @@
     <ClCompile Include="Shader.cpp" />

     <ClCompile Include="Texture.cpp" />

     <ClCompile Include="Uniform.cpp" />

+    <ClCompile Include="VertexArray.cpp" />

   </ItemGroup>

   <ItemGroup>

     <ClInclude Include="..\..\include\GLES2\gl2.h" />

@@ -439,6 +440,7 @@
     <ClInclude Include="Uniform.h" />

     <ClInclude Include="..\common\version.h" />

     <ClInclude Include="VertexAttribute.h" />

+    <ClInclude Include="VertexArray.h" />

   </ItemGroup>

   <ItemGroup>

     <None Include="libGLESv2.def" />

diff --git a/src/libGLESv2/libGLESv2.vcxproj.filters b/src/libGLESv2/libGLESv2.vcxproj.filters
index 00046a2..11993dc 100644
--- a/src/libGLESv2/libGLESv2.vcxproj.filters
+++ b/src/libGLESv2/libGLESv2.vcxproj.filters
@@ -239,6 +239,9 @@
     <ClCompile Include="renderer\Blit11.cpp">

       <Filter>Source Files\Renderer11</Filter>

     </ClCompile>

+    <ClCompile Include="VertexArray.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

   </ItemGroup>

   <ItemGroup>

     <ClInclude Include="BinaryStream.h">

@@ -619,6 +622,9 @@
     <ClInclude Include="VertexAttribute.h">

       <Filter>Header Files</Filter>

     </ClInclude>

+    <ClInclude Include="VertexArray.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

   </ItemGroup>

   <ItemGroup>

     <None Include="renderer\shaders\Blit.ps">

diff --git a/src/libGLESv2/renderer/Renderer.h b/src/libGLESv2/renderer/Renderer.h
index a16efb5..8836d56 100644
--- a/src/libGLESv2/renderer/Renderer.h
+++ b/src/libGLESv2/renderer/Renderer.h
@@ -131,7 +131,7 @@
     virtual void applyShaders(gl::ProgramBinary *programBinary) = 0;
     virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) = 0;
     virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0;
-    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
+    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
                                      GLint first, GLsizei count, GLsizei instances) = 0;
     virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0;
 
diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp
index 95b589d..287efdd 100644
--- a/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/libGLESv2/renderer/Renderer11.cpp
@@ -1034,7 +1034,7 @@
     return true;
 }
 
-GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
+GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
                                      GLint first, GLsizei count, GLsizei instances)
 {
     TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
diff --git a/src/libGLESv2/renderer/Renderer11.h b/src/libGLESv2/renderer/Renderer11.h
index 92a3eef..10af628 100644
--- a/src/libGLESv2/renderer/Renderer11.h
+++ b/src/libGLESv2/renderer/Renderer11.h
@@ -74,7 +74,7 @@
     virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
     virtual void applyShaders(gl::ProgramBinary *programBinary);
     virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray);
-    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
+    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
                                      GLint first, GLsizei count, GLsizei instances);
     virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
 
diff --git a/src/libGLESv2/renderer/Renderer9.cpp b/src/libGLESv2/renderer/Renderer9.cpp
index 5bb1cae..6519984 100644
--- a/src/libGLESv2/renderer/Renderer9.cpp
+++ b/src/libGLESv2/renderer/Renderer9.cpp
@@ -1338,7 +1338,7 @@
     return true;
 }
 
-GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
+GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
                                     GLint first, GLsizei count, GLsizei instances)
 {
     TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
diff --git a/src/libGLESv2/renderer/Renderer9.h b/src/libGLESv2/renderer/Renderer9.h
index fe607ba..d758972 100644
--- a/src/libGLESv2/renderer/Renderer9.h
+++ b/src/libGLESv2/renderer/Renderer9.h
@@ -88,7 +88,7 @@
     virtual void applyShaders(gl::ProgramBinary *programBinary);
     virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray);
     virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount);
-    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
+    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
                                      GLint first, GLsizei count, GLsizei instances);
     virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
 
diff --git a/src/libGLESv2/renderer/VertexDataManager.h b/src/libGLESv2/renderer/VertexDataManager.h
index b442c46..eadf584 100644
--- a/src/libGLESv2/renderer/VertexDataManager.h
+++ b/src/libGLESv2/renderer/VertexDataManager.h
@@ -18,6 +18,7 @@
 {
 class VertexAttribute;
 class ProgramBinary;
+struct VertexAttribCurrentValueData;
 }
 
 namespace rx