Integrated new IndexBuffer into IndexDataManager and Renderer9.

TRAC #22237

Author: Geoff Lang
Signed-off-by: Shannon Woods
Signed-off-by: Nicolas Capens
Signed-off-by: Daniel Koch

git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1607 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Buffer.cpp b/src/libGLESv2/Buffer.cpp
index bc1f24e..7573e50 100644
--- a/src/libGLESv2/Buffer.cpp
+++ b/src/libGLESv2/Buffer.cpp
@@ -70,7 +70,7 @@
 {
     memcpy(mContents + offset, data, size);
     
-    if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->size() != 0))
+    if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0))
     {
         invalidateStaticData();
     }
diff --git a/src/libGLESv2/renderer/IndexBuffer.cpp b/src/libGLESv2/renderer/IndexBuffer.cpp
index 37e8c3b..ba076f8 100644
--- a/src/libGLESv2/renderer/IndexBuffer.cpp
+++ b/src/libGLESv2/renderer/IndexBuffer.cpp
@@ -9,8 +9,6 @@
 
 #include "libGLESv2/renderer/IndexBuffer.h"
 
-#include "libGLESv2/renderer/Renderer9.h"
-
 namespace rx
 {
 
@@ -36,172 +34,143 @@
 }
 
 
-unsigned int IndexBufferInterface::mCurrentSerial = 1;
-
-IndexBufferInterface::IndexBufferInterface(rx::Renderer9 *renderer, UINT size, D3DFORMAT format) : mRenderer(renderer), mBufferSize(size), mIndexBuffer(NULL)
+IndexBufferInterface::IndexBufferInterface(Renderer *renderer, bool dynamic) : mRenderer(renderer)
 {
-    if (size > 0)
-    {
-        // D3D9_REPLACE
-        HRESULT result = mRenderer->createIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, &mIndexBuffer);
-        mSerial = issueSerial();
+    mIndexBuffer = renderer->createIndexBuffer();
 
-        if (FAILED(result))
-        {
-            ERR("Out of memory allocating an index buffer of size %lu.", size);
-        }
-    }
+    mDynamic = dynamic;
+    mWritePosition = 0;
 }
 
 IndexBufferInterface::~IndexBufferInterface()
 {
     if (mIndexBuffer)
     {
-        mIndexBuffer->Release();
+        delete mIndexBuffer;
     }
 }
 
-IDirect3DIndexBuffer9 *IndexBufferInterface::getBuffer() const
+GLenum IndexBufferInterface::getIndexType() const
 {
-    return mIndexBuffer;
+    return mIndexBuffer->getIndexType();
+}
+
+unsigned int IndexBufferInterface::getBufferSize() const
+{
+    return mIndexBuffer->getBufferSize();
 }
 
 unsigned int IndexBufferInterface::getSerial() const
 {
-    return mSerial;
+    return mIndexBuffer->getSerial();
 }
 
-unsigned int IndexBufferInterface::issueSerial()
+int IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory)
 {
-    return mCurrentSerial++;
-}
-
-void IndexBufferInterface::unmap()
-{
-    if (mIndexBuffer)
+    if (!mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory))
     {
-        mIndexBuffer->Unlock();
+        *outMappedMemory = NULL;
+        return -1;
+    }
+
+    int oldWritePos = static_cast<int>(mWritePosition);
+    mWritePosition += size;
+
+    return oldWritePos;
+}
+
+bool IndexBufferInterface::unmapBuffer()
+{
+    return mIndexBuffer->unmapBuffer();
+}
+
+IndexBuffer * IndexBufferInterface::getIndexBuffer() const
+{
+    return mIndexBuffer;
+}
+
+unsigned int IndexBufferInterface::getWritePosition() const
+{
+    return mWritePosition;
+}
+
+void IndexBufferInterface::setWritePosition(unsigned int writePosition)
+{
+    mWritePosition = writePosition;
+}
+
+bool IndexBufferInterface::discard()
+{
+    return mIndexBuffer->discard();
+}
+
+bool IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType)
+{
+    if (mIndexBuffer->getBufferSize() == 0)
+    {
+        return mIndexBuffer->initialize(bufferSize, indexType, mDynamic);
+    }
+    else
+    {
+        return mIndexBuffer->setSize(bufferSize, indexType);
     }
 }
 
