Move the index data manager and draw calls into the renderer implementation.

TRAC #22016
Signed-off-by: Daniel Koch
Signed-off-by: Geoff Lang
Author: Nicolas Capens

git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1492 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 13fab27..2450cf5 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -27,8 +27,6 @@
 #include "libGLESv2/Renderbuffer.h"
 #include "libGLESv2/Shader.h"
 #include "libGLESv2/Texture.h"
-#include "libGLESv2/VertexDataManager.h"
-#include "libGLESv2/IndexDataManager.h"
 
 #undef near
 #undef far
@@ -153,9 +151,6 @@
     mState.unpackAlignment = 4;
     mState.packReverseRowOrder = false;
 
-    mIndexDataManager = NULL;
-    mLineLoopIB = NULL;
-
     mInvalidEnum = false;
     mInvalidValue = false;
     mInvalidOperation = false;
@@ -236,9 +231,6 @@
     mTexture2DZero.set(NULL);
     mTextureCubeMapZero.set(NULL);
 
-    delete mIndexDataManager;
-    delete mLineLoopIB;
-
     if (mMaskedClearSavedState)
     {
         mMaskedClearSavedState->Release();
@@ -253,8 +245,6 @@
 
     if (!mHasBeenCurrent)
     {
-        mIndexDataManager = new IndexDataManager(mRenderer);
-
         mSupportsShaderModel3 = mRenderer->getShaderModel3Support();
         mMaximumPointSize = mRenderer->getMaxPointSize();
         mSupportsVertexTexture = mRenderer->getVertexTextureSupport();
@@ -340,7 +330,6 @@
     }
 
     mAppliedProgramBinarySerial = 0;
-    mAppliedIBSerial = 0;
 
     mDxUniformsDirty = true;
 }
@@ -1845,23 +1834,6 @@
                                     mState.rasterizer.frontFace == GL_CCW, stencilSize);
 }
 
-// Applies the indices and element array bindings to the Direct3D 9 device
-GLenum Context::applyIndexBuffer(const GLvoid *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
-{
-    GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo);
-
-    if (err == GL_NO_ERROR)
-    {
-        if (indexInfo->serial != mAppliedIBSerial)
-        {
-            mDevice->SetIndices(indexInfo->indexBuffer);
-            mAppliedIBSerial = indexInfo->serial;
-        }
-    }
-
-    return err;
-}
-
 // Applies the shaders and shader constants to the Direct3D 9 device
 void Context::applyShaders()
 {
@@ -2065,13 +2037,7 @@
         return error(GL_INVALID_OPERATION);
     }
 
-    D3DPRIMITIVETYPE primitiveType;
-    int primitiveCount;
-
-    if(!gl_d3d9::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
-        return error(GL_INVALID_ENUM);
-
-    if (primitiveCount <= 0)
+    if (!mRenderer->applyPrimitiveType(mode, count))
     {
         return;
     }
@@ -2085,8 +2051,7 @@
 
     ProgramBinary *programBinary = getCurrentProgramBinary();
 
-    GLsizei repeatDraw = 1;
-    GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, first, count, instances, &repeatDraw);
+    GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, first, count, instances);
     if (err != GL_NO_ERROR)
     {
         return error(err);
@@ -2102,38 +2067,7 @@
 
     if (!skipDraw(mode))
     {
-        mRenderer->startScene();
-        
-        if (mode == GL_LINE_LOOP)
-        {
-            drawLineLoop(count, GL_NONE, NULL, 0);
-        }
-        else if (instances > 0)
-        {
-            StaticIndexBuffer *countingIB = mIndexDataManager->getCountingIndices(count);
-            if (countingIB)
-            {
-                if (mAppliedIBSerial != countingIB->getSerial())
-                {
-                    mDevice->SetIndices(countingIB->getBuffer());
-                    mAppliedIBSerial = countingIB->getSerial();
-                }
-
-                for (int i = 0; i < repeatDraw; i++)
-                {
-                    mDevice->DrawIndexedPrimitive(primitiveType, 0, 0, count, 0, primitiveCount);
-                }
-            }
-            else
-            {
-                ERR("Could not create a counting index buffer for glDrawArraysInstanced.");
-                return error(GL_OUT_OF_MEMORY);
-            }
-        }
-        else   // Regular case
-        {
-            mDevice->DrawPrimitive(primitiveType, 0, primitiveCount);
-        }
+        mRenderer->drawArrays(mode, count, instances);
     }
 }
 
