Moved D3DConstantTable, IndexDataManager, VertexDataManager and vertexconversion files.

TRAC #22198

Signed-off-by: Nicolas Capens
Signed-off-by: Daniel Koch

git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1547 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/renderer/D3DConstantTable.cpp b/src/libGLESv2/renderer/D3DConstantTable.cpp
new file mode 100644
index 0000000..10a0f9d
--- /dev/null
+++ b/src/libGLESv2/renderer/D3DConstantTable.cpp
@@ -0,0 +1,231 @@
+//
+// Copyright (c) 2012 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.
+//
+
+// D3DConstantTable.cpp: Implements the D3DConstantTable class which parses
+// information about constants from the CTAB comment in a D3D shader blob.
+// Restructures the constant table as a hierarchy of constants in the same
+// way as D3DX.
+
+#include "libGLESv2/renderer/D3DConstantTable.h"
+
+#include <d3d9.h>
+#include <d3d9types.h>
+#include <windows.h>
+#include <mmsystem.h>
+
+#include "libGLESv2/BinaryStream.h"
+
+const static int SHADER_VERSION_MASK = D3DVS_VERSION(0, 0);
+const static int FOURCC_CTAB = MAKEFOURCC('C','T','A','B');
+
+namespace gl
+{
+// These structs and constants correspond to the format of the constant table in a shader binary.
+// They match the corresponding structures in d3dx9shader.h.
+namespace ctab
+{
+struct ConstantTable
+{
+    DWORD size;
+    DWORD creator;
+    DWORD version;
+    DWORD constants;
+    DWORD constantInfos;
+    DWORD flags;
+    DWORD target;
+};
+
+struct ConstantInfo
+{
+    DWORD name;
+    WORD registerSet;
+    WORD registerIndex;
+    WORD registerCount;
+    WORD reserved;
+    DWORD typeInfo;
+    DWORD defaultValue;
+};
+
+struct TypeInfo
+{
+    WORD typeClass;
+    WORD type;
+    WORD rows;
+    WORD columns;
+    WORD elements;
+    WORD structMembers;
+    DWORD structMemberInfos;
+};
+
+struct StructMemberInfo
+{
+    DWORD name;
+    DWORD typeInfo;
+};
+}
+
+D3DConstant::D3DConstant(const char *base, const ctab::ConstantInfo *constantInfo)
+{
+    const ctab::TypeInfo *typeInfo = reinterpret_cast<const ctab::TypeInfo*>(base + constantInfo->typeInfo);
+
+    name = base + constantInfo->name;
+    registerSet = static_cast<RegisterSet>(constantInfo->registerSet);
+    registerIndex = constantInfo->registerIndex;
+    registerCount = constantInfo->registerCount;
+    typeClass = static_cast<Class>(typeInfo->typeClass);
+    type = static_cast<Type>(typeInfo->type);
+    rows = typeInfo->rows;
+    columns = typeInfo->columns;
+    elements = typeInfo->elements;
+
+    if (typeClass == CLASS_STRUCT)
+    {
+        addStructMembers(base, registerSet, registerIndex, typeInfo);
+    }
+}
+
+D3DConstant::D3DConstant(const char *base, RegisterSet registerSet, unsigned registerIndex, const ctab::StructMemberInfo *memberInfo)
+    : registerSet(registerSet), registerIndex(registerIndex)
+{
+    const ctab::TypeInfo *typeInfo = reinterpret_cast<const ctab::TypeInfo*>(base + memberInfo->typeInfo);
+
+    name = base + memberInfo->name;
+    registerCount = typeInfo->rows * typeInfo->elements;
+    typeClass = static_cast<Class>(typeInfo->typeClass);
+    type = static_cast<Type>(typeInfo->type);
+    rows = typeInfo->rows;
+    columns = typeInfo->columns;
+    elements = typeInfo->elements;
+
+    if (typeClass == CLASS_STRUCT)
+    {
+        registerCount = addStructMembers(base, registerSet, registerIndex, typeInfo);
+    }
+}
+
+D3DConstant::~D3DConstant()
+{
+    for (size_t j = 0; j < structMembers.size(); ++j)
+    {
+        for (size_t i = 0; i < structMembers[j].size(); ++i)
+        {
+            delete structMembers[j][i];
+        }
+    }
+}
+
+unsigned D3DConstant::addStructMembers(const char *base, RegisterSet registerSet, unsigned registerIndex, const ctab::TypeInfo *typeInfo)
+{
+    const ctab::StructMemberInfo *memberInfos = reinterpret_cast<const ctab::StructMemberInfo*>(
+        base + typeInfo->structMemberInfos);
+
+    unsigned memberIndex = registerIndex;
+
+    structMembers.resize(elements);
+
+    for (unsigned j = 0; j < elements; ++j)
+    {
+        structMembers[j].resize(typeInfo->structMembers);
+
+        for (unsigned i = 0; i < typeInfo->structMembers; ++i)
+        {
+            const ctab::TypeInfo *memberTypeInfo = reinterpret_cast<const ctab::TypeInfo*>(
+                base + memberInfos[i].typeInfo);
+
+            D3DConstant *member = new D3DConstant(base, registerSet, memberIndex, memberInfos + i);
+            memberIndex += member->registerCount;
+
+            structMembers[j][i] = member;
+        }
+    }
+
+    return memberIndex - registerIndex;
+}
+
+D3DConstantTable::D3DConstantTable(void *blob, size_t size) : mError(false)
+{
+    BinaryInputStream stream(blob, size);
+
+    int version;
+    stream.read(&version);
+    if ((version & SHADER_VERSION_MASK) != SHADER_VERSION_MASK)
+    {
+        mError = true;
+        return;
+    }
+
+    const ctab::ConstantTable* constantTable = NULL;
+
+    while (!stream.error())
+    {
+        int token;
+        stream.read(&token);
+
+        if ((token & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
+        {
+            size_t length = ((token & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT) * sizeof(DWORD);
+
+            int fourcc;
+            stream.read(&fourcc);
+            if (fourcc == FOURCC_CTAB)
+            {
+                constantTable = reinterpret_cast<const ctab::ConstantTable*>(static_cast<const char*>(blob) + stream.offset());
+                break;
+            }
+
+            stream.skip(length - sizeof(fourcc));
+        }
+        else if (token == D3DSIO_END)
+        {
+            break;
+        }
+    }
+
+    mError = !constantTable || stream.error();
+    if (mError)
+    {
+        return;
+    }
+
+    const char *base = reinterpret_cast<const char*>(constantTable);
+
+    mConstants.resize(constantTable->constants);
+    const ctab::ConstantInfo *constantInfos =
+        reinterpret_cast<const ctab::ConstantInfo*>(base + constantTable->constantInfos);
+    for (size_t i = 0; i < constantTable->constants; ++i)
+    {
+        mConstants[i] = new D3DConstant(base, constantInfos + i);
+    }
+}
+
+D3DConstantTable::~D3DConstantTable()
+{
+    for (size_t i = 0; i < mConstants.size(); ++i)
+    {
+        delete mConstants[i];
+    }
+}
+
+const D3DConstant *D3DConstantTable::getConstant(unsigned index) const
+{
+    return mConstants[index];
+}
+
+const D3DConstant *D3DConstantTable::getConstantByName(const char *name) const
+{
+    for (size_t i = 0; i < mConstants.size(); ++i)
+    {
+        const D3DConstant *constant = getConstant(i);
+        if (constant->name == name)
+        {
+            return constant;
+        }
+    }
+
+    return NULL;
+}
+
+}
diff --git a/src/libGLESv2/renderer/D3DConstantTable.h b/src/libGLESv2/renderer/D3DConstantTable.h
new file mode 100644
index 0000000..c2c8e9f
--- /dev/null
+++ b/src/libGLESv2/renderer/D3DConstantTable.h
@@ -0,0 +1,117 @@
+//
+// Copyright (c) 2012 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.
+//
+
+// D3DConstantTable.h: Implements the D3DConstantTable class which parses
+// information about constants from the CTAB comment in a D3D shader blob.
+// Restructures the constant table as a hierarchy of constants in the same
+// way as D3DX.
+
+#ifndef LIBGLESV2_D3DCONSTANTTABLE_H_
+#define LIBGLESV2_D3DCONSTANTTABLE_H_
+
+#include <vector>
+#include <string>
+
+#include "common/angleutils.h"
+
+namespace gl
+{
+
+namespace ctab
+{
+struct ConstantTable;
+struct ConstantInfo;
+struct TypeInfo;
+struct StructMemberInfo;
+}
+
+struct D3DConstant
+{
+    // These enums match those in d3dx9shader.h.
+    enum Class
+    {
+        CLASS_SCALAR,
+        CLASS_VECTOR,
+        CLASS_MATRIX_ROWS,
+        CLASS_MATRIX_COLUMNS,
+        CLASS_OBJECT,
+        CLASS_STRUCT,
+    };
+
+    enum RegisterSet
+    {
+        RS_BOOL,
+        RS_INT4,
+        RS_FLOAT4,
+        RS_SAMPLER,
+    };
+
+    enum Type
+    {
+        PT_VOID,
+        PT_BOOL,
+        PT_INT,
+        PT_FLOAT,
+        PT_STRING,
+        PT_TEXTURE,
+        PT_TEXTURE1D,
+        PT_TEXTURE2D,
+        PT_TEXTURE3D,
+        PT_TEXTURECUBE,
+        PT_SAMPLER,
+        PT_SAMPLER1D,
+        PT_SAMPLER2D,
+        PT_SAMPLER3D,
+        PT_SAMPLERCUBE,
+        PT_PIXELSHADER,
+        PT_VERTEXSHADER,
+        PT_PIXELFRAGMENT,
+        PT_VERTEXFRAGMENT,
+        PT_UNSUPPORTED,
+    };
+
+    D3DConstant(const char *base, const ctab::ConstantInfo *constantInfo);
+    ~D3DConstant();
+
+    std::string name;
+    RegisterSet registerSet;
+    unsigned registerIndex;
+    unsigned registerCount;
+    Class typeClass;
+    Type type;
+    unsigned rows;
+    unsigned columns;
+    unsigned elements;
+
+    // Array of structure members.
+    std::vector<std::vector<const D3DConstant*> > structMembers;
+
+  private:
+    D3DConstant(const char *base, RegisterSet registerSet, unsigned registerIndex, const ctab::StructMemberInfo *memberInfo);
+    unsigned addStructMembers(const char *base, RegisterSet registerSet, unsigned registerIndex, const ctab::TypeInfo *typeInfo);
+};
+
+class D3DConstantTable
+{
+  public:
+    D3DConstantTable(void *blob, size_t size);
+    ~D3DConstantTable();
+
+    bool error() const { return mError; }
+
+    unsigned constants() const { return mConstants.size(); }
+    const D3DConstant *getConstant(unsigned index) const;
+    const D3DConstant *getConstantByName(const char *name) const;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(D3DConstantTable);
+    std::vector<const D3DConstant*> mConstants;
+    bool mError;
+};
+
+}
+
+#endif   // LIBGLESV2_D3DCONSTANTTABLE_H_
diff --git a/src/libGLESv2/renderer/IndexDataManager.cpp b/src/libGLESv2/renderer/IndexDataManager.cpp
new file mode 100644
index 0000000..272478f
--- /dev/null
+++ b/src/libGLESv2/renderer/IndexDataManager.cpp
@@ -0,0 +1,473 @@
+//
+// Copyright (c) 2002-2012 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.
+//
+
+// IndexDataManager.cpp: Defines the IndexDataManager, a class that
+// runs the Buffer translation process for index buffers.
+
+#include "libGLESv2/renderer/IndexDataManager.h"
+
+#include "common/debug.h"
+
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/main.h"
+
+namespace gl
+{
+unsigned int IndexBuffer::mCurrentSerial = 1;
+
+IndexDataManager::IndexDataManager(rx::Renderer9 *renderer) : mRenderer(renderer)
+{
+    mStreamingBufferShort = new StreamingIndexBuffer(mRenderer, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
+
+    if (renderer->get32BitIndexSupport())
+    {
+        mStreamingBufferInt = new StreamingIndexBuffer(mRenderer, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
+
+        if (!mStreamingBufferInt)
+        {
+            // Don't leave it in a half-initialized state
+            delete mStreamingBufferShort;
+            mStreamingBufferShort = NULL;
+        }
+    }
+    else
+    {
+        mStreamingBufferInt = NULL;
+    }
+
+    if (!mStreamingBufferShort)
+    {
+        ERR("Failed to allocate the streaming index buffer(s).");
+    }
+
+    mCountingBuffer = NULL;
+}
+
+IndexDataManager::~IndexDataManager()
+{
+    delete mStreamingBufferShort;
+    delete mStreamingBufferInt;
+    delete mCountingBuffer;
+}
+
+void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
+{
+    if (type == GL_UNSIGNED_BYTE)
+    {
+        const GLubyte *in = static_cast<const GLubyte*>(input);
+        GLushort *out = static_cast<GLushort*>(output);
+
+        for (GLsizei i = 0; i < count; i++)
+        {
+            out[i] = in[i];
+        }
+    }
+    else if (type == GL_UNSIGNED_INT)
+    {
+        memcpy(output, input, count * sizeof(GLuint));
+    }
+    else if (type == GL_UNSIGNED_SHORT)
+    {
+        memcpy(output, input, count * sizeof(GLushort));
+    }
+    else UNREACHABLE();
+}
+
+template <class IndexType>
+void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
+{
+    *minIndex = indices[0];
+    *maxIndex = indices[0];
+
+    for (GLsizei i = 0; i < count; i++)
+    {
+        if (*minIndex > indices[i]) *minIndex = indices[i];
+        if (*maxIndex < indices[i]) *maxIndex = indices[i];
+    }
+}
+
+void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
+{
+    if (type == GL_UNSIGNED_BYTE)
+    {
+        computeRange(static_cast<const GLubyte*>(indices), count, minIndex, maxIndex);
+    }
+    else if (type == GL_UNSIGNED_INT)
+    {
+        computeRange(static_cast<const GLuint*>(indices), count, minIndex, maxIndex);
+    }
+    else if (type == GL_UNSIGNED_SHORT)
+    {
+        computeRange(static_cast<const GLushort*>(indices), count, minIndex, maxIndex);
+    }
+    else UNREACHABLE();
+}
+
+GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated, IDirect3DIndexBuffer9 **d3dIndexBuffer, unsigned int *serial)
+{
+    if (!mStreamingBufferShort)
+    {
+        return GL_OUT_OF_MEMORY;
+    }
+
+    D3DFORMAT format = (type == GL_UNSIGNED_INT) ? D3DFMT_INDEX32 : D3DFMT_INDEX16;
+    intptr_t offset = reinterpret_cast<intptr_t>(indices);
+    bool alignedOffset = false;
+
+    if (buffer != NULL)
+    {
+        switch (type)
+        {
+          case GL_UNSIGNED_BYTE:  alignedOffset = (offset % sizeof(GLubyte) == 0);  break;
+          case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break;
+          case GL_UNSIGNED_INT:   alignedOffset = (offset % sizeof(GLuint) == 0);   break;
+          default: UNREACHABLE(); alignedOffset = false;
+        }
+
+        if (typeSize(type) * count + offset > static_cast<std::size_t>(buffer->size()))
+        {
+            return GL_INVALID_OPERATION;
+        }
+
+        indices = static_cast<const GLubyte*>(buffer->data()) + offset;
+    }
+
+    StreamingIndexBuffer *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort;
+
+    StaticIndexBuffer *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL;
+    IndexBuffer *indexBuffer = streamingBuffer;
+    UINT streamOffset = 0;
+
+    if (staticBuffer && staticBuffer->lookupType(type) && alignedOffset)
+    {
+        indexBuffer = staticBuffer;
+        streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex);
+
+        if (streamOffset == -1)
+        {
+            streamOffset = (offset / typeSize(type)) * indexSize(format);
+            computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
+            staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
+        }
+    }
+    else
+    {
+        int convertCount = count;
+
+        if (staticBuffer)
+        {
+            if (staticBuffer->size() == 0 && alignedOffset)
+            {
+                indexBuffer = staticBuffer;
+                convertCount = buffer->size() / typeSize(type);
+            }
+            else
+            {
+                buffer->invalidateStaticData();
+                staticBuffer = NULL;
+            }
+        }
+
+        void *output = NULL;
+
+        if (indexBuffer)
+        {
+            indexBuffer->reserveSpace(convertCount * indexSize(format), type);
+            output = indexBuffer->map(indexSize(format) * convertCount, &streamOffset);
+        }
+
+        if (output == NULL)
+        {
+            ERR("Failed to map index buffer.");
+            return GL_OUT_OF_MEMORY;
+        }
+
+        convertIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output);
+        indexBuffer->unmap();
+
+        computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
+
+        if (staticBuffer)
+        {
+            streamOffset = (offset / typeSize(type)) * indexSize(format);
+            staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
+        }
+    }
+
+    *d3dIndexBuffer = indexBuffer->getBuffer();
+    *serial = indexBuffer->getSerial();
+    translated->startIndex = streamOffset / indexSize(format);
+
+    if (buffer)
+    {
+        buffer->promoteStaticUsage(count * typeSize(type));
+    }
+
+    return GL_NO_ERROR;
+}
+
+std::size_t IndexDataManager::indexSize(D3DFORMAT format) const
+{
+    return (format == D3DFMT_INDEX32) ? sizeof(unsigned int) : sizeof(unsigned short);
+}
+
+std::size_t IndexDataManager::typeSize(GLenum type) const
+{
+    switch (type)
+    {
+      case GL_UNSIGNED_INT:   return sizeof(GLuint);
+      case GL_UNSIGNED_SHORT: return sizeof(GLushort);
+      case GL_UNSIGNED_BYTE:  return sizeof(GLubyte);
+      default: UNREACHABLE(); return sizeof(GLushort);
+    }
+}
+
+StaticIndexBuffer *IndexDataManager::getCountingIndices(GLsizei count)
+{
+    if (count <= 65536)   // 16-bit indices
+    {
+        const unsigned int spaceNeeded = count * sizeof(unsigned short);
+
+        if (!mCountingBuffer || mCountingBuffer->size() < spaceNeeded)
+        {
+            delete mCountingBuffer;
+            mCountingBuffer = new StaticIndexBuffer(mRenderer);
+            mCountingBuffer->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
+
+            UINT offset;
+            unsigned short *data = static_cast<unsigned short*>(mCountingBuffer->map(spaceNeeded, &offset));
+
+            if (data)
+            {
+                for(int i = 0; i < count; i++)
+                {
+                    data[i] = i;
+                }
+
+                mCountingBuffer->unmap();
+            }
+        }
+    }
+    else if (mStreamingBufferInt)   // 32-bit indices supported
+    {
+        const unsigned int spaceNeeded = count * sizeof(unsigned int);
+
+        if (!mCountingBuffer || mCountingBuffer->size() < spaceNeeded)
+        {
+            delete mCountingBuffer;
+            mCountingBuffer = new StaticIndexBuffer(mRenderer);
+            mCountingBuffer->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
+
+            UINT offset;
+            unsigned int *data = static_cast<unsigned int*>(mCountingBuffer->map(spaceNeeded, &offset));
+
+            if (data)
+            {
+                for(int i = 0; i < count; i++)
+                {
+                    data[i] = i;
+                }
+
+                mCountingBuffer->unmap();
+            }
+        }
+    }
+    else return NULL;
+
+    return mCountingBuffer;
+}
+
+IndexBuffer::IndexBuffer(rx::Renderer9 *renderer, UINT size, D3DFORMAT format) : mRenderer(renderer), mBufferSize(size), mIndexBuffer(NULL)
+{
+    if (size > 0)
+    {
+        // D3D9_REPLACE
+        HRESULT result = mRenderer->createIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, &mIndexBuffer);
+        mSerial = issueSerial();
+
+        if (FAILED(result))
+        {
+            ERR("Out of memory allocating an index buffer of size %lu.", size);
+        }
+    }
+}
+
+IndexBuffer::~IndexBuffer()
+{
+    if (mIndexBuffer)
+    {
+        mIndexBuffer->Release();
+    }
+}
+
+IDirect3DIndexBuffer9 *IndexBuffer::getBuffer() const
+{
+    return mIndexBuffer;
+}
+
+unsigned int IndexBuffer::getSerial() const
+{
+    return mSerial;
+}
+
+unsigned int IndexBuffer::issueSerial()
+{
+    return mCurrentSerial++;
+}
+
+void IndexBuffer::unmap()
+{
+    if (mIndexBuffer)
+    {
+        mIndexBuffer->Unlock();
+    }
+}
+
+StreamingIndexBuffer::StreamingIndexBuffer(rx::Renderer9 *renderer, UINT initialSize, D3DFORMAT format) : IndexBuffer(renderer, initialSize, format)
+{
+    mWritePosition = 0;
+}
+
+StreamingIndexBuffer::~StreamingIndexBuffer()
+{
+}
+
+void *StreamingIndexBuffer::map(UINT requiredSpace, UINT *offset)
+{
+    void *mapPtr = NULL;
+
+    if (mIndexBuffer)
+    {
+        HRESULT result = mIndexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE);
+
+        if (FAILED(result))
+        {
+            ERR(" Lock failed with error 0x%08x", result);
+            return NULL;
+        }
+
+        *offset = mWritePosition;
+        mWritePosition += requiredSpace;
+    }
+
+    return mapPtr;
+}
+
+void StreamingIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
+{
+    if (requiredSpace > mBufferSize)
+    {
+        if (mIndexBuffer)
+        {
+            mIndexBuffer->Release();
+            mIndexBuffer = NULL;
+        }
+
+        mBufferSize = std::max(requiredSpace, 2 * mBufferSize);
+
+        // D3D9_REPLACE
+        HRESULT result = mRenderer->createIndexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, &mIndexBuffer);
+        mSerial = issueSerial();
+
+        if (FAILED(result))
+        {
+            ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
+        }
+
+        mWritePosition = 0;
+    }
+    else if (mWritePosition + requiredSpace > mBufferSize)   // Recycle
+    {
+        void *dummy;
+        mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
+        mIndexBuffer->Unlock();
+
+        mWritePosition = 0;
+    }
+}
+
+StaticIndexBuffer::StaticIndexBuffer(rx::Renderer9 *renderer) : IndexBuffer(renderer, 0, D3DFMT_UNKNOWN)
+{
+    mCacheType = GL_NONE;
+}
+
+StaticIndexBuffer::~StaticIndexBuffer()
+{
+}
+
+void *StaticIndexBuffer::map(UINT requiredSpace, UINT *offset)
+{
+    void *mapPtr = NULL;
+
+    if (mIndexBuffer)
+    {
+        HRESULT result = mIndexBuffer->Lock(0, requiredSpace, &mapPtr, 0);
+
+        if (FAILED(result))
+        {
+            ERR(" Lock failed with error 0x%08x", result);
+            return NULL;
+        }
+
+        *offset = 0;
+    }
+
+    return mapPtr;
+}
+
+void StaticIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
+{
+    if (!mIndexBuffer && mBufferSize == 0)
+    {
+        // D3D9_REPLACE
+        HRESULT result = mRenderer->createIndexBuffer(requiredSpace, D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, &mIndexBuffer);
+        mSerial = issueSerial();
+
+        if (FAILED(result))
+        {
+            ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
+        }
+
+        mBufferSize = requiredSpace;
+        mCacheType = type;
+    }
+    else if (mIndexBuffer && mBufferSize >= requiredSpace && mCacheType == type)
+    {
+        // Already allocated
+    }
+    else UNREACHABLE();   // Static index buffers can't be resized
+}
+
+bool StaticIndexBuffer::lookupType(GLenum type)
+{
+    return mCacheType == type;
+}
+
+UINT StaticIndexBuffer::lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex)
+{
+    IndexRange range = {offset, count};
+
+    std::map<IndexRange, IndexResult>::iterator res = mCache.find(range);
+
+    if (res == mCache.end())
+    {
+        return -1;
+    }
+
+    *minIndex = res->second.minIndex;
+    *maxIndex = res->second.maxIndex;
+    return res->second.streamOffset;
+}
+
+void StaticIndexBuffer::addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset)
+{
+    IndexRange indexRange = {offset, count};
+    IndexResult indexResult = {minIndex, maxIndex, streamOffset};
+    mCache[indexRange] = indexResult;
+}
+
+}
diff --git a/src/libGLESv2/renderer/IndexDataManager.h b/src/libGLESv2/renderer/IndexDataManager.h
new file mode 100644
index 0000000..6e4a6e4
--- /dev/null
+++ b/src/libGLESv2/renderer/IndexDataManager.h
@@ -0,0 +1,146 @@
+//
+// Copyright (c) 2002-2012 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.
+//
+
+// IndexDataManager.h: Defines the IndexDataManager, a class that
+// runs the Buffer translation process for index buffers.
+
+#ifndef LIBGLESV2_INDEXDATAMANAGER_H_
+#define LIBGLESV2_INDEXDATAMANAGER_H_
+
+#include <vector>
+#include <cstddef>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include "libGLESv2/Context.h"
+
+namespace
+{
+    enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
+}
+
+namespace gl
+{
+
+struct TranslatedIndexData
+{
+    UINT minIndex;
+    UINT maxIndex;
+    UINT startIndex;
+};
+
+class IndexBuffer
+{
+  public:
+    IndexBuffer(rx::Renderer9 *renderer, UINT size, D3DFORMAT format);
+    virtual ~IndexBuffer();
+
+    UINT size() const { return mBufferSize; }
+    virtual void *map(UINT requiredSpace, UINT *offset) = 0;
+    void unmap();
+    virtual void reserveSpace(UINT requiredSpace, GLenum type) = 0;
+
+    IDirect3DIndexBuffer9 *getBuffer() const;
+    unsigned int getSerial() const;
+
+  protected:
+    rx::Renderer9 *const mRenderer;   // D3D9_REPLACE
+
+    IDirect3DIndexBuffer9 *mIndexBuffer;
+    UINT mBufferSize;
+
+    unsigned int mSerial;
+    static unsigned int issueSerial();
+    static unsigned int mCurrentSerial;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(IndexBuffer);
+};
+
+class StreamingIndexBuffer : public IndexBuffer
+{
+  public:
+    StreamingIndexBuffer(rx::Renderer9 *renderer, UINT initialSize, D3DFORMAT format);
+    ~StreamingIndexBuffer();
+
+    virtual void *map(UINT requiredSpace, UINT *offset);
+    virtual void reserveSpace(UINT requiredSpace, GLenum type);
+
+  private:
+    UINT mWritePosition;
+};
+
+class StaticIndexBuffer : public IndexBuffer
+{
+  public:
+    explicit StaticIndexBuffer(rx::Renderer9 *renderer);
+    ~StaticIndexBuffer();
+
+    virtual void *map(UINT requiredSpace, UINT *offset);
+    virtual void reserveSpace(UINT requiredSpace, GLenum type);
+
+    bool lookupType(GLenum type);
+    UINT lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex);   // Returns the offset into the index buffer, or -1 if not found
+    void addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset);
+
+  private:
+    GLenum mCacheType;
+
+    struct IndexRange
+    {
+        intptr_t offset;
+        GLsizei count;
+
+        bool operator<(const IndexRange& rhs) const
+        {
+            if (offset != rhs.offset)
+            {
+                return offset < rhs.offset;
+            }
+            if (count != rhs.count)
+            {
+                return count < rhs.count;
+            }
+            return false;
+        }
+    };
+
+    struct IndexResult
+    {
+        UINT minIndex;
+        UINT maxIndex;
+        UINT streamOffset;
+    };
+
+    std::map<IndexRange, IndexResult> mCache;
+};
+
+class IndexDataManager
+{
+  public:
+    IndexDataManager(rx::Renderer9 *renderer);
+    virtual ~IndexDataManager();
+
+    GLenum prepareIndexData(GLenum type, GLsizei count, Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated, IDirect3DIndexBuffer9 **indexBuffer, unsigned int *serial);
+    StaticIndexBuffer *getCountingIndices(GLsizei count);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(IndexDataManager);
+
+    std::size_t typeSize(GLenum type) const;
+    std::size_t indexSize(D3DFORMAT format) const;
+
+    rx::Renderer9 *const mRenderer;   // D3D9_REPLACE
+
+    StreamingIndexBuffer *mStreamingBufferShort;
+    StreamingIndexBuffer *mStreamingBufferInt;
+    StaticIndexBuffer *mCountingBuffer;
+};
+
+}
+
+#endif   // LIBGLESV2_INDEXDATAMANAGER_H_
diff --git a/src/libGLESv2/renderer/Renderer9.cpp b/src/libGLESv2/renderer/Renderer9.cpp
index 6e82f0f..41ab0ab 100644
--- a/src/libGLESv2/renderer/Renderer9.cpp
+++ b/src/libGLESv2/renderer/Renderer9.cpp
@@ -14,8 +14,8 @@
 #include "libGLESv2/Framebuffer.h"
 #include "libGLESv2/Program.h"
 #include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/IndexDataManager.h"