-StreamingIndexBufferInterface::StreamingIndexBufferInterface(rx::Renderer9 *renderer, UINT initialSize, D3DFORMAT format) : IndexBufferInterface(renderer, initialSize, format)
+StreamingIndexBufferInterface::StreamingIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, true)
 {
-    mWritePosition = 0;
 }
 
 StreamingIndexBufferInterface::~StreamingIndexBufferInterface()
 {
 }
 
-void *StreamingIndexBufferInterface::map(UINT requiredSpace, UINT *offset)
+bool StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
 {
-    void *mapPtr = NULL;
-
-    if (mIndexBuffer)
+    bool result = true;
+    unsigned int curBufferSize = getBufferSize();
+    if (size > curBufferSize)
     {
-        HRESULT result = mIndexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE);
-
-        if (FAILED(result))
+        result = setBufferSize(std::max(size, 2 * curBufferSize), indexType);
+        setWritePosition(0);
+    }
+    else if (getWritePosition() + size > curBufferSize)
+    {
+        if (!discard())
         {
-            ERR(" Lock failed with error 0x%08x", result);
-            return NULL;
+            return false;
         }
-
-        *offset = mWritePosition;
-        mWritePosition += requiredSpace;
+        setWritePosition(0);
     }
 
-    return mapPtr;
+    return result;
 }
 
-void StreamingIndexBufferInterface::reserveSpace(UINT requiredSpace, GLenum type)
+
+StaticIndexBufferInterface::StaticIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, false)
 {
-    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;
-    }
-}
-
-StaticIndexBufferInterface::StaticIndexBufferInterface(rx::Renderer9 *renderer) : IndexBufferInterface(renderer, 0, D3DFMT_UNKNOWN)
-{
-    mCacheType = GL_NONE;
 }
 
 StaticIndexBufferInterface::~StaticIndexBufferInterface()
 {
 }
 
-void *StaticIndexBufferInterface::map(UINT requiredSpace, UINT *offset)
+bool StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
 {
-    void *mapPtr = NULL;
-
-    if (mIndexBuffer)
+    unsigned int curSize = getBufferSize();
+    if (curSize == 0)
     {
-        HRESULT result = mIndexBuffer->Lock(0, requiredSpace, &mapPtr, 0);
-
-        if (FAILED(result))
-        {
-            ERR(" Lock failed with error 0x%08x", result);
-            return NULL;
-        }
-
-        *offset = 0;
+        return setBufferSize(size, indexType);
     }
-
-    return mapPtr;
-}
-
-void StaticIndexBufferInterface::reserveSpace(UINT requiredSpace, GLenum type)
-{
-    if (!mIndexBuffer && mBufferSize == 0)
+    else if (curSize >= size && indexType == getIndexType())
     {
-        // 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;
+        return true;
     }
-    else if (mIndexBuffer && mBufferSize >= requiredSpace && mCacheType == type)
+    else
     {
-        // Already allocated
+        ERR("Static index buffers can't be resized");
+        UNREACHABLE();
+        return false;
     }
-    else UNREACHABLE();   // Static index buffers can't be resized
-}
-
-bool StaticIndexBufferInterface::lookupType(GLenum type)
-{
-    return mCacheType == type;
 }
 
 UINT StaticIndexBufferInterface::lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex)
diff --git a/src/libGLESv2/renderer/IndexBuffer.h b/src/libGLESv2/renderer/IndexBuffer.h
index 04a189b..c7bc3b6 100644
--- a/src/libGLESv2/renderer/IndexBuffer.h
+++ b/src/libGLESv2/renderer/IndexBuffer.h
@@ -10,9 +10,6 @@
 #ifndef LIBGLESV2_RENDERER_INDEXBUFFER_H_
 #define LIBGLESV2_RENDERER_INDEXBUFFER_H_
 
-#include <vector>
-#include <cstddef>
-
 #define GL_APICALL
 #include <GLES2/gl2.h>
 
