Implement GL_OES_element_index_uint

TRAC #11951

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

Author:    Andrew Lewycky

git-svn-id: https://angleproject.googlecode.com/svn/trunk@240 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 9c3b232..0d87a7e 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -239,6 +239,8 @@
 
     if (!mHasBeenCurrent)
     {
+        initExtensionString();
+
         mState.viewportX = 0;
         mState.viewportY = 0;
         mState.viewportWidth = surface->getWidth();
@@ -1731,23 +1733,6 @@
     }
 }
 
-// The indices parameter to glDrawElements can have two interpretations:
-// - as a pointer into client memory
-// - as an offset into the current GL_ELEMENT_ARRAY_BUFFER buffer
-// Handle these cases here and return a pointer to the index data.
-const Index *Context::adjustIndexPointer(const void *indices)
-{
-    if (mState.elementArrayBuffer)
-    {
-        Buffer *buffer = getBuffer(mState.elementArrayBuffer);
-        return reinterpret_cast<const Index*>(static_cast<unsigned char*>(buffer->data()) + reinterpret_cast<GLsizei>(indices));
-    }
-    else
-    {
-        return static_cast<const Index*>(indices);
-    }
-}
-
 void Context::applyVertexBuffer(GLint first, GLsizei count)
 {
     TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
@@ -1763,7 +1748,7 @@
 {
     TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
 
-    mVertexDataManager->preRenderValidate(indexInfo, translated);
+    mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
 
     lookupAttributeMapping(translated);
 
@@ -2256,7 +2241,7 @@
     if (!cullSkipsDraw(mode))
     {
         display->startScene();
-        device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/sizeof(Index), primitiveCount);
+        device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount);
     }
 }
 
@@ -2575,6 +2560,25 @@
     mVertexDataManager->dirtyCurrentValues();
 }
 
+void Context::initExtensionString()
+{
+    if (mBufferBackEnd->supportIntIndices())
+    {
+        mExtensionString += "GL_OES_element_index_uint ";
+    }
+
+    std::string::size_type end = mExtensionString.find_last_not_of(' ');
+    if (end != std::string::npos)
+    {
+        mExtensionString.resize(end+1);
+    }
+}
+
+const char *Context::getExtensionString() const
+{
+    return mExtensionString.c_str();
+}
+
 }
 
 extern "C"
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index 4372b0b..3943430 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -69,9 +69,6 @@
 const float ALIASED_POINT_SIZE_RANGE_MIN = 1.0f;
 const float ALIASED_POINT_SIZE_RANGE_MAX = 1.0f;
 
-// Because indices are accessed internally, we convert them to a common format.
-typedef unsigned short Index;
-
 enum SamplerType
 {
     SAMPLER_2D,
@@ -376,13 +373,14 @@
     const char *getPixelShaderProfile();
     const char *getVertexShaderProfile();
 
+    const char *getExtensionString() const;
+
     Blit *getBlitter() { return mBlit; }
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Context);
 
     void lookupAttributeMapping(TranslatedAttribute *attributes);
-    const Index *adjustIndexPointer(const void *indices);
 
     void detachBuffer(GLuint buffer);
     void detachTexture(GLuint texture);
@@ -423,6 +421,9 @@
     typedef std::map<GLuint, Renderbuffer*> RenderbufferMap;
     RenderbufferMap mRenderbufferMap;
 
+    void initExtensionString();
+    std::string mExtensionString;
+
     BufferBackEnd *mBufferBackEnd;
     VertexDataManager *mVertexDataManager;
     IndexDataManager *mIndexDataManager;