-#include "libGLESv2/VertexDataManager.h"
+#include "libGLESv2/renderer/IndexDataManager.h"
+#include "libGLESv2/renderer/VertexDataManager.h"
 #include "libGLESv2/renderer/Renderer9.h"
 #include "libGLESv2/renderer/renderer9_utils.h"
 #include "libGLESv2/renderer/ShaderExecutable9.h"
diff --git a/src/libGLESv2/renderer/Renderer9.h b/src/libGLESv2/renderer/Renderer9.h
index ce0eb02..15f3623 100644
--- a/src/libGLESv2/renderer/Renderer9.h
+++ b/src/libGLESv2/renderer/Renderer9.h
@@ -26,7 +26,7 @@
 #include "libGLESv2/renderer/ShaderCache.h"
 #include "libGLESv2/renderer/VertexDeclarationCache.h"
 #include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/IndexDataManager.h"
+#include "libGLESv2/renderer/IndexDataManager.h"
 
 namespace gl
 {
diff --git a/src/libGLESv2/renderer/ShaderExecutable.h b/src/libGLESv2/renderer/ShaderExecutable.h
index bce6708..cbb30ee 100644
--- a/src/libGLESv2/renderer/ShaderExecutable.h
+++ b/src/libGLESv2/renderer/ShaderExecutable.h
@@ -11,7 +11,7 @@
 #define LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_
 
 #include "common/angleutils.h"
-#include "libGLESv2/D3DConstantTable.h"
+#include "libGLESv2/renderer/D3DConstantTable.h"
 
 namespace rx
 {
diff --git a/src/libGLESv2/renderer/ShaderExecutable9.h b/src/libGLESv2/renderer/ShaderExecutable9.h
index e3802d6..d5d3f93 100644
--- a/src/libGLESv2/renderer/ShaderExecutable9.h
+++ b/src/libGLESv2/renderer/ShaderExecutable9.h
@@ -13,7 +13,7 @@
 #include <d3d9.h>
 
 #include "libGLESv2/renderer/ShaderExecutable.h"
-#include "libGLESv2/D3DConstantTable.h"
+#include "libGLESv2/renderer/D3DConstantTable.h"
 
 namespace rx
 {
diff --git a/src/libGLESv2/renderer/VertexDataManager.cpp b/src/libGLESv2/renderer/VertexDataManager.cpp
new file mode 100644
index 0000000..da43a67
--- /dev/null
+++ b/src/libGLESv2/renderer/VertexDataManager.cpp
@@ -0,0 +1,792 @@
+//
+// Copyright (c) 2002-2012 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.
+//
+
+// VertexDataManager.h: Defines the VertexDataManager, a class that
+// runs the Buffer translation process.
+
+#include "libGLESv2/renderer/VertexDataManager.h"
+
+#include "common/debug.h"
+
+#include "libGLESv2/renderer/Renderer9.h"
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/main.h"
+
+#include "libGLESv2/renderer/vertexconversion.h"
+#include "libGLESv2/renderer/IndexDataManager.h"
+
+#include <limits>
+
+namespace
+{
+    enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 };
+    // This has to be at least 4k or else it fails on ATI cards.
+    enum { CONSTANT_VERTEX_BUFFER_SIZE = 4096 };
+}
+
+namespace gl
+{
+unsigned int VertexBuffer::mCurrentSerial = 1;
+
+int elementsInBuffer(const VertexAttribute &attribute, int size)
+{
+    int stride = attribute.stride();
+    return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride;
+}
+
+VertexDataManager::VertexDataManager(rx::Renderer9 *renderer) : mRenderer(renderer)
+{
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        mCurrentValue[i][0] = std::numeric_limits<float>::quiet_NaN();
+        mCurrentValue[i][1] = std::numeric_limits<float>::quiet_NaN();
+        mCurrentValue[i][2] = std::numeric_limits<float>::quiet_NaN();
+        mCurrentValue[i][3] = std::numeric_limits<float>::quiet_NaN();
+        mCurrentValueBuffer[i] = NULL;
+        mCurrentValueOffsets[i] = 0;
+    }
+
+    // D3D9_REPLACE
+    checkVertexCaps(renderer->getCapsDeclTypes());
+
+    mStreamingBuffer = new StreamingVertexBuffer(renderer, INITIAL_STREAM_BUFFER_SIZE);
+
+    if (!mStreamingBuffer)
+    {
+        ERR("Failed to allocate the streaming vertex buffer.");
+    }
+}
+
+VertexDataManager::~VertexDataManager()
+{
+    delete mStreamingBuffer;
+
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        delete mCurrentValueBuffer[i];
+    }
+}
+
+std::size_t VertexDataManager::writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute, GLsizei instances)
+{
+    Buffer *buffer = attribute.mBoundBuffer.get();
+
+    int inputStride = attribute.stride();
+    int elementSize = attribute.typeSize();
+    const FormatConverter &converter = formatConverter(attribute);
+    std::size_t streamOffset = 0;
+
+    void *output = NULL;
+
+    if (vertexBuffer)
+    {
+        output = vertexBuffer->map(attribute, spaceRequired(attribute, count, instances), &streamOffset);
+    }
+
+    if (output == NULL)
+    {
+        ERR("Failed to map vertex buffer.");
+        return -1;
+    }
+
+    const char *input = NULL;
+
+    if (buffer)
+    {
+        int offset = attribute.mOffset;
+
+        input = static_cast<const char*>(buffer->data()) + offset;
+    }
+    else
+    {
+        input = static_cast<const char*>(attribute.mPointer);
+    }
+
+    if (instances == 0 || attribute.mDivisor == 0)
+    {
+        input += inputStride * start;
+    }
+
+    if (converter.identity && inputStride == elementSize)
+    {
+        memcpy(output, input, count * inputStride);
+    }
+    else
+    {
+        converter.convertArray(input, inputStride, count, output);
+    }
+
+    vertexBuffer->unmap();
+
+    return streamOffset;
+}
+
+GLenum VertexDataManager::prepareVertexData(const VertexAttribute attribs[], ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances)
+{
+    if (!mStreamingBuffer)
+    {
+        return GL_OUT_OF_MEMORY;
+    }
+
+    for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+    {
+        translated[attributeIndex].active = (programBinary->getSemanticIndex(attributeIndex) != -1);
+    }
+
+    // Determine the required storage size per used buffer, and invalidate static buffers that don't contain matching attributes
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        if (translated[i].active && attribs[i].mArrayEnabled)
+        {
+            Buffer *buffer = attribs[i].mBoundBuffer.get();
+            StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
+
+            if (staticBuffer)
+            {
+                if (staticBuffer->size() == 0)
+                {
+                    int totalCount = elementsInBuffer(attribs[i], buffer->size());
+                    staticBuffer->addRequiredSpace(spaceRequired(attribs[i], totalCount, 0));
+                }
+                else if (staticBuffer->lookupAttribute(attribs[i]) == -1)
+                {
+                    // This static buffer doesn't have matching attributes, so fall back to using the streaming buffer
+                    // Add the space of all previous attributes belonging to the invalidated static buffer to the streaming buffer
+                    for (int previous = 0; previous < i; previous++)
+                    {
+                        if (translated[previous].active && attribs[previous].mArrayEnabled)
+                        {
+                            Buffer *previousBuffer = attribs[previous].mBoundBuffer.get();
+                            StaticVertexBuffer *previousStaticBuffer = previousBuffer ? previousBuffer->getStaticVertexBuffer() : NULL;
+
+                            if (staticBuffer == previousStaticBuffer)
+                            {
+                                mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[previous], count, instances));
+                            }
+                        }
+                    }
+
+                    mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[i], count, instances));
+
+                    buffer->invalidateStaticData();
+                }
+            }
+            else
+            {
+                mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[i], count, instances));
+            }
+        }
+    }
+
+    // Reserve the required space per used buffer
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        if (translated[i].active && attribs[i].mArrayEnabled)
+        {
+            Buffer *buffer = attribs[i].mBoundBuffer.get();
+            ArrayVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
+            ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : mStreamingBuffer;
+
+            if (vertexBuffer)
+            {
+                vertexBuffer->reserveRequiredSpace();
+            }
+        }
+    }
+
+    // Perform the vertex data translations
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        if (translated[i].active)
+        {
+            if (attribs[i].mArrayEnabled)
+            {
+                Buffer *buffer = attribs[i].mBoundBuffer.get();
+
+                if (!buffer && attribs[i].mPointer == NULL)
+                {
+                    // This is an application error that would normally result in a crash, but we catch it and return an error
+                    ERR("An enabled vertex array has no buffer and no pointer.");
+                    return GL_INVALID_OPERATION;
+                }
+
+                const FormatConverter &converter = formatConverter(attribs[i]);
+
+                StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
+                ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : static_cast<ArrayVertexBuffer*>(mStreamingBuffer);
+
+                std::size_t streamOffset = -1;
+
+                if (staticBuffer)
+                {
+                    streamOffset = staticBuffer->lookupAttribute(attribs[i]);
+
+                    if (streamOffset == -1)
+                    {
+                        // Convert the entire buffer
+                        int totalCount = elementsInBuffer(attribs[i], buffer->size());
+                        int startIndex = attribs[i].mOffset / attribs[i].stride();
+
+                        streamOffset = writeAttributeData(staticBuffer, -startIndex, totalCount, attribs[i], 0);
+                    }
+
+                    if (streamOffset != -1)
+                    {
+                        streamOffset += (attribs[i].mOffset / attribs[i].stride()) * converter.outputElementSize;
+
+                        if (instances == 0 || attribs[i].mDivisor == 0)
+                        {
+                            streamOffset += start * converter.outputElementSize;
+                        }
+                    }
+                }
+                else
+                {
+                    streamOffset = writeAttributeData(mStreamingBuffer, start, count, attribs[i], instances);
+                }
+
+                if (streamOffset == -1)
+                {
+                    return GL_OUT_OF_MEMORY;
+                }
+
+                translated[i].vertexBuffer = vertexBuffer->getBuffer();
+                translated[i].serial = vertexBuffer->getSerial();
+                translated[i].divisor = attribs[i].mDivisor;
+
+                translated[i].type = converter.d3dDeclType;
+                translated[i].stride = converter.outputElementSize;
+                translated[i].offset = streamOffset;
+            }
+            else
+            {
+                if (!mCurrentValueBuffer[i])
+                {
+                    mCurrentValueBuffer[i] = new StreamingVertexBuffer(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE);
+                }
+
+                StreamingVertexBuffer *buffer = mCurrentValueBuffer[i];
+
+                if (mCurrentValue[i][0] != attribs[i].mCurrentValue[0] ||
+                    mCurrentValue[i][1] != attribs[i].mCurrentValue[1] ||
+                    mCurrentValue[i][2] != attribs[i].mCurrentValue[2] ||
+                    mCurrentValue[i][3] != attribs[i].mCurrentValue[3])
+                {
+                    const int requiredSpace = 4 * sizeof(float);
+                    buffer->addRequiredSpace(requiredSpace);
+                    buffer->reserveRequiredSpace();
+                    float *data = static_cast<float*>(buffer->map(VertexAttribute(), requiredSpace, &mCurrentValueOffsets[i]));
+                    if (data)
+                    {
+                        data[0] = attribs[i].mCurrentValue[0];
+                        data[1] = attribs[i].mCurrentValue[1];
+                        data[2] = attribs[i].mCurrentValue[2];
+                        data[3] = attribs[i].mCurrentValue[3];
+                        buffer->unmap();
+
+                        mCurrentValue[i][0] = attribs[i].mCurrentValue[0];
+                        mCurrentValue[i][1] = attribs[i].mCurrentValue[1];
+                        mCurrentValue[i][2] = attribs[i].mCurrentValue[2];
+                        mCurrentValue[i][3] = attribs[i].mCurrentValue[3];
+                    }
+                }
+
+                translated[i].vertexBuffer = mCurrentValueBuffer[i]->getBuffer();
+                translated[i].serial = mCurrentValueBuffer[i]->getSerial();
+                translated[i].divisor = 0;
+
+                translated[i].type = D3DDECLTYPE_FLOAT4;
+                translated[i].stride = 0;
+                translated[i].offset = mCurrentValueOffsets[i];
+            }
+        }
+    }
+
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        if (translated[i].active && attribs[i].mArrayEnabled)
+        {
+            Buffer *buffer = attribs[i].mBoundBuffer.get();
+
+            if (buffer)
+            {
+                buffer->promoteStaticUsage(count * attribs[i].typeSize());
+            }
+        }
+    }
+
+    return GL_NO_ERROR;
+}
+
+std::size_t VertexDataManager::spaceRequired(const VertexAttribute &attrib, std::size_t count, GLsizei instances) const
+{
+    size_t elementSize = formatConverter(attrib).outputElementSize;
+
+    if (instances == 0 || attrib.mDivisor == 0)
+    {
+        return elementSize * count;
+    }
+    else
+    {
+        return elementSize * ((instances + attrib.mDivisor - 1) / attrib.mDivisor);
+    }
+}
+
+// Mapping from OpenGL-ES vertex attrib type to D3D decl type:
+//
+// BYTE                 SHORT (Cast)
+// BYTE-norm            FLOAT (Normalize) (can't be exactly represented as SHORT-norm)
+// UNSIGNED_BYTE        UBYTE4 (Identity) or SHORT (Cast)
+// UNSIGNED_BYTE-norm   UBYTE4N (Identity) or FLOAT (Normalize)
+// SHORT                SHORT (Identity)
+// SHORT-norm           SHORT-norm (Identity) or FLOAT (Normalize)
+// UNSIGNED_SHORT       FLOAT (Cast)
+// UNSIGNED_SHORT-norm  USHORT-norm (Identity) or FLOAT (Normalize)
+// FIXED (not in WebGL) FLOAT (FixedToFloat)
+// FLOAT                FLOAT (Identity)
+
+// GLToCType maps from GL type (as GLenum) to the C typedef.
+template <GLenum GLType> struct GLToCType { };
+
+template <> struct GLToCType<GL_BYTE> { typedef GLbyte type; };
+template <> struct GLToCType<GL_UNSIGNED_BYTE> { typedef GLubyte type; };
+template <> struct GLToCType<GL_SHORT> { typedef GLshort type; };
+template <> struct GLToCType<GL_UNSIGNED_SHORT> { typedef GLushort type; };
+template <> struct GLToCType<GL_FIXED> { typedef GLuint type; };
+template <> struct GLToCType<GL_FLOAT> { typedef GLfloat type; };
+
+// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.)
+enum D3DVertexType
+{
+    D3DVT_FLOAT,
+    D3DVT_SHORT,
+    D3DVT_SHORT_NORM,
+    D3DVT_UBYTE,
+    D3DVT_UBYTE_NORM,
+    D3DVT_USHORT_NORM
+};
+
+// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type.
+template <unsigned int D3DType> struct D3DToCType { };
+
+template <> struct D3DToCType<D3DVT_FLOAT> { typedef float type; };
+template <> struct D3DToCType<D3DVT_SHORT> { typedef short type; };
+template <> struct D3DToCType<D3DVT_SHORT_NORM> { typedef short type; };
+template <> struct D3DToCType<D3DVT_UBYTE> { typedef unsigned char type; };
+template <> struct D3DToCType<D3DVT_UBYTE_NORM> { typedef unsigned char type; };
+template <> struct D3DToCType<D3DVT_USHORT_NORM> { typedef unsigned short type; };
+
+// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size.
+template <unsigned int type, int size>
+struct WidenRule
+{
+};
+
+template <int size> struct WidenRule<D3DVT_FLOAT, size>          : gl::NoWiden<size> { };
+template <int size> struct WidenRule<D3DVT_SHORT, size>          : gl::WidenToEven<size> { };
+template <int size> struct WidenRule<D3DVT_SHORT_NORM, size>     : gl::WidenToEven<size> { };
+template <int size> struct WidenRule<D3DVT_UBYTE, size>          : gl::WidenToFour<size> { };
+template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size>     : gl::WidenToFour<size> { };
+template <int size> struct WidenRule<D3DVT_USHORT_NORM, size>    : gl::WidenToEven<size> { };
+
+// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination.
+template <unsigned int d3dtype, int size>
+struct VertexTypeFlags
+{
+};
+
+template <unsigned int _capflag, unsigned int _declflag>
+struct VertexTypeFlagsHelper
+{
+    enum { capflag = _capflag };
+    enum { declflag = _declflag };
+};
+
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { };
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { };
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { };
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> { };
+template <> struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> { };
+template <> struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> { };
+template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> { };
+template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> { };
+
+
+// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums).
+template <GLenum GLtype, bool normalized>
+struct VertexTypeMapping
+{
+};
+
+template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred>
+struct VertexTypeMappingBase
+{
+    enum { preferred = Preferred };
+    enum { fallback = Fallback };
+};
+
+template <> struct VertexTypeMapping<GL_BYTE, false>                        : VertexTypeMappingBase<D3DVT_SHORT> { };                       // Cast
+template <> struct VertexTypeMapping<GL_BYTE, true>                         : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Normalize
+template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, false>               : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> { };          // Identity, Cast
+template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, true>                : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> { };     // Identity, Normalize
+template <> struct VertexTypeMapping<GL_SHORT, false>                       : VertexTypeMappingBase<D3DVT_SHORT> { };                       // Identity
+template <> struct VertexTypeMapping<GL_SHORT, true>                        : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> { };     // Cast, Normalize
+template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, false>              : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Cast
+template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, true>               : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> { };    // Cast, Normalize
+template <bool normalized> struct VertexTypeMapping<GL_FIXED, normalized>   : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // FixedToFloat
+template <bool normalized> struct VertexTypeMapping<GL_FLOAT, normalized>   : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Identity
+
+
+// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat).
+// The conversion rules themselves are defined in vertexconversion.h.
+
+// Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> knows it's an identity mapping).
+template <GLenum fromType, bool normalized, unsigned int toType>
+struct ConversionRule : gl::Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type>
+{
+};
+
+// All conversions from normalized types to float use the Normalize operator.
+template <GLenum fromType> struct ConversionRule<fromType, true, D3DVT_FLOAT> : gl::Normalize<typename GLToCType<fromType>::type> { };
+
+// Use a full specialisation for this so that it preferentially matches ahead of the generic normalize-to-float rules.
+template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT> : gl::FixedToFloat<GLint, 16> { };
+template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : gl::FixedToFloat<GLint, 16> { };
+
+// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1)
+// whether it is normalized or not.
+template <class T, bool normalized>
+struct DefaultVertexValuesStage2
+{
+};
+
+template <class T> struct DefaultVertexValuesStage2<T, true>  : gl::NormalizedDefaultValues<T> { };
+template <class T> struct DefaultVertexValuesStage2<T, false> : gl::SimpleDefaultValues<T> { };
+
+// Work out the default value rule for a D3D type (expressed as the C type) and
+template <class T, bool normalized>
+struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized>
+{
+};
+
+template <bool normalized> struct DefaultVertexValues<float, normalized> : gl::SimpleDefaultValues<float> { };
+
+// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion.
+// The fallback conversion produces an output that all D3D9 devices must support.
+template <class T> struct UsePreferred { enum { type = T::preferred }; };
+template <class T> struct UseFallback { enum { type = T::fallback }; };
+
+// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion,
+// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag
+// and the D3DDECLTYPE member needed for the vertex declaration in declflag.
+template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule>
+struct Converter
+    : gl::VertexDataConverter<typename GLToCType<fromType>::type,
+                              WidenRule<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type, size>,
+                              ConversionRule<fromType,
+                                             normalized,
+                                             PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>,
+                              DefaultVertexValues<typename D3DToCType<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>::type, normalized > >
+{
+private:
+    enum { d3dtype = PreferenceRule< VertexTypeMapping<fromType, normalized> >::type };
+    enum { d3dsize = WidenRule<d3dtype, size>::finalWidth };
+
+public:
+    enum { capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag };
+    enum { declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag };
+};
+
+// Initialise a TranslationInfo
+#define TRANSLATION(type, norm, size, preferred)                                    \
+    {                                                                               \
+        Converter<type, norm, size, preferred>::identity,                           \
+        Converter<type, norm, size, preferred>::finalSize,                          \
+        Converter<type, norm, size, preferred>::convertArray,                       \
+        static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag)  \
+    }
+
+#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size)    \
+    {                                                       \
+        Converter<type, norm, size, UsePreferred>::capflag, \
+        TRANSLATION(type, norm, size, UsePreferred),        \
+        TRANSLATION(type, norm, size, UseFallback)          \
+    }
+
+#define TRANSLATIONS_FOR_TYPE(type)                                                                                                                                                                         \
+    {                                                                                                                                                                                                       \
+        { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
+        { TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) },     \
+    }
+
+#define TRANSLATIONS_FOR_TYPE_NO_NORM(type)                                                                                                                                                                 \
+    {                                                                                                                                                                                                       \
+        { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
+        { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
+    }
+
+const VertexDataManager::TranslationDescription VertexDataManager::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1]
+{
+    TRANSLATIONS_FOR_TYPE(GL_BYTE),
+    TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE),
+    TRANSLATIONS_FOR_TYPE(GL_SHORT),
+    TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT),
+    TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED),
+    TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT)
+};
+
+void VertexDataManager::checkVertexCaps(DWORD declTypes)
+{
+    for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++)
+    {
+        for (unsigned int j = 0; j < 2; j++)
+        {
+            for (unsigned int k = 0; k < 4; k++)
+            {
+                if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0)
+                {
+                    mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion;
+                }
+                else
+                {
+                    mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion;
+                }
+            }
+        }
+    }
+}
+
+// This is used to index mAttributeTypes and mPossibleTranslations.
+unsigned int VertexDataManager::typeIndex(GLenum type) const
+{
+    switch (type)
+    {
+      case GL_BYTE: return 0;
+      case GL_UNSIGNED_BYTE: return 1;
+      case GL_SHORT: return 2;
+      case GL_UNSIGNED_SHORT: return 3;
+      case GL_FIXED: return 4;
+      case GL_FLOAT: return 5;
+
+      default: UNREACHABLE(); return 5;
+    }
+}
+
+VertexBuffer::VertexBuffer(rx::Renderer9 *renderer, std::size_t size, DWORD usageFlags) : mRenderer(renderer), mVertexBuffer(NULL)
+{
+    if (size > 0)
+    {
+        // D3D9_REPLACE
+        HRESULT result = mRenderer->createVertexBuffer(size, usageFlags,&mVertexBuffer);
+        mSerial = issueSerial();
+
+        if (FAILED(result))
+        {
+            ERR("Out of memory allocating a vertex buffer of size %lu.", size);
+        }
+    }
+}
+
+VertexBuffer::~VertexBuffer()
+{
+    if (mVertexBuffer)
+    {
+        mVertexBuffer->Release();
+    }
+}
+
+void VertexBuffer::unmap()
+{
+    if (mVertexBuffer)
+    {
+        mVertexBuffer->Unlock();
+    }
+}
+
+IDirect3DVertexBuffer9 *VertexBuffer::getBuffer() const
+{
+    return mVertexBuffer;
+}
+
+unsigned int VertexBuffer::getSerial() const
+{
+    return mSerial;
+}
+
+unsigned int VertexBuffer::issueSerial()
+{
+    return mCurrentSerial++;
+}
+
+ArrayVertexBuffer::ArrayVertexBuffer(rx::Renderer9 *renderer, std::size_t size, DWORD usageFlags) : VertexBuffer(renderer, size, usageFlags)
+{
+    mBufferSize = size;
+    mWritePosition = 0;
+    mRequiredSpace = 0;
+}
+
+ArrayVertexBuffer::~ArrayVertexBuffer()
+{
+}
+
+void ArrayVertexBuffer::addRequiredSpace(UINT requiredSpace)
+{
+    mRequiredSpace += requiredSpace;
+}
+
+StreamingVertexBuffer::StreamingVertexBuffer(rx::Renderer9 *renderer, std::size_t initialSize) : ArrayVertexBuffer(renderer, initialSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY)
+{
+}
+
+StreamingVertexBuffer::~StreamingVertexBuffer()
+{
+}
+
+void *StreamingVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *offset)
+{
+    void *mapPtr = NULL;
+
+    if (mVertexBuffer)
+    {
+        HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE);
+
+        if (FAILED(result))
+        {
+            ERR("Lock failed with error 0x%08x", result);
+            return NULL;
+        }
+
+        *offset = mWritePosition;
+        mWritePosition += requiredSpace;
+    }
+
+    return mapPtr;
+}
+
+void StreamingVertexBuffer::reserveRequiredSpace()
+{
+    if (mRequiredSpace > mBufferSize)
+    {
+        if (mVertexBuffer)
+        {
+            mVertexBuffer->Release();
+            mVertexBuffer = NULL;
+        }
+
+        mBufferSize = std::max(mRequiredSpace, 3 * mBufferSize / 2);   // 1.5 x mBufferSize is arbitrary and should be checked to see we don't have too many reallocations.
+
+        // D3D9_REPLACE
+        HRESULT result = mRenderer->createVertexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, &mVertexBuffer);
+        mSerial = issueSerial();
+
+        if (FAILED(result))
+        {
+            ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
+        }
+
+        mWritePosition = 0;
+    }
+    else if (mWritePosition + mRequiredSpace > mBufferSize)   // Recycle
+    {
+        if (mVertexBuffer)
+        {
+            void *dummy;
+            mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
+            mVertexBuffer->Unlock();
+        }
+
+        mWritePosition = 0;
+    }
+
+    mRequiredSpace = 0;
+}
+
+StaticVertexBuffer::StaticVertexBuffer(rx::Renderer9 *renderer) : ArrayVertexBuffer(renderer, 0, D3DUSAGE_WRITEONLY)
+{
+}
+
+StaticVertexBuffer::~StaticVertexBuffer()
+{
+}
+
+void *StaticVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset)
+{
+    void *mapPtr = NULL;
+
+    if (mVertexBuffer)
+    {
+        HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, 0);
+
+        if (FAILED(result))
+        {
+            ERR("Lock failed with error 0x%08x", result);
+            return NULL;
+        }
+
+        int attributeOffset = attribute.mOffset % attribute.stride();
+        VertexElement element = {attribute.mType, attribute.mSize, attribute.stride(), attribute.mNormalized, attributeOffset, mWritePosition};
+        mCache.push_back(element);
+
+        *streamOffset = mWritePosition;
+        mWritePosition += requiredSpace;
+    }
+
+    return mapPtr;
+}
+
+void StaticVertexBuffer::reserveRequiredSpace()
+{
+    if (!mVertexBuffer && mBufferSize == 0)
+    {
+        // D3D9_REPLACE
+        HRESULT result = mRenderer->createVertexBuffer(mRequiredSpace, D3DUSAGE_WRITEONLY, &mVertexBuffer);
+        mSerial = issueSerial();
+
+        if (FAILED(result))
+        {
+            ERR("Out of memory allocating a vertex buffer of size %lu.", mRequiredSpace);
+        }
+
+        mBufferSize = mRequiredSpace;
+    }
+    else if (mVertexBuffer && mBufferSize >= mRequiredSpace)
+    {
+        // Already allocated
+    }
+    else UNREACHABLE();   // Static vertex buffers can't be resized
+
+    mRequiredSpace = 0;
+}
+
+std::size_t StaticVertexBuffer::lookupAttribute(const VertexAttribute &attribute)
+{
+    for (unsigned int element = 0; element < mCache.size(); element++)
+    {
+        if (mCache[element].type == attribute.mType &&
+            mCache[element].size == attribute.mSize &&
+            mCache[element].stride == attribute.stride() &&
+            mCache[element].normalized == attribute.mNormalized)
+        {
+            if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride())
+            {
+                return mCache[element].streamOffset;
+            }
+        }
+    }
+
+    return -1;
+}
+
+const VertexDataManager::FormatConverter &VertexDataManager::formatConverter(const VertexAttribute &attribute) const
+{
+    return mAttributeTypes[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1];
+}
+}
diff --git a/src/libGLESv2/renderer/VertexDataManager.h b/src/libGLESv2/renderer/VertexDataManager.h
new file mode 100644
index 0000000..971aeca
--- /dev/null
+++ b/src/libGLESv2/renderer/VertexDataManager.h
@@ -0,0 +1,166 @@
+//
+// Copyright (c) 2002-2012 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.
+//
+
+// VertexDataManager.h: Defines the VertexDataManager, a class that
+// runs the Buffer translation process.
+
+#ifndef LIBGLESV2_VERTEXDATAMANAGER_H_
+#define LIBGLESV2_VERTEXDATAMANAGER_H_
+
+#include <vector>
+#include <cstddef>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include "libGLESv2/Context.h"
+
+namespace gl
+{
+
+struct TranslatedAttribute
+{
+    bool active;
+
+    D3DDECLTYPE type;
+    UINT offset;
+    UINT stride;   // 0 means not to advance the read pointer at all
+
+    IDirect3DVertexBuffer9 *vertexBuffer;
+    unsigned int serial;
+    unsigned int divisor;
+};
+
+class VertexBuffer
+{
+  public:
+    VertexBuffer(rx::Renderer9 *renderer, std::size_t size, DWORD usageFlags);
+    virtual ~VertexBuffer();
+
+    void unmap();
+
+    IDirect3DVertexBuffer9 *getBuffer() const;
+    unsigned int getSerial() const;
+
+  protected:
+    rx::Renderer9 *const mRenderer;   // D3D9_REPLACE
+    IDirect3DVertexBuffer9 *mVertexBuffer;
+
+    unsigned int mSerial;
+    static unsigned int issueSerial();
+    static unsigned int mCurrentSerial;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(VertexBuffer);
+};
+
+class ArrayVertexBuffer : public VertexBuffer
+{
+  public:
+    ArrayVertexBuffer(rx::Renderer9 *renderer, std::size_t size, DWORD usageFlags);
+    ~ArrayVertexBuffer();
+
+    std::size_t size() const { return mBufferSize; }
+    virtual void *map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset) = 0;
+    virtual void reserveRequiredSpace() = 0;
+    void addRequiredSpace(UINT requiredSpace);
+
+  protected:
+    std::size_t mBufferSize;
+    std::size_t mWritePosition;
+    std::size_t mRequiredSpace;
+};
+
+class StreamingVertexBuffer : public ArrayVertexBuffer
+{
+  public:
+    StreamingVertexBuffer(rx::Renderer9 *renderer, std::size_t initialSize);
+    ~StreamingVertexBuffer();
+
+    void *map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset);
+    void reserveRequiredSpace();
+};
+
+class StaticVertexBuffer : public ArrayVertexBuffer
+{
+  public:
+    explicit StaticVertexBuffer(rx::Renderer9 *renderer);
+    ~StaticVertexBuffer();
+
+    void *map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset);
+    void reserveRequiredSpace();
+
+    std::size_t lookupAttribute(const VertexAttribute &attribute);   // Returns the offset into the vertex buffer, or -1 if not found
+
+  private:
+    struct VertexElement
+    {
+        GLenum type;
+        GLint size;
+        GLsizei stride;
+        bool normalized;
+        int attributeOffset;
+
+        std::size_t streamOffset;
+    };
+
+    std::vector<VertexElement> mCache;
+};
+
+class VertexDataManager
+{
+  public:
+    VertexDataManager(rx::Renderer9 *renderer);
+    virtual ~VertexDataManager();
+
+    GLenum prepareVertexData(const VertexAttribute attribs[], ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(VertexDataManager);
+
+    std::size_t spaceRequired(const VertexAttribute &attrib, std::size_t count, GLsizei instances) const;
+    std::size_t writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute, GLsizei instances);
+
+    rx::Renderer9 *const mRenderer;   // D3D9_REPLACE
+
+    StreamingVertexBuffer *mStreamingBuffer;
+
+    float mCurrentValue[MAX_VERTEX_ATTRIBS][4];
+    StreamingVertexBuffer *mCurrentValueBuffer[MAX_VERTEX_ATTRIBS];
+    std::size_t mCurrentValueOffsets[MAX_VERTEX_ATTRIBS];
+
+    // Attribute format conversion
+    struct FormatConverter
+    {
+        bool identity;
+        std::size_t outputElementSize;
+        void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out);
+        D3DDECLTYPE d3dDeclType;
+    };
+
+    enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 };
+
+    FormatConverter mAttributeTypes[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];   // [GL types as enumerated by typeIndex()][normalized][size - 1]
+
+    struct TranslationDescription
+    {
+        DWORD capsFlag;
+        FormatConverter preferredConversion;
+        FormatConverter fallbackConversion;
+    };
+
+    // This table is used to generate mAttributeTypes.
+    static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1]
+
+    void checkVertexCaps(DWORD declTypes);
+
+    unsigned int typeIndex(GLenum type) const;
+    const FormatConverter &formatConverter(const VertexAttribute &attribute) const;
+};
+
+}
+
+#endif   // LIBGLESV2_VERTEXDATAMANAGER_H_
diff --git a/src/libGLESv2/renderer/VertexDeclarationCache.cpp b/src/libGLESv2/renderer/VertexDeclarationCache.cpp
index 37ccf5f..b69ad5d 100644
--- a/src/libGLESv2/renderer/VertexDeclarationCache.cpp
+++ b/src/libGLESv2/renderer/VertexDeclarationCache.cpp
@@ -7,7 +7,7 @@
 // VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations.
 
 #include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/VertexDataManager.h"