@@ -22,8 +19,6 @@
 namespace rx
 {
 
-class Renderer9;
-
 class IndexBuffer
 {
   public:
@@ -56,60 +51,61 @@
 class IndexBufferInterface
 {
   public:
-    IndexBufferInterface(rx::Renderer9 *renderer, UINT size, D3DFORMAT format);
+    IndexBufferInterface(Renderer *renderer, bool dynamic);
     virtual ~IndexBufferInterface();
 
-    UINT size() const { return mBufferSize; }
-    virtual void *map(UINT requiredSpace, UINT *offset) = 0;
-    void unmap();
-    virtual void reserveSpace(UINT requiredSpace, GLenum type) = 0;
+    virtual bool reserveBufferSpace(unsigned int size, GLenum indexType) = 0;
 
-    IDirect3DIndexBuffer9 *getBuffer() const;
+    GLenum getIndexType() const;
+    unsigned int getBufferSize() const;
+
     unsigned int getSerial() const;
 
+    int mapBuffer(unsigned int size, void** outMappedMemory);
+    bool unmapBuffer();
+
+    IndexBuffer *getIndexBuffer() const;
+
   protected:
-    rx::Renderer9 *const mRenderer;   // D3D9_REPLACE
+    unsigned int getWritePosition() const;
+    void setWritePosition(unsigned int writePosition);
 
-    IDirect3DIndexBuffer9 *mIndexBuffer;
-    UINT mBufferSize;
+    bool discard();
 
-    unsigned int mSerial;
-    static unsigned int issueSerial();
-    static unsigned int mCurrentSerial;
+    bool setBufferSize(unsigned int bufferSize, GLenum indexType);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(IndexBufferInterface);
+
+    rx::Renderer *const mRenderer;
+
+    IndexBuffer* mIndexBuffer;
+
+    unsigned int mWritePosition;
+    bool mDynamic;
 };
 
 class StreamingIndexBufferInterface : public IndexBufferInterface
 {
   public:
-    StreamingIndexBufferInterface(rx::Renderer9 *renderer, UINT initialSize, D3DFORMAT format);
+    StreamingIndexBufferInterface(Renderer *renderer);
     ~StreamingIndexBufferInterface();
 
-    virtual void *map(UINT requiredSpace, UINT *offset);
-    virtual void reserveSpace(UINT requiredSpace, GLenum type);
-
-  private:
-    UINT mWritePosition;
+    virtual bool reserveBufferSpace(unsigned int size, GLenum indexType);
 };
 
 class StaticIndexBufferInterface : public IndexBufferInterface
 {
   public:
-    explicit StaticIndexBufferInterface(rx::Renderer9 *renderer);
+    explicit StaticIndexBufferInterface(Renderer *renderer);
     ~StaticIndexBufferInterface();
 
-    virtual void *map(UINT requiredSpace, UINT *offset);
-    virtual void reserveSpace(UINT requiredSpace, GLenum type);
+    virtual bool reserveBufferSpace(unsigned int size, GLenum indexType);
 
-    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;
diff --git a/src/libGLESv2/renderer/IndexDataManager.cpp b/src/libGLESv2/renderer/IndexDataManager.cpp
index 4a02919..8c4e7e6 100644
--- a/src/libGLESv2/renderer/IndexDataManager.cpp
+++ b/src/libGLESv2/renderer/IndexDataManager.cpp
@@ -18,28 +18,28 @@
 namespace rx
 {
 
-IndexDataManager::IndexDataManager(rx::Renderer9 *renderer) : mRenderer(renderer)
+IndexDataManager::IndexDataManager(Renderer *renderer) : mRenderer(renderer)
 {
-    mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
-
-    if (renderer->get32BitIndexSupport())
+    mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer);
+    if (!mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT))
     {
-        mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
-
-        if (!mStreamingBufferInt)
-        {
-            // Don't leave it in a half-initialized state
-            delete mStreamingBufferShort;
-            mStreamingBufferShort = NULL;
-        }
+        delete mStreamingBufferShort;
+        mStreamingBufferShort = NULL;
     }
-    else
+
+    mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer);
+    if (!mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
     {
+        delete mStreamingBufferInt;
         mStreamingBufferInt = NULL;
     }
 
     if (!mStreamingBufferShort)
     {
+        // Make sure both buffers are deleted.
+        delete mStreamingBufferInt;
+        mStreamingBufferInt = NULL;
+
         ERR("Failed to allocate the streaming index buffer(s).");
     }
 
@@ -53,7 +53,18 @@
     delete mCountingBuffer;
 }
 
-void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
+static unsigned int indexTypeSize(GLenum type)
+{
+    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);
+    }
+}
+
+static void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
 {
     if (type == GL_UNSIGNED_BYTE)
     {
@@ -77,7 +88,7 @@
 }
 
 template <class IndexType>
-void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
+static void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
 {
     *minIndex = indices[0];
     *maxIndex = indices[0];
@@ -89,7 +100,7 @@
     }
 }
 