diff --git a/src/libGLESv2/geometry/IndexDataManager.cpp b/src/libGLESv2/geometry/IndexDataManager.cpp
index e50ca6b..3015723 100644
--- a/src/libGLESv2/geometry/IndexDataManager.cpp
+++ b/src/libGLESv2/geometry/IndexDataManager.cpp
@@ -16,30 +16,40 @@
 
 namespace
 {
-    enum { INITIAL_INDEX_BUFFER_SIZE = sizeof(gl::Index) * 8192 };
+    enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
 }
 
 namespace gl
 {
 
 IndexDataManager::IndexDataManager(Context *context, BufferBackEnd *backend)
-    : mContext(context), mBackend(backend)
+  : mContext(context), mBackend(backend), mIntIndicesSupported(backend->supportIntIndices())
 {
-    mStreamBuffer = mBackend->createIndexBuffer(INITIAL_INDEX_BUFFER_SIZE);
+    mStreamBufferShort = mBackend->createIndexBuffer(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT);
+
+    if (mIntIndicesSupported)
+    {
+        mStreamBufferInt = mBackend->createIndexBuffer(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
+    }
+    else
+    {
+        mStreamBufferInt = NULL;
+    }
 }
 
 IndexDataManager::~IndexDataManager()
 {
-    delete mStreamBuffer;
+    delete mStreamBufferShort;
+    delete mStreamBufferInt;
 }
 
 namespace
 {
 
-template <class InputIndexType>
-void copyIndices(const InputIndexType *in, GLsizei count, Index *out, GLuint *minIndex, GLuint *maxIndex)
+template <class InputIndexType, class OutputIndexType>
+void copyIndices(const InputIndexType *in, GLsizei count, OutputIndexType *out, GLuint *minIndex, GLuint *maxIndex)
 {
-    Index first = *in;
+    InputIndexType first = *in;
     GLuint minIndexSoFar = first;
     GLuint maxIndexSoFar = first;
 
@@ -62,7 +72,7 @@
 
 TranslatedIndexData IndexDataManager::preRenderValidate(GLenum mode, GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices)
 {
-    ASSERT(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_BYTE);
+    ASSERT(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT);
     ASSERT(count > 0);
 
     TranslatedIndexData translated;
@@ -71,54 +81,100 @@
 
     std::size_t requiredSpace = spaceRequired(type, count);
 
-    if (requiredSpace > mStreamBuffer->size())
-    {
-        std::size_t newSize = std::max(requiredSpace, 2 * mStreamBuffer->size());
-
-        TranslatedIndexBuffer *newStreamBuffer = mBackend->createIndexBuffer(newSize);
-
-        delete mStreamBuffer;
-        mStreamBuffer = newStreamBuffer;
-    }
-
-    mStreamBuffer->reserveSpace(requiredSpace);
+    TranslatedIndexBuffer *streamIb = prepareIndexBuffer(type, requiredSpace);
 
     size_t offset;
-    void *output = mStreamBuffer->map(requiredSpace, &offset);
+    void *output = streamIb->map(requiredSpace, &offset);
 
-    translated.buffer = mStreamBuffer;
+    translated.buffer = streamIb;
     translated.offset = offset;
+    translated.indexSize = indexSize(type);
 
-    translated.indices = static_cast<const Index*>(output);
+    translated.indices = output;
 
     if (arrayElementBuffer != NULL)
     {
         indices = static_cast<const GLubyte*>(arrayElementBuffer->data()) + reinterpret_cast<GLsizei>(indices);
     }
 
-    Index *out = static_cast<Index*>(output);
-
-    if (type == GL_UNSIGNED_SHORT)
+    if (type == GL_UNSIGNED_BYTE)
     {
-        const GLushort *in = static_cast<const GLushort*>(indices);
+        const GLubyte *in = static_cast<const GLubyte*>(indices);
+        GLushort *out = static_cast<GLushort*>(output);
 
         copyIndices(in, count, out, &translated.minIndex, &translated.maxIndex);
     }
+    else if (type == GL_UNSIGNED_INT)
+    {
+        const GLuint *in = static_cast<const GLuint*>(indices);
+
+        if (mIntIndicesSupported)
+        {
+            GLuint *out = static_cast<GLuint*>(output);
+
+            copyIndices(in, count, out, &translated.minIndex, &translated.maxIndex);
+        }
+        else
+        {
+            // When 32-bit indices are unsupported, fake them by truncating to 16-bit.
+
+            GLushort *out = static_cast<GLushort*>(output);
+
+            copyIndices(in, count, out, &translated.minIndex, &translated.maxIndex);
+        }
+    }
     else
     {
-        const GLubyte *in = static_cast<const GLubyte*>(indices);
+        const GLushort *in = static_cast<const GLushort*>(indices);
+        GLushort *out = static_cast<GLushort*>(output);
 
         copyIndices(in, count, out, &translated.minIndex, &translated.maxIndex);
     }
 
-    mStreamBuffer->unmap();
+    streamIb->unmap();
 
     return translated;
 }
 
-std::size_t IndexDataManager::spaceRequired(GLenum type, GLsizei count)
+std::size_t IndexDataManager::indexSize(GLenum type) const
 {
-    return (count + 1) * sizeof(Index); // +1 because we always leave an extra for line loops
+    return (type == GL_UNSIGNED_INT && mIntIndicesSupported) ? sizeof(GLuint) : sizeof(GLushort);
+}
+
+std::size_t IndexDataManager::spaceRequired(GLenum type, GLsizei count) const
+{
+    return (count + 1) * indexSize(type); // +1 because we always leave an extra for line loops
+}
+
+TranslatedIndexBuffer *IndexDataManager::prepareIndexBuffer(GLenum type, std::size_t requiredSpace)
+{
+    bool use32 = (type == GL_UNSIGNED_INT && mIntIndicesSupported);
+
+    TranslatedIndexBuffer *streamIb = use32 ? mStreamBufferInt : mStreamBufferShort;
+
+    if (requiredSpace > streamIb->size())
+    {
+        std::size_t newSize = std::max(requiredSpace, 2 * streamIb->size());
+
+        TranslatedIndexBuffer *newStreamBuffer = mBackend->createIndexBuffer(newSize, use32 ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT);
+
+        delete streamIb;
+
+        streamIb = newStreamBuffer;
+
+        if (use32)
+        {
+            mStreamBufferInt = streamIb;
+        }
+        else
+        {
+            mStreamBufferShort = streamIb;
+        }
+    }
+
+    streamIb->reserveSpace(requiredSpace);
+
+    return streamIb;
 }
 
 }
diff --git a/src/libGLESv2/geometry/IndexDataManager.h b/src/libGLESv2/geometry/IndexDataManager.h
index 087b5fe..0165640 100644
--- a/src/libGLESv2/geometry/IndexDataManager.h
+++ b/src/libGLESv2/geometry/IndexDataManager.h
@@ -31,8 +31,9 @@
     GLuint minIndex;
     GLuint maxIndex;
     GLuint count;
+    GLuint indexSize;
 
-    const Index *indices;
+    const void *indices;
 
     TranslatedIndexBuffer *buffer;
     GLsizei offset;
@@ -47,12 +48,17 @@
     TranslatedIndexData preRenderValidate(GLenum mode, GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices);
 
   private:
-    std::size_t spaceRequired(GLenum type, GLsizei count);
+    std::size_t IndexDataManager::indexSize(GLenum type) const;
+    std::size_t spaceRequired(GLenum type, GLsizei count) const;
+    TranslatedIndexBuffer *prepareIndexBuffer(GLenum type, std::size_t requiredSpace);
 
     Context *mContext;
     BufferBackEnd *mBackend;
 
-    TranslatedIndexBuffer *mStreamBuffer;
+    bool mIntIndicesSupported;
+
+    TranslatedIndexBuffer *mStreamBufferShort;
+    TranslatedIndexBuffer *mStreamBufferInt;
 };
 
 }
diff --git a/src/libGLESv2/geometry/VertexDataManager.cpp b/src/libGLESv2/geometry/VertexDataManager.cpp
index 11ccba4..42a051e 100644
--- a/src/libGLESv2/geometry/VertexDataManager.cpp
+++ b/src/libGLESv2/geometry/VertexDataManager.cpp
@@ -46,27 +46,7 @@
     delete mCurrentValueBuffer;
 }
 