@@ -2148,14 +2082,8 @@
     {
         return error(GL_INVALID_OPERATION);
     }
-
-    D3DPRIMITIVETYPE primitiveType;
-    int primitiveCount;
-
-    if(!gl_d3d9::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
-        return error(GL_INVALID_ENUM);
-
-    if (primitiveCount <= 0)
+    
+    if (!mRenderer->applyPrimitiveType(mode, count))
     {
         return;
     }
@@ -2168,7 +2096,7 @@
     applyState(mode);
 
     TranslatedIndexData indexInfo;
-    GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
+    GLenum err = mRenderer->applyIndexBuffer(indices, mState.elementArrayBuffer.get(), count, mode, type, &indexInfo);
     if (err != GL_NO_ERROR)
     {
         return error(err);
@@ -2177,8 +2105,7 @@
     ProgramBinary *programBinary = getCurrentProgramBinary();
 
     GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
-    GLsizei repeatDraw = 1;
-    err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, indexInfo.minIndex, vertexCount, instances, &repeatDraw);
+    err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, indexInfo.minIndex, vertexCount, instances);
     if (err != GL_NO_ERROR)
     {
         return error(err);
@@ -2194,19 +2121,7 @@
 
     if (!skipDraw(mode))
     {
-        mRenderer->startScene();
-
-        if (mode == GL_LINE_LOOP)
-        {
-            drawLineLoop(count, type, indices, indexInfo.minIndex);   
-        }
-        else
-        {
-            for (int i = 0; i < repeatDraw; i++)
-            {
-                mDevice->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount);
-            }
-        }
+        mRenderer->drawElements(mode, count, type, indices, mState.elementArrayBuffer.get());
     }
 }
 
@@ -2216,151 +2131,6 @@
     mRenderer->sync(block);
 }
 
-void Context::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex)
-{
-    // Get the raw indices for an indexed draw
-    if (type != GL_NONE && mState.elementArrayBuffer.get())
-    {
-        Buffer *indexBuffer = mState.elementArrayBuffer.get();
-        intptr_t offset = reinterpret_cast<intptr_t>(indices);
-        indices = static_cast<const GLubyte*>(indexBuffer->data()) + offset;
-    }
-
-    UINT startIndex = 0;
-    bool succeeded = false;
-
-    if (supports32bitIndices())
-    {
-        const int spaceNeeded = (count + 1) * sizeof(unsigned int);
-
-        if (!mLineLoopIB)
-        {
-            mLineLoopIB = new StreamingIndexBuffer(mRenderer, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
-        }
-
-        if (mLineLoopIB)
-        {
-            mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
-
-            UINT offset = 0;
-            unsigned int *data = static_cast<unsigned int*>(mLineLoopIB->map(spaceNeeded, &offset));
-            startIndex = offset / 4;
-            
-            if (data)
-            {
-                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;
-            }
-        }
-    }
-    else
-    {
-        const int spaceNeeded = (count + 1) * sizeof(unsigned short);
-
-        if (!mLineLoopIB)
-        {
-            mLineLoopIB = new StreamingIndexBuffer(mRenderer, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
-        }
-
-        if (mLineLoopIB)
-        {
-            mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
-
-            UINT offset = 0;
-            unsigned short *data = static_cast<unsigned short*>(mLineLoopIB->map(spaceNeeded, &offset));
-            startIndex = offset / 2;
-            
-            if (data)
-            {
-                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;
-            }
-        }
-    }
-    
-    if (succeeded)
-    {
-        if (mAppliedIBSerial != mLineLoopIB->getSerial())
-        {
-            mDevice->SetIndices(mLineLoopIB->getBuffer());
-            mAppliedIBSerial = mLineLoopIB->getSerial();
-        }
-
-        mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
-    }
-    else
-    {
-        ERR("Could not create a looping index buffer for GL_LINE_LOOP.");
-        return error(GL_OUT_OF_MEMORY);
-    }
-}
-
 void Context::recordInvalidEnum()
 {
     mInvalidEnum = true;
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index 69169e4..79be9e7 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -41,10 +41,6 @@
 
 namespace gl
 {
-struct TranslatedAttribute;
-struct TranslatedIndexData;
-
-class Buffer;
 class Shader;
 class Program;
 class ProgramBinary;
@@ -56,10 +52,8 @@
 class RenderbufferStorage;
 class Colorbuffer;
 class Depthbuffer;
-class StreamingIndexBuffer;
 class Stencilbuffer;
 class DepthStencilbuffer;
-class IndexDataManager;
 class Fence;
 class Query;
 
@@ -376,8 +370,6 @@
     void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances);
     void sync(bool block);   // flush/finish
 
-    void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex);
-
     void recordInvalidEnum();
     void recordInvalidValue();
     void recordInvalidOperation();
@@ -433,7 +425,6 @@
 
     bool applyRenderTarget(bool ignoreViewport);
     void applyState(GLenum drawMode);
-    GLenum applyIndexBuffer(const GLvoid *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
     void applyShaders();
     void applyTextures();
     void applyTextures(SamplerType type);
@@ -481,10 +472,6 @@
 
     std::string mExtensionString;
     std::string mRendererString;
-
-    IndexDataManager *mIndexDataManager;
-
-    StreamingIndexBuffer *mLineLoopIB;
     
     BindingPointer<Texture> mIncompleteTextures[TEXTURE_TYPE_COUNT];
 
@@ -505,7 +492,6 @@
     unsigned int mAppliedTextureSerialPS[MAX_TEXTURE_IMAGE_UNITS];
     unsigned int mAppliedTextureSerialVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF];
     unsigned int mAppliedProgramBinarySerial;
-    unsigned int mAppliedIBSerial;
     rx::RenderTarget::Desc mRenderTargetDesc; // D3D9_REPLACE
     bool mDxUniformsDirty;
     BindingPointer<ProgramBinary> mCurrentProgramBinary;
diff --git a/src/libGLESv2/IndexDataManager.cpp b/src/libGLESv2/IndexDataManager.cpp
index fc8c20b..c290d07 100644
--- a/src/libGLESv2/IndexDataManager.cpp
+++ b/src/libGLESv2/IndexDataManager.cpp
@@ -107,7 +107,7 @@
     else UNREACHABLE();
 }
 
-GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated)
+GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated, IDirect3DIndexBuffer9 **d3dIndexBuffer, unsigned int *serial)
 {
     if (!mStreamingBufferShort)
     {
@@ -198,8 +198,8 @@
         }
     }
 