-void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
+static void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
 {
     if (type == GL_UNSIGNED_BYTE)
     {
@@ -106,14 +117,14 @@
     else UNREACHABLE();
 }
 
-GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated, IDirect3DIndexBuffer9 **d3dIndexBuffer, unsigned int *serial)
+GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated)
 {
     if (!mStreamingBufferShort)
     {
         return GL_OUT_OF_MEMORY;
     }
 
-    D3DFORMAT format = (type == GL_UNSIGNED_INT) ? D3DFMT_INDEX32 : D3DFMT_INDEX16;
+    GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
     intptr_t offset = reinterpret_cast<intptr_t>(indices);
     bool alignedOffset = false;
 
@@ -127,7 +138,7 @@
           default: UNREACHABLE(); alignedOffset = false;
         }
 
-        if (typeSize(type) * count + offset > static_cast<std::size_t>(buffer->size()))
+        if (indexTypeSize(type) * count + offset > static_cast<std::size_t>(buffer->size()))
         {
             return GL_INVALID_OPERATION;
         }
@@ -141,14 +152,14 @@
     IndexBufferInterface *indexBuffer = streamingBuffer;
     UINT streamOffset = 0;
 
-    if (staticBuffer && staticBuffer->lookupType(type) && alignedOffset)
+    if (staticBuffer && staticBuffer->getIndexType() == type && alignedOffset)
     {
         indexBuffer = staticBuffer;
         streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex);
 
         if (streamOffset == -1)
         {
-            streamOffset = (offset / typeSize(type)) * indexSize(format);
+            streamOffset = (offset / indexTypeSize(type)) * indexTypeSize(destinationIndexType);
             computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
             staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
         }
@@ -159,10 +170,10 @@
 
         if (staticBuffer)
         {
-            if (staticBuffer->size() == 0 && alignedOffset)
+            if (staticBuffer->getBufferSize() == 0 && alignedOffset)
             {
                 indexBuffer = staticBuffer;
-                convertCount = buffer->size() / typeSize(type);
+                convertCount = buffer->size() / indexTypeSize(type);
             }
             else
             {
@@ -171,83 +182,81 @@
             }
         }
 
-        void *output = NULL;
-
-        if (indexBuffer)
+        if (!indexBuffer)
         {
-            indexBuffer->reserveSpace(convertCount * indexSize(format), type);
-            output = indexBuffer->map(indexSize(format) * convertCount, &streamOffset);
+            ERR("No valid index buffer.");
+            return GL_INVALID_OPERATION;
         }
 
-        if (output == NULL)
+        unsigned int bufferSizeRequired = convertCount * indexTypeSize(destinationIndexType);
+        indexBuffer->reserveBufferSpace(bufferSizeRequired, type);
+
+        void* output = NULL;
+        streamOffset = indexBuffer->mapBuffer(bufferSizeRequired, &output);
+        if (streamOffset == -1 || output == NULL)
         {
             ERR("Failed to map index buffer.");
             return GL_OUT_OF_MEMORY;
         }
 
         convertIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output);
-        indexBuffer->unmap();
+
+        if (!indexBuffer->unmapBuffer())
+        {
+            ERR("Failed to unmap index buffer.");
+            return GL_OUT_OF_MEMORY;
+        }
 
         computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
 
         if (staticBuffer)
         {
-            streamOffset = (offset / typeSize(type)) * indexSize(format);
+            streamOffset = (offset / indexTypeSize(type)) * indexTypeSize(destinationIndexType);
             staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
         }
     }
 
-    *d3dIndexBuffer = indexBuffer->getBuffer();
-    *serial = indexBuffer->getSerial();
-    translated->startIndex = streamOffset / indexSize(format);
+    translated->indexBuffer = indexBuffer->getIndexBuffer();
+    translated->serial = indexBuffer->getSerial();
+    translated->startIndex = streamOffset / indexTypeSize(destinationIndexType);
 
     if (buffer)
     {
-        buffer->promoteStaticUsage(count * typeSize(type));
+        buffer->promoteStaticUsage(count * indexTypeSize(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);
-    }
-}
-
 StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count)
 {
     if (count <= 65536)   // 16-bit indices
     {
         const unsigned int spaceNeeded = count * sizeof(unsigned short);
 
-        if (!mCountingBuffer || mCountingBuffer->size() < spaceNeeded)
+        if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded)
         {
             delete mCountingBuffer;
             mCountingBuffer = new StaticIndexBufferInterface(mRenderer);
-            mCountingBuffer->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
+            mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT);
 
-            UINT offset;
-            unsigned short *data = static_cast<unsigned short*>(mCountingBuffer->map(spaceNeeded, &offset));
-
-            if (data)
+            void* mappedMemory = NULL;
+            if (mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory) == -1 || mappedMemory == NULL)
             {
-                for(int i = 0; i < count; i++)
-                {
-                    data[i] = i;
-                }
+                ERR("Failed to map counting buffer.");
+                return NULL;
+            }
 