+#include "libGLESv2/renderer/VertexDataManager.h"
 #include "libGLESv2/renderer/VertexDeclarationCache.h"
 
 namespace rx
diff --git a/src/libGLESv2/renderer/VertexDeclarationCache.h b/src/libGLESv2/renderer/VertexDeclarationCache.h
index 3b4545e..f977eb6 100644
--- a/src/libGLESv2/renderer/VertexDeclarationCache.h
+++ b/src/libGLESv2/renderer/VertexDeclarationCache.h
@@ -10,7 +10,7 @@
 #define LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_
 
 #include "libGLESv2/Context.h"
-#include "libGLESv2/VertexDataManager.h"
+#include "libGLESv2/renderer/VertexDataManager.h"
 
 namespace gl
 {
diff --git a/src/libGLESv2/renderer/vertexconversion.h b/src/libGLESv2/renderer/vertexconversion.h
new file mode 100644
index 0000000..5bb8b89
--- /dev/null
+++ b/src/libGLESv2/renderer/vertexconversion.h
@@ -0,0 +1,208 @@
+//
+// Copyright (c) 2002-2010 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.
+//
+
+// vertexconversion.h: A library of vertex conversion classes that can be used to build
+// the FormatConverter objects used by the buffer conversion system.
+
+#ifndef LIBGLESV2_VERTEXCONVERSION_H_
+#define LIBGLESV2_VERTEXCONVERSION_H_
+
+#include <cstddef>
+#include <limits>
+
+#include "libGLESv2/Context.h" // Defines Index
+
+namespace gl
+{
+
+// Conversion types:
+// static const bool identity: true if this is an identity transform, false otherwise
+// static U convert(T): convert a single element from the input type to the output type
+// typedef ... OutputType: the type produced by this conversion
+
+template <class T>
+struct Identity
+{
+    static const bool identity = true;
+
+    typedef T OutputType;
+
+    static T convert(T x)
+    {
+        return x;
+    }
+};
+
+template <class FromT, class ToT>
+struct Cast
+{
+    static const bool identity = false;
+
+    typedef ToT OutputType;
+
+    static ToT convert(FromT x)
+    {
+        return static_cast<ToT>(x);
+    }
+};
+
+template <class T>
+struct Cast<T, T>
+{
+    static const bool identity = true;
+
+    typedef T OutputType;
+
+    static T convert(T x)
+    {
+        return static_cast<T>(x);
+    }
+};
+
+template <class T>
+struct Normalize
+{
+    static const bool identity = false;
+
+    typedef float OutputType;
+
+    static float convert(T x)
+    {
+        typedef std::numeric_limits<T> NL;
+        float f = static_cast<float>(x);
+
+        if (NL::is_signed)
+        {
+            // const float => VC2008 computes it at compile time
+            // static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that.
+            const float divisor = 1.0f/(2*static_cast<float>(NL::max())+1);
+            return (2*f+1)*divisor;
+        }
+        else
+        {
+            return f/NL::max();
+        }
+    }
+};
+
+template <class FromType, std::size_t ScaleBits>
+struct FixedToFloat
+{
+    static const bool identity = false;
+
+    typedef float OutputType;
+
+    static float convert(FromType x)
+    {
+        const float divisor = 1.0f / static_cast<float>(static_cast<FromType>(1) << ScaleBits);
+        return static_cast<float>(x) * divisor;
+    }
+};
+
+// Widen types:
+// static const unsigned int initialWidth: number of components before conversion
+// static const unsigned int finalWidth: number of components after conversion
+
+// Float is supported at any size.
+template <std::size_t N>
+struct NoWiden
+{
+    static const std::size_t initialWidth = N;
+    static const std::size_t finalWidth = N;
+};
+
+// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components
+template <std::size_t N>
+struct WidenToEven
+{
+    static const std::size_t initialWidth = N;
+    static const std::size_t finalWidth = N+(N&1);
+};
+
+template <std::size_t N>
+struct WidenToFour
+{
+    static const std::size_t initialWidth = N;
+    static const std::size_t finalWidth = 4;
+};
+
+// Most types have 0 and 1 that are just that.
+template <class T>
+struct SimpleDefaultValues
+{
+    static T zero() { return static_cast<T>(0); }
+    static T one() { return static_cast<T>(1); }
+};
+
+// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value.
+template <class T>
+struct NormalizedDefaultValues
+{
+    static T zero() { return static_cast<T>(0); }
+    static T one() { return std::numeric_limits<T>::max(); }
+};
+
+// Converter:
+// static const bool identity: true if this is an identity transform (with no widening)
+// static const std::size_t finalSize: number of bytes per output vertex
+// static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert an array of vertices. Input may be strided, but output will be unstrided.
+
+template <class InT, class WidenRule, class Converter, class DefaultValueRule = SimpleDefaultValues<InT> >
+struct VertexDataConverter
+{
+    typedef typename Converter::OutputType OutputType;
+    typedef InT InputType;
+
+    static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity;
+    static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType);
+
+    static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out)
+    {
+        for (std::size_t i = 0; i < n; i++)
+        {
+            const InputType *ein = pointerAddBytes(in, i * stride);
+
+            copyComponent(out, ein, 0, static_cast<OutputType>(DefaultValueRule::zero()));
+            copyComponent(out, ein, 1, static_cast<OutputType>(DefaultValueRule::zero()));
+            copyComponent(out, ein, 2, static_cast<OutputType>(DefaultValueRule::zero()));
+            copyComponent(out, ein, 3, static_cast<OutputType>(DefaultValueRule::one()));
+
+            out += WidenRule::finalWidth;
+        }
+    }
+
+    static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out)
+    {
+        return convertArray(static_cast<const InputType*>(in), stride, n, static_cast<OutputType*>(out));
+    }
+
+  private:
+    // Advance the given pointer by a number of bytes (not pointed-to elements).
+    template <class T>
+    static T *pointerAddBytes(T *basePtr, std::size_t numBytes)
+    {
+        return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(basePtr) + numBytes);
+    }
+
+    static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue)
+    {
+        if (WidenRule::finalWidth > elementindex)
+        {
+            if (WidenRule::initialWidth > elementindex)
+            {
+                out[elementindex] = Converter::convert(in[elementindex]);
+            }
+            else
+            {
+                out[elementindex] = defaultvalue;
+            }
+        }
+    }
+};
+
+}
+
+#endif   // LIBGLESV2_VERTEXCONVERSION_H_