-    translated->indexBuffer = indexBuffer->getBuffer();
-    translated->serial = indexBuffer->getSerial();
+    *d3dIndexBuffer = indexBuffer->getBuffer();
+    *serial = indexBuffer->getSerial();
     translated->startIndex = streamOffset / indexSize(format);
 
     if (buffer)
diff --git a/src/libGLESv2/IndexDataManager.h b/src/libGLESv2/IndexDataManager.h
index ba021c5..5f9f7a9 100644
--- a/src/libGLESv2/IndexDataManager.h
+++ b/src/libGLESv2/IndexDataManager.h
@@ -31,9 +31,6 @@
     UINT minIndex;
     UINT maxIndex;
     UINT startIndex;
-
-    IDirect3DIndexBuffer9 *indexBuffer;
-    unsigned int serial;
 };
 
 class IndexBuffer
@@ -128,7 +125,7 @@
     IndexDataManager(rx::Renderer9 *renderer);
     virtual ~IndexDataManager();
 
-    GLenum prepareIndexData(GLenum type, GLsizei count, Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated);
+    GLenum prepareIndexData(GLenum type, GLsizei count, Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated, IDirect3DIndexBuffer9 **indexBuffer, unsigned int *serial);
     StaticIndexBuffer *getCountingIndices(GLsizei count);
 
   private:
diff --git a/src/libGLESv2/renderer/Renderer.h b/src/libGLESv2/renderer/Renderer.h
index 60d579c..adf6b9f 100644
--- a/src/libGLESv2/renderer/Renderer.h
+++ b/src/libGLESv2/renderer/Renderer.h
@@ -41,6 +41,8 @@
 {
 class ProgramBinary;
 class VertexAttribute;
+class Buffer;
+struct TranslatedIndexData;
 }
 
 namespace rx
@@ -69,9 +71,6 @@
     virtual int generateConfigs(ConfigDesc **configDescList) = 0;
     virtual void deleteConfigs(ConfigDesc *configDescList) = 0;
 