-                mCountingBuffer->unmap();
+            unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
+            for(int i = 0; i < count; i++)
+            {
+                data[i] = i;
+            }
+
+            if (!mCountingBuffer->unmapBuffer())
+            {
+                ERR("Failed to unmap counting buffer.");
+                return NULL;
             }
         }
     }
@@ -255,27 +264,36 @@
     {
         const unsigned int spaceNeeded = count * sizeof(unsigned int);
 
-        if (!mCountingBuffer || mCountingBuffer->size() < spaceNeeded)
+        if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded)
         {
             delete mCountingBuffer;
             mCountingBuffer = new StaticIndexBufferInterface(mRenderer);
-            mCountingBuffer->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
+            mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
 
-            UINT offset;
-            unsigned int *data = static_cast<unsigned int*>(mCountingBuffer->map(spaceNeeded, &offset));
-
-            if (data)
+            void* mappedMemory = NULL;
+            if (mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory) == -1 || mappedMemory == NULL)
             {
-                for(int i = 0; i < count; i++)
-                {
-                    data[i] = i;
-                }
+                ERR("Failed to map counting buffer.");
+                return NULL;
+            }
 
-                mCountingBuffer->unmap();
+            unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
+            for(int i = 0; i < count; i++)
+            {
+                data[i] = i;
+            }
+
+            if (!mCountingBuffer->unmapBuffer())
+            {
+                ERR("Failed to unmap counting buffer.");
+                return NULL;
             }
         }
     }
-    else return NULL;
+    else
+    {
+        return NULL;
+    }
 
     return mCountingBuffer;
 }
diff --git a/src/libGLESv2/renderer/IndexDataManager.h b/src/libGLESv2/renderer/IndexDataManager.h
index 3eb6558..a542f62 100644
--- a/src/libGLESv2/renderer/IndexDataManager.h
+++ b/src/libGLESv2/renderer/IndexDataManager.h
@@ -32,24 +32,24 @@
     UINT minIndex;
     UINT maxIndex;
     UINT startIndex;
+
+    IndexBuffer *indexBuffer;
+    unsigned int serial;
 };
 
 class IndexDataManager
 {
   public:
-    IndexDataManager(rx::Renderer9 *renderer);
+    explicit IndexDataManager(Renderer *renderer);
     virtual ~IndexDataManager();
 
-    GLenum prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated, IDirect3DIndexBuffer9 **indexBuffer, unsigned int *serial);
+    GLenum prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated);
     StaticIndexBufferInterface *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
+    Renderer *const mRenderer;
 
     StreamingIndexBufferInterface *mStreamingBufferShort;
     StreamingIndexBufferInterface *mStreamingBufferInt;
diff --git a/src/libGLESv2/renderer/Renderer9.cpp b/src/libGLESv2/renderer/Renderer9.cpp
index 781276f..b974965 100644
--- a/src/libGLESv2/renderer/Renderer9.cpp
+++ b/src/libGLESv2/renderer/Renderer9.cpp
@@ -1200,16 +1200,16 @@
 // Applies the indices and element array bindings to the Direct3D 9 device
 GLenum Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
 {
-    IDirect3DIndexBuffer9 *indexBuffer;
-    unsigned int serial;
-    GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo, &indexBuffer, &serial);
+    GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
 
     if (err == GL_NO_ERROR)
     {
-        if (serial != mAppliedIBSerial)
+        if (indexInfo->serial != mAppliedIBSerial)
         {
-            mDevice->SetIndices(indexBuffer);
-            mAppliedIBSerial = serial;
+            IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer);
+
+            mDevice->SetIndices(indexBuffer->getBuffer());
+            mAppliedIBSerial = indexInfo->serial;
         }
     }
 