-VertexDataManager::ArrayTranslationHelper::ArrayTranslationHelper(GLint first, GLsizei count)
-    : mFirst(first), mCount(count)
-{
-}
-
-void VertexDataManager::ArrayTranslationHelper::translate(const FormatConverter &converter, GLsizei stride, const void *source, void *dest)
-{
-    converter.convertArray(source, stride, mCount, dest);
-}
-
-VertexDataManager::IndexedTranslationHelper::IndexedTranslationHelper(const Index *indices, Index minIndex, GLsizei count)
-    : mIndices(indices), mMinIndex(minIndex), mCount(count)
-{
-}
-
-void VertexDataManager::IndexedTranslationHelper::translate(const FormatConverter &converter, GLsizei stride, const void *source, void *dest)
-{
-    converter.convertIndexed(source, stride, mMinIndex, mCount, mIndices, dest);
-}
-
-std::bitset<MAX_VERTEX_ATTRIBS> VertexDataManager::activeAttribs()
+std::bitset<MAX_VERTEX_ATTRIBS> VertexDataManager::getActiveAttribs() const
 {
     std::bitset<MAX_VERTEX_ATTRIBS> active;
 
@@ -81,28 +61,11 @@
 }
 
 GLenum VertexDataManager::preRenderValidate(GLint start, GLsizei count,
-                                            TranslatedAttribute *outAttribs)
+                                            TranslatedAttribute *translated)
 {
-    ArrayTranslationHelper translationHelper(start, count);
+    const AttributeState *attribs = mContext->getVertexAttribBlock();
+    const std::bitset<MAX_VERTEX_ATTRIBS> activeAttribs = getActiveAttribs();
 
-    return internalPreRenderValidate(mContext->getVertexAttribBlock(), activeAttribs(), start, start+count-1, &translationHelper, outAttribs);
-}
-
-GLenum VertexDataManager::preRenderValidate(const TranslatedIndexData &indexInfo,
-                                            TranslatedAttribute *outAttribs)
-{
-    IndexedTranslationHelper translationHelper(indexInfo.indices, indexInfo.minIndex, indexInfo.count);
-
-    return internalPreRenderValidate(mContext->getVertexAttribBlock(), activeAttribs(), indexInfo.minIndex, indexInfo.maxIndex, &translationHelper, outAttribs);
-}
-
-GLenum VertexDataManager::internalPreRenderValidate(const AttributeState *attribs,
-                                                    const std::bitset<MAX_VERTEX_ATTRIBS> &activeAttribs,
-                                                    Index minIndex,
-                                                    Index maxIndex,
-                                                    TranslationHelper *translator,
-                                                    TranslatedAttribute *translated)
-{
     std::bitset<MAX_VERTEX_ATTRIBS> translateOrLift;
 
     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
@@ -127,7 +90,7 @@
             if (attribs[i].mBoundBuffer != 0 && mBackend->getFormatConverter(attribs[i].mType, attribs[i].mSize, attribs[i].mNormalized).identity)
             {
                 std::size_t stride = interpretGlStride(attribs[i]);
-                std::size_t offset = static_cast<std::size_t>(static_cast<const char*>(attribs[i].mPointer) - static_cast<const char*>(NULL)) + stride * minIndex;
+                std::size_t offset = static_cast<std::size_t>(static_cast<const char*>(attribs[i].mPointer) - static_cast<const char*>(NULL)) + stride * start;
 
                 if (mBackend->validateStream(attribs[i].mType, attribs[i].mSize, stride, offset))
                 {
@@ -153,8 +116,6 @@
     // Handle any attributes needing translation or lifting.
     if (translateOrLift.any())
     {
-        std::size_t count = maxIndex - minIndex + 1;
-
         std::size_t requiredSpace = 0;
 
         for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
@@ -204,9 +165,9 @@
 
                 size_t inputStride = interpretGlStride(attribs[i]);
 
-                input = static_cast<const char*>(input) + inputStride * minIndex;
+                input = static_cast<const char*>(input) + inputStride * start;
 
-                translator->translate(formatConverter, interpretGlStride(attribs[i]), input, output);
+                formatConverter.convertArray(input, inputStride, count, output);
 
                 mStreamBuffer->unmap();
             }
diff --git a/src/libGLESv2/geometry/VertexDataManager.h b/src/libGLESv2/geometry/VertexDataManager.h
index f0d5dc0..7f5e72c 100644
--- a/src/libGLESv2/geometry/VertexDataManager.h
+++ b/src/libGLESv2/geometry/VertexDataManager.h
@@ -40,51 +40,8 @@
                              GLsizei count,
                              TranslatedAttribute *outAttribs);
 
-    GLenum preRenderValidate(const TranslatedIndexData &indexInfo,
-                             TranslatedAttribute* outAttribs);
-
   private:
-    std::bitset<MAX_VERTEX_ATTRIBS> activeAttribs();
-
-    class TranslationHelper
-    {
-      public:
-        virtual ~TranslationHelper() { }
-
-        virtual void translate(const FormatConverter &converter, GLsizei stride, const void *source, void *dest) = 0;
-    };
-
-    class ArrayTranslationHelper : public TranslationHelper
-    {
-      public:
-        ArrayTranslationHelper(GLint first, GLsizei count);
-
-        void translate(const FormatConverter &converter, GLsizei stride, const void *source, void *dest);
-
-      private:
-        GLint mFirst;
-        GLsizei mCount;
-    };
-
-    class IndexedTranslationHelper : public TranslationHelper
-    {
-      public:
-        IndexedTranslationHelper(const Index *indices, Index minIndex, GLsizei count);
-
-        void translate(const FormatConverter &converter, GLint stride, const void *source, void *dest);
-
-      private:
-        const Index *mIndices;
-        Index mMinIndex;
-        GLsizei mCount;
-    };
-
-    GLenum internalPreRenderValidate(const AttributeState *attribs,
-                                     const std::bitset<MAX_VERTEX_ATTRIBS> &activeAttribs,
-                                     Index minIndex,
-                                     Index maxIndex,
-                                     TranslationHelper *translator,
-                                     TranslatedAttribute *outAttribs);
+    std::bitset<MAX_VERTEX_ATTRIBS> getActiveAttribs() const;
 
     void reloadCurrentValues(const AttributeState *attribs, std::size_t *offset);
 
diff --git a/src/libGLESv2/geometry/backend.h b/src/libGLESv2/geometry/backend.h
index 6a9f0dc..09267df 100644
--- a/src/libGLESv2/geometry/backend.h
+++ b/src/libGLESv2/geometry/backend.h
@@ -26,7 +26,6 @@
 {
     bool identity;
     std::size_t outputVertexSize;
-    void (*convertIndexed)(const void *in, std::size_t stride, Index minIndex, std::size_t n, const Index *indices, void *out);
     void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out);
 };
 
@@ -53,9 +52,11 @@
   public:
     virtual ~BufferBackEnd() { }
 
+    virtual bool supportIntIndices() = 0;
+
     virtual TranslatedVertexBuffer *createVertexBuffer(std::size_t size) = 0;
     virtual TranslatedVertexBuffer *createVertexBufferForStrideZero(std::size_t size) = 0;
-    virtual TranslatedIndexBuffer *createIndexBuffer(std::size_t size) = 0;
+    virtual TranslatedIndexBuffer *createIndexBuffer(std::size_t size, GLenum type) = 0;
     virtual FormatConverter getFormatConverter(GLenum type, std::size_t size, bool normalize) = 0;
 
     // For an identity-mappable stream, verify that the stride and offset are okay.
diff --git a/src/libGLESv2/geometry/dx9.cpp b/src/libGLESv2/geometry/dx9.cpp
index 485d8d7..7224a7a 100644
--- a/src/libGLESv2/geometry/dx9.cpp
+++ b/src/libGLESv2/geometry/dx9.cpp
@@ -32,7 +32,6 @@
 
         formatConverter.identity = gl::VertexDataConverter<InputType, WidenRule<IncomingWidth>, ElementConverter, DefaultValueRule>::identity;
         formatConverter.outputVertexSize = gl::VertexDataConverter<InputType, WidenRule<IncomingWidth>, ElementConverter, DefaultValueRule>::finalSize;
-        formatConverter.convertIndexed = gl::VertexDataConverter<InputType, WidenRule<IncomingWidth>, ElementConverter, DefaultValueRule>::convertIndexed;
         formatConverter.convertArray = gl::VertexDataConverter<InputType, WidenRule<IncomingWidth>, ElementConverter, DefaultValueRule>::convertArray;
 
         return formatConverter;
@@ -66,6 +65,14 @@
     mDevice->Release();
 }
 