-    virtual void startScene() = 0;
-    virtual void endScene() = 0;
-
     virtual void sync(bool block) = 0;
 
     virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0;
@@ -93,8 +92,12 @@
 
     virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer) = 0;
     virtual void applyShaders(gl::ProgramBinary *programBinary) = 0;
+    virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0;
+    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) = 0;
+    virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, gl::TranslatedIndexData *indexInfo) = 0;
 
-    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw) = 0;
+    virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances) = 0;
+    virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer) = 0;
 
     virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) = 0;
 
diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp
index ab4047d..7bd4022 100644
--- a/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/libGLESv2/renderer/Renderer11.cpp
@@ -230,16 +230,6 @@
     delete [] (configDescList);
 }
 
-void Renderer11::startScene()
-{
-    // TODO: nop in d3d11?
-}
-
-void Renderer11::endScene()
-{
-    // TODO: nop in d3d11?
-}
-
 void Renderer11::sync(bool block)
 {
     // TODO
@@ -436,7 +426,15 @@
     return true;
 }
 
-bool Renderer11::applyRenderTarget(gl::Framebuffer *frameBuffer)
+bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
+{
+    // TODO
+    UNIMPLEMENTED();
+
+    return false;
+}
+
+bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
 {
     // TODO
     UNIMPLEMENTED();
@@ -447,7 +445,7 @@
     return true;
 }
 
-GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw)
+GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
 {
     // TODO
     UNIMPLEMENTED();
@@ -455,6 +453,26 @@
     return GL_OUT_OF_MEMORY;
 }
 
+GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, gl::TranslatedIndexData *indexInfo)
+{
+    // TODO
+    UNIMPLEMENTED();
+
+    return GL_OUT_OF_MEMORY;
+}
+
+void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
+{
+    // TODO
+    UNIMPLEMENTED();
+}
+
+void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer)
+{
+    // TODO
+    UNIMPLEMENTED();
+}
+
 void Renderer11::applyShaders(gl::ProgramBinary *programBinary)
 {
     // TODO
diff --git a/src/libGLESv2/renderer/Renderer11.h b/src/libGLESv2/renderer/Renderer11.h
index 5e6c730..192282f 100644
--- a/src/libGLESv2/renderer/Renderer11.h
+++ b/src/libGLESv2/renderer/Renderer11.h
@@ -41,9 +41,6 @@
     virtual int generateConfigs(ConfigDesc **configDescList);
     virtual void deleteConfigs(ConfigDesc *configDescList);
 
-    virtual void startScene();
-    virtual void endScene();
-
     virtual void sync(bool block);
 
     virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
@@ -63,10 +60,14 @@
                              unsigned int renderTargetWidth, unsigned int renderTargetHeight,
                              gl::ProgramBinary *currentProgram, bool forceSetUniforms);
 
+    virtual bool applyPrimitiveType(GLenum mode, GLsizei count);
     virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
     virtual void applyShaders(gl::ProgramBinary *programBinary);
+    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances);
+    virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, gl::TranslatedIndexData *indexInfo);
 
-    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw);
+    virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances);
+    virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer);
 
     virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer);
 
diff --git a/src/libGLESv2/renderer/Renderer9.cpp b/src/libGLESv2/renderer/Renderer9.cpp
index 7469c04..05ecb55 100644
--- a/src/libGLESv2/renderer/Renderer9.cpp
+++ b/src/libGLESv2/renderer/Renderer9.cpp
@@ -10,9 +10,11 @@
 #include "libGLESv2/main.h"
 #include "libGLESv2/utilities.h"
 #include "libGLESv2/mathutil.h"
+#include "libGLESv2/Buffer.h"
 #include "libGLESv2/Framebuffer.h"
 #include "libGLESv2/Program.h"
 #include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/IndexDataManager.h"
 #include "libGLESv2/VertexDataManager.h"
 #include "libGLESv2/renderer/Renderer9.h"
 #include "libGLESv2/renderer/renderer9_utils.h"
@@ -87,9 +89,13 @@
 
     mMaxSupportedSamples = 0;
 
-    mVertexDataManager = NULL;
+    mAppliedIBSerial = 0;
 
     mMaskedClearSavedState = NULL;