@@ -1231,7 +1231,9 @@
         {
             if (mAppliedIBSerial != countingIB->getSerial())
             {
-                mDevice->SetIndices(countingIB->getBuffer());
+                IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer());
+
+                mDevice->SetIndices(indexBuffer->getBuffer());
                 mAppliedIBSerial = countingIB->getSerial();
             }
 
@@ -1281,138 +1283,161 @@
     }
 
     UINT startIndex = 0;
-    bool succeeded = false;
 
     if (get32BitIndexSupport())
     {
+        if (!mLineLoopIB)
+        {
+            mLineLoopIB = new StreamingIndexBufferInterface(this);
+            if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
+            {
+                delete mLineLoopIB;
+                mLineLoopIB = NULL;
+
+                ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
+                return error(GL_OUT_OF_MEMORY);
+            }
+        }
+
         const int spaceNeeded = (count + 1) * sizeof(unsigned int);
-
-        if (!mLineLoopIB)
+        if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
         {
-            mLineLoopIB = new StreamingIndexBufferInterface(this, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
+            ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
+            return error(GL_OUT_OF_MEMORY);
         }
 
-        if (mLineLoopIB)
+        void* mappedMemory = NULL;
+        int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory);
+        if (offset == -1 || mappedMemory == NULL)
         {
-            mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
+            ERR("Could not map index buffer for GL_LINE_LOOP.");
+            return error(GL_OUT_OF_MEMORY);
+        }
 
-            UINT offset = 0;
-            unsigned int *data = static_cast<unsigned int*>(mLineLoopIB->map(spaceNeeded, &offset));
-            startIndex = offset / 4;
-            
-            if (data)
+        startIndex = static_cast<UINT>(offset) / 4;
+        unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
+
+        switch (type)
+        {
+          case GL_NONE:   // Non-indexed draw
+            for (int i = 0; i < count; i++)
             {
-                switch (type)
-                {
-                  case GL_NONE:   // Non-indexed draw
-                    for (int i = 0; i < count; i++)
-                    {
-                        data[i] = i;
-                    }
-                    data[count] = 0;
-                    break;
-                  case GL_UNSIGNED_BYTE:
-                    for (int i = 0; i < count; i++)
-                    {
-                        data[i] = static_cast<const GLubyte*>(indices)[i];
-                    }
-                    data[count] = static_cast<const GLubyte*>(indices)[0];
-                    break;
-                  case GL_UNSIGNED_SHORT:
-                    for (int i = 0; i < count; i++)
-                    {
-                        data[i] = static_cast<const GLushort*>(indices)[i];
-                    }
-                    data[count] = static_cast<const GLushort*>(indices)[0];
-                    break;
-                  case GL_UNSIGNED_INT:
-                    for (int i = 0; i < count; i++)
-                    {
-                        data[i] = static_cast<const GLuint*>(indices)[i];
-                    }
-                    data[count] = static_cast<const GLuint*>(indices)[0];
-                    break;
-                  default: UNREACHABLE();
-                }
-
-                mLineLoopIB->unmap();
-                succeeded = true;
+                data[i] = i;
             }
+            data[count] = 0;
+            break;
+          case GL_UNSIGNED_BYTE:
+            for (int i = 0; i < count; i++)
+            {
+                data[i] = static_cast<const GLubyte*>(indices)[i];
+            }
+            data[count] = static_cast<const GLubyte*>(indices)[0];
+            break;
+          case GL_UNSIGNED_SHORT:
+            for (int i = 0; i < count; i++)
+            {
+                data[i] = static_cast<const GLushort*>(indices)[i];
+            }
+            data[count] = static_cast<const GLushort*>(indices)[0];
+            break;
+          case GL_UNSIGNED_INT:
+            for (int i = 0; i < count; i++)
+            {
+                data[i] = static_cast<const GLuint*>(indices)[i];
+            }
+            data[count] = static_cast<const GLuint*>(indices)[0];
+            break;
+          default: UNREACHABLE();
+        }
+
+        if (!mLineLoopIB->unmapBuffer())
+        {
+            ERR("Could not unmap index buffer for GL_LINE_LOOP.");
+            return error(GL_OUT_OF_MEMORY);
         }
     }
     else
     {
+        if (!mLineLoopIB)
+        {
+            mLineLoopIB = new StreamingIndexBufferInterface(this);
+            if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT))
+            {
+                delete mLineLoopIB;
+                mLineLoopIB = NULL;
+
+                ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP.");
+                return error(GL_OUT_OF_MEMORY);
+            }
+        }
+
         const int spaceNeeded = (count + 1) * sizeof(unsigned short);