+bool Dx9BackEnd::supportIntIndices()
+{
+    D3DCAPS9 caps;
+    mDevice->GetDeviceCaps(&caps);
+
+    return (caps.MaxVertexIndex >= (1 << 16));
+}
+
 TranslatedVertexBuffer *Dx9BackEnd::createVertexBuffer(std::size_t size)
 {
     return new Dx9VertexBuffer(mDevice, size);
@@ -76,9 +83,9 @@
     return new Dx9VertexBufferZeroStrideWorkaround(mDevice, size);
 }
 
-TranslatedIndexBuffer *Dx9BackEnd::createIndexBuffer(std::size_t size)
+TranslatedIndexBuffer *Dx9BackEnd::createIndexBuffer(std::size_t size, GLenum type)
 {
-    return new Dx9IndexBuffer(mDevice, size);
+    return new Dx9IndexBuffer(mDevice, size, type);
 }
 
 // Mapping from OpenGL-ES vertex attrib type to D3D decl type:
@@ -325,10 +332,14 @@
     return mapPtr;
 }
 
-Dx9BackEnd::Dx9IndexBuffer::Dx9IndexBuffer(IDirect3DDevice9 *device, std::size_t size)
+Dx9BackEnd::Dx9IndexBuffer::Dx9IndexBuffer(IDirect3DDevice9 *device, std::size_t size, GLenum type)
     : TranslatedIndexBuffer(size)
 {
-    HRESULT hr = device->CreateIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &mIndexBuffer, NULL);
+    ASSERT(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT);
+
+    D3DFORMAT format = (type == GL_UNSIGNED_SHORT) ? D3DFMT_INDEX16 : D3DFMT_INDEX32;
+
+    HRESULT hr = device->CreateIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, D3DPOOL_DEFAULT, &mIndexBuffer, NULL);
     if (hr != S_OK)
     {
         ERR("Out of memory allocating an index buffer of size %lu.", size);
diff --git a/src/libGLESv2/geometry/dx9.h b/src/libGLESv2/geometry/dx9.h
index f3938d8..b57cd31 100644
--- a/src/libGLESv2/geometry/dx9.h
+++ b/src/libGLESv2/geometry/dx9.h
@@ -23,9 +23,11 @@
     explicit Dx9BackEnd(IDirect3DDevice9 *d3ddevice);
     ~Dx9BackEnd();
 
+    virtual bool supportIntIndices();
+
     virtual TranslatedVertexBuffer *createVertexBuffer(std::size_t size);
     virtual TranslatedVertexBuffer *createVertexBufferForStrideZero(std::size_t size);
-    virtual TranslatedIndexBuffer *createIndexBuffer(std::size_t size);
+    virtual TranslatedIndexBuffer *createIndexBuffer(std::size_t size, GLenum type);
     virtual FormatConverter getFormatConverter(GLenum type, std::size_t size, bool normalize);
 
     virtual bool validateStream(GLenum type, std::size_t size, std::size_t stride, std::size_t offset) const;
@@ -70,7 +72,7 @@
     class Dx9IndexBuffer : public TranslatedIndexBuffer
     {
       public:
-        Dx9IndexBuffer(IDirect3DDevice9 *device, std::size_t size);
+        Dx9IndexBuffer(IDirect3DDevice9 *device, std::size_t size, GLenum type);
         virtual ~Dx9IndexBuffer();
 
         IDirect3DIndexBuffer9 *getBuffer() const;
diff --git a/src/libGLESv2/geometry/vertexconversion.h b/src/libGLESv2/geometry/vertexconversion.h
index 29f17c0..e55dc72 100644
--- a/src/libGLESv2/geometry/vertexconversion.h
+++ b/src/libGLESv2/geometry/vertexconversion.h
@@ -149,7 +149,6 @@
 // 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.
-// static void convertIndexed(const void *in, std::size_t stride, std::size_t n, const Index *indices, void *out): convert an indexed 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
@@ -180,25 +179,6 @@
         return convertArray(static_cast<const InputType*>(in), stride, n, static_cast<OutputType*>(out));
     }
 
-    static void convertIndexed(const InputType *in, std::size_t stride, Index minIndex, std::size_t n, const Index *indices, OutputType *out)
-    {
-        for (std::size_t i = 0; i < n; i++)
-        {
-            const InputType *ein = pointerAddBytes(in, (indices[i] - minIndex) * stride);
-            OutputType *eout = pointerAddBytes(out, (indices[i] - minIndex) * finalSize);
-
-            copyComponent(eout, ein, 0, static_cast<OutputType>(DefaultValueRule::zero()));
-            copyComponent(eout, ein, 1, static_cast<OutputType>(DefaultValueRule::zero()));
-            copyComponent(eout, ein, 2, static_cast<OutputType>(DefaultValueRule::zero()));
-            copyComponent(eout, ein, 3, static_cast<OutputType>(DefaultValueRule::one()));
-        }
-    }
-
-    static void convertIndexed(const void *in, std::size_t stride, Index minIndex, std::size_t n, const Index *indices, void *out)
-    {
-        convertIndexed(static_cast<const InputType*>(in), stride, minIndex, n, indices, static_cast<OutputType*>(out));
-    }
-
   private:
     // Advance the given pointer by a number of bytes (not pointed-to elements).
     template <class T>
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index 02893ba..c3c7a2f 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -1439,6 +1439,7 @@
         {
           case GL_UNSIGNED_BYTE:
           case GL_UNSIGNED_SHORT:
+          case GL_UNSIGNED_INT:
             break;
           default:
             return error(GL_INVALID_ENUM);
@@ -2735,6 +2736,8 @@
 
     try
     {
+        gl::Context *context = gl::getContext();
+
         switch (name)
         {
           case GL_VENDOR:
@@ -2746,7 +2749,7 @@
           case GL_SHADING_LANGUAGE_VERSION:
             return (GLubyte*)"OpenGL ES GLSL ES 1.00 (git-devel "__DATE__ " " __TIME__")";
           case GL_EXTENSIONS:
-            return (GLubyte*)"";
+            return (GLubyte*)((context != NULL) ? context->getExtensionString() : "");
           default:
             return error(GL_INVALID_ENUM, (GLubyte*)NULL);
         }