+
+    mVertexDataManager = NULL;
+    mIndexDataManager = NULL;
+    mLineLoopIB = NULL;
 }
 
 Renderer9::~Renderer9()
@@ -398,9 +404,10 @@
 
     mSceneStarted = false;
 
-    ASSERT(!mBlit && !mVertexDataManager);
+    ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager);
     mBlit = new Blit(this);
     mVertexDataManager = new gl::VertexDataManager(this);
+    mIndexDataManager = new gl::IndexDataManager(this);
 }
 
 D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
@@ -975,6 +982,45 @@
     return true;
 }
 
+bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count)
+{
+    switch (mode)
+    {
+      case GL_POINTS:
+        mPrimitiveType = D3DPT_POINTLIST;
+        mPrimitiveCount = count;
+        break;
+      case GL_LINES:
+        mPrimitiveType = D3DPT_LINELIST;
+        mPrimitiveCount = count / 2;
+        break;
+      case GL_LINE_LOOP:
+        mPrimitiveType = D3DPT_LINESTRIP;
+        mPrimitiveCount = count - 1;   // D3D doesn't support line loops, so we draw the last line separately
+        break;
+      case GL_LINE_STRIP:
+        mPrimitiveType = D3DPT_LINESTRIP;
+        mPrimitiveCount = count - 1;
+        break;
+      case GL_TRIANGLES:
+        mPrimitiveType = D3DPT_TRIANGLELIST;
+        mPrimitiveCount = count / 3;
+        break;
+      case GL_TRIANGLE_STRIP:
+        mPrimitiveType = D3DPT_TRIANGLESTRIP;
+        mPrimitiveCount = count - 2;
+        break;
+      case GL_TRIANGLE_FAN:
+        mPrimitiveType = D3DPT_TRIANGLEFAN;
+        mPrimitiveCount = count - 2;
+        break;
+      default:
+        return error(GL_INVALID_ENUM, false);
+    }
+
+    return mPrimitiveCount > 0;
+}
+
 bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
 {
     // if there is no color attachment we must synthesize a NULL colorattachment
@@ -1094,7 +1140,7 @@
     return true;
 }
 
-GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw)
+GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
 {
     gl::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
     GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
@@ -1103,7 +1149,229 @@
         return err;
     }
     