-
-        if (!mLineLoopIB)
+        if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT))
         {
-            mLineLoopIB = new StreamingIndexBufferInterface(this, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
+            ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
+            return error(GL_OUT_OF_MEMORY);
         }
 
-        if (mLineLoopIB)
+        void* mappedMemory = NULL;
+        int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory);
+        if (offset == -1 || mappedMemory == NULL)
         {
-            mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
+            ERR("Could not map index buffer for GL_LINE_LOOP.");
+            return error(GL_OUT_OF_MEMORY);
+        }
 
-            UINT offset = 0;
-            unsigned short *data = static_cast<unsigned short*>(mLineLoopIB->map(spaceNeeded, &offset));
-            startIndex = offset / 2;
-            
-            if (data)
+        startIndex = static_cast<UINT>(offset) / 2;
+        unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
+
+        switch (type)
+        {
+          case GL_NONE:   // Non-indexed draw
+            for (int i = 0; i < count; i++)
             {
-                switch (type)
-                {
-                  case GL_NONE:   // Non-indexed draw
-                    for (int i = 0; i < count; i++)
-                    {
-                        data[i] = i;
-                    }
-                    data[count] = 0;
-                    break;
-                  case GL_UNSIGNED_BYTE:
-                    for (int i = 0; i < count; i++)
-                    {
-                        data[i] = static_cast<const GLubyte*>(indices)[i];
-                    }
-                    data[count] = static_cast<const GLubyte*>(indices)[0];
-                    break;
-                  case GL_UNSIGNED_SHORT:
-                    for (int i = 0; i < count; i++)
-                    {
-                        data[i] = static_cast<const GLushort*>(indices)[i];
-                    }
-                    data[count] = static_cast<const GLushort*>(indices)[0];
-                    break;
-                  case GL_UNSIGNED_INT:
-                    for (int i = 0; i < count; i++)
-                    {
-                        data[i] = static_cast<const GLuint*>(indices)[i];
-                    }
-                    data[count] = static_cast<const GLuint*>(indices)[0];
-                    break;
-                  default: UNREACHABLE();
-                }
-
-                mLineLoopIB->unmap();
-                succeeded = true;
+                data[i] = i;
             }
-        }
-    }
-    
-    if (succeeded)
-    {
-        if (mAppliedIBSerial != mLineLoopIB->getSerial())
-        {
-            mDevice->SetIndices(mLineLoopIB->getBuffer());
-            mAppliedIBSerial = mLineLoopIB->getSerial();
+            data[count] = 0;
+            break;
+          case GL_UNSIGNED_BYTE:
+            for (int i = 0; i < count; i++)
+            {
+                data[i] = static_cast<const GLubyte*>(indices)[i];
+            }
+            data[count] = static_cast<const GLubyte*>(indices)[0];
+            break;
+          case GL_UNSIGNED_SHORT:
+            for (int i = 0; i < count; i++)
+            {
+                data[i] = static_cast<const GLushort*>(indices)[i];
+            }
+            data[count] = static_cast<const GLushort*>(indices)[0];
+            break;
+          case GL_UNSIGNED_INT:
+            for (int i = 0; i < count; i++)
+            {
+                data[i] = static_cast<const GLuint*>(indices)[i];
+            }
+            data[count] = static_cast<const GLuint*>(indices)[0];
+            break;
+          default: UNREACHABLE();
         }
 
-        mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
+        if (!mLineLoopIB->unmapBuffer())
+        {
+            ERR("Could not unmap index buffer for GL_LINE_LOOP.");
+            return error(GL_OUT_OF_MEMORY);
+        }
     }
-    else
+
+    if (mAppliedIBSerial != mLineLoopIB->getSerial())
     {
-        ERR("Could not create a looping index buffer for GL_LINE_LOOP.");
-        return error(GL_OUT_OF_MEMORY);
+        IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(mLineLoopIB->getIndexBuffer());
+
+        mDevice->SetIndices(indexBuffer->getBuffer());
+        mAppliedIBSerial = mLineLoopIB->getSerial();
     }
+
+    mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
 }
 
 void Renderer9::applyShaders(gl::ProgramBinary *programBinary)