-    return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, repeatDraw);
+    return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw);
+}
+
+// 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, gl::TranslatedIndexData *indexInfo)
+{
+    IDirect3DIndexBuffer9 *indexBuffer;
+    unsigned int serial;
+    GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo, &indexBuffer, &serial);
+
+    mIndexInfo.minIndex = indexInfo->minIndex;
+    mIndexInfo.maxIndex = indexInfo->maxIndex;
+    mIndexInfo.startIndex = indexInfo->startIndex;
+
+    if (err == GL_NO_ERROR)
+    {
+        if (serial != mAppliedIBSerial)
+        {
+            mDevice->SetIndices(indexBuffer);
+            mAppliedIBSerial = serial;
+        }
+    }
+
+    return err;
+}
+
+void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
+{
+    startScene();
+        
+    if (mode == GL_LINE_LOOP)
+    {
+        drawLineLoop(count, GL_NONE, NULL, 0, NULL);
+    }
+    else if (instances > 0)
+    {
+        gl::StaticIndexBuffer *countingIB = mIndexDataManager->getCountingIndices(count);
+        if (countingIB)
+        {
+            if (mAppliedIBSerial != countingIB->getSerial())
+            {
+                mDevice->SetIndices(countingIB->getBuffer());
+                mAppliedIBSerial = countingIB->getSerial();
+            }
+
+            for (int i = 0; i < mRepeatDraw; i++)
+            {
+                mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount);
+            }
+        }
+        else
+        {
+            ERR("Could not create a counting index buffer for glDrawArraysInstanced.");
+            return error(GL_OUT_OF_MEMORY);
+        }
+    }
+    else   // Regular case
+    {
+        mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount);
+    }
+}
+
+void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer)
+{
+    startScene();
+
+    if (mode == GL_LINE_LOOP)
+    {
+        drawLineLoop(count, type, indices, mIndexInfo.minIndex, elementArrayBuffer);
+    }
+    else
+    {
+        for (int i = 0; i < mRepeatDraw; i++)
+        {
+            GLsizei vertexCount = mIndexInfo.maxIndex - mIndexInfo.minIndex + 1;
+            mDevice->DrawIndexedPrimitive(mPrimitiveType, -(INT)mIndexInfo.minIndex, mIndexInfo.minIndex, vertexCount, mIndexInfo.startIndex, mPrimitiveCount);
+        }
+    }
+}
+
+void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
+{
+    // Get the raw indices for an indexed draw
+    if (type != GL_NONE && elementArrayBuffer)
+    {
+        gl::Buffer *indexBuffer = elementArrayBuffer;
+        intptr_t offset = reinterpret_cast<intptr_t>(indices);
+        indices = static_cast<const GLubyte*>(indexBuffer->data()) + offset;
+    }
+
+    UINT startIndex = 0;
+    bool succeeded = false;
+
+    if (get32BitIndexSupport())
+    {
+        const int spaceNeeded = (count + 1) * sizeof(unsigned int);
+
+        if (!mLineLoopIB)
+        {
+            mLineLoopIB = new gl::StreamingIndexBuffer(this, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
+        }
+
+        if (mLineLoopIB)
+        {
+            mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
+
+            UINT offset = 0;
+            unsigned int *data = static_cast<unsigned int*>(mLineLoopIB->map(spaceNeeded, &offset));
+            startIndex = offset / 4;
+            
+            if (data)
+            {
+                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;
+            }
+        }
+    }
+    else
+    {
+        const int spaceNeeded = (count + 1) * sizeof(unsigned short);
+
+        if (!mLineLoopIB)
+        {
+            mLineLoopIB = new gl::StreamingIndexBuffer(this, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
+        }
+
+        if (mLineLoopIB)
+        {
+            mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
+
+            UINT offset = 0;
+            unsigned short *data = static_cast<unsigned short*>(mLineLoopIB->map(spaceNeeded, &offset));
+            startIndex = offset / 2;
+            
+            if (data)
+            {
+                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;
+            }
+        }
+    }
+    
+    if (succeeded)
+    {
+        if (mAppliedIBSerial != mLineLoopIB->getSerial())
+        {
+            mDevice->SetIndices(mLineLoopIB->getBuffer());
+            mAppliedIBSerial = mLineLoopIB->getSerial();
+        }
+
+        mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
+    }
+    else
+    {
+        ERR("Could not create a looping index buffer for GL_LINE_LOOP.");
+        return error(GL_OUT_OF_MEMORY);
+    }
 }
 
 void Renderer9::applyShaders(gl::ProgramBinary *programBinary)
@@ -1339,6 +1607,12 @@
 
     delete mVertexDataManager;
     mVertexDataManager = NULL;
+
+    delete mIndexDataManager;
+    mIndexDataManager = NULL;
+
+    delete mLineLoopIB;
+    mLineLoopIB = NULL;
 }
 
 
diff --git a/src/libGLESv2/renderer/Renderer9.h b/src/libGLESv2/renderer/Renderer9.h
index abecc13..3bf38ab 100644
--- a/src/libGLESv2/renderer/Renderer9.h
+++ b/src/libGLESv2/renderer/Renderer9.h
@@ -23,13 +23,17 @@
 #include <D3Dcompiler.h>
 
 #include "common/angleutils.h"
+#include "libGLESv2/Context.h"
 #include "libGLESv2/renderer/ShaderCache.h"
 #include "libGLESv2/renderer/VertexDeclarationCache.h"
 #include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/IndexDataManager.h"
 
 namespace gl
 {
 class VertexDataManager;
+class StreamingIndexBuffer;
+struct TranslatedAttribute;
 }
 
 namespace rx
@@ -49,8 +53,8 @@
     virtual int generateConfigs(ConfigDesc **configDescList);
     virtual void deleteConfigs(ConfigDesc *configDescList);
 
-    virtual void startScene();
-    virtual void endScene();
+    void startScene();
+    void endScene();
 
     virtual void sync(bool block);
 
@@ -93,8 +97,12 @@
 
     virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
     virtual void applyShaders(gl::ProgramBinary *programBinary);
+    virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount);
+    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances);
+    virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, gl::TranslatedIndexData *indexInfo);
 
-    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw);
+    virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances);
+    virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer);
 
     virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer);
 
@@ -166,6 +174,8 @@
   private:
     DISALLOW_COPY_AND_ASSIGN(Renderer9);
 
+    void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
+
     void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray);
     bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged);
 
@@ -209,6 +219,11 @@
     D3DCAPS9 mDeviceCaps;
     D3DADAPTER_IDENTIFIER9 mAdapterIdentifier;
 
+    D3DPRIMITIVETYPE mPrimitiveType;
+    int mPrimitiveCount;
+    GLsizei mRepeatDraw;
+    gl::TranslatedIndexData mIndexInfo;
+
     bool mSceneStarted;
     bool mSupportsNonPower2Textures;
     bool mSupportsTextureFilterAnisotropy;
@@ -255,6 +270,8 @@
     gl::Color mCurBlendColor;
     GLuint mCurSampleMask;
 
+    unsigned int mAppliedIBSerial;
+
     // A pool of event queries that are currently unused.
     std::vector<IDirect3DQuery9*> mEventQueryPool;
     VertexShaderCache mVertexShaderCache;
@@ -262,6 +279,9 @@
 
     gl::VertexDataManager *mVertexDataManager;
     VertexDeclarationCache mVertexDeclarationCache;
+
+    gl::IndexDataManager *mIndexDataManager;
+    gl::StreamingIndexBuffer *mLineLoopIB;
 };
 
 }
diff --git a/src/libGLESv2/renderer/VertexDeclarationCache.h b/src/libGLESv2/renderer/VertexDeclarationCache.h
index 2b87277..2364e10 100644
--- a/src/libGLESv2/renderer/VertexDeclarationCache.h
+++ b/src/libGLESv2/renderer/VertexDeclarationCache.h
@@ -10,6 +10,7 @@
 #define LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_

 

 #include "libGLESv2/Context.h"

+#include "libGLESv2/VertexDataManager.h"

 

 namespace gl

 {

diff --git a/src/libGLESv2/renderer/renderer9_utils.cpp b/src/libGLESv2/renderer/renderer9_utils.cpp
index c11f5c6..fa63904 100644
--- a/src/libGLESv2/renderer/renderer9_utils.cpp
+++ b/src/libGLESv2/renderer/renderer9_utils.cpp
@@ -236,46 +236,6 @@
     }
 }
 
-bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
-                          D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount)
-{
-    switch (primitiveType)
-    {
-      case GL_POINTS:
-        *d3dPrimitiveType = D3DPT_POINTLIST;
-        *d3dPrimitiveCount = elementCount;
-        break;
-      case GL_LINES:
-        *d3dPrimitiveType = D3DPT_LINELIST;
-        *d3dPrimitiveCount = elementCount / 2;
-        break;
-      case GL_LINE_LOOP:
-        *d3dPrimitiveType = D3DPT_LINESTRIP;
-        *d3dPrimitiveCount = elementCount - 1;   // D3D doesn't support line loops, so we draw the last line separately
-        break;
-      case GL_LINE_STRIP:
-        *d3dPrimitiveType = D3DPT_LINESTRIP;
-        *d3dPrimitiveCount = elementCount - 1;
-        break;
-      case GL_TRIANGLES:
-        *d3dPrimitiveType = D3DPT_TRIANGLELIST;
-        *d3dPrimitiveCount = elementCount / 3;
-        break;
-      case GL_TRIANGLE_STRIP:
-        *d3dPrimitiveType = D3DPT_TRIANGLESTRIP;
-        *d3dPrimitiveCount = elementCount - 2;
-        break;
-      case GL_TRIANGLE_FAN:
-        *d3dPrimitiveType = D3DPT_TRIANGLEFAN;
-        *d3dPrimitiveCount = elementCount - 2;
-        break;
-      default:
-        return false;
-    }
-
-    return true;
-}
-
 D3DFORMAT ConvertRenderbufferFormat(GLenum format)
 {
     switch (format)
diff --git a/src/libGLESv2/renderer/renderer9_utils.h b/src/libGLESv2/renderer/renderer9_utils.h
index 957ae63..9436945 100644
--- a/src/libGLESv2/renderer/renderer9_utils.h
+++ b/src/libGLESv2/renderer/renderer9_utils.h
@@ -35,8 +35,6 @@
 DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha);
 D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy);
 void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy);
-bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
-                          D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount);
 D3DFORMAT ConvertRenderbufferFormat(GLenum format);
 D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples);