Index data manager uses direct buffers for indices if possible.

TRAC #22297

Signed-off-by: Jamie Madill
Signed-off-by: Nicolas Capens
Author: Geoff Lang

git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1887 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/renderer/IndexDataManager.cpp b/src/libGLESv2/renderer/IndexDataManager.cpp
index e58a5ae..783e46a 100644
--- a/src/libGLESv2/renderer/IndexDataManager.cpp
+++ b/src/libGLESv2/renderer/IndexDataManager.cpp
@@ -128,9 +128,11 @@
     intptr_t offset = reinterpret_cast<intptr_t>(indices);
     bool alignedOffset = false;
 
+    BufferStorage *storage = NULL;
+
     if (buffer != NULL)
     {
-        BufferStorage *storage = buffer->getStorage();
+        storage = buffer->getStorage();
 
         switch (type)
         {
@@ -152,10 +154,18 @@
 
     StaticIndexBufferInterface *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL;
     IndexBufferInterface *indexBuffer = streamingBuffer;
-    BufferStorage *storage = buffer ? buffer->getStorage() : NULL;
+    bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() &&
+                         destinationIndexType == type;
     UINT streamOffset = 0;
 
-    if (staticBuffer && staticBuffer->getIndexType() == type && alignedOffset)
+    if (directStorage)
+    {
+        indexBuffer = streamingBuffer;
+        streamOffset = offset;
+        storage->markBufferUsage();
+        computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
+    }
+    else if (staticBuffer && staticBuffer->getIndexType() == type && alignedOffset)
     {
         indexBuffer = staticBuffer;
         streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex);
@@ -219,8 +229,9 @@
         }
     }
 
+    translated->storage = directStorage ? storage : NULL;
     translated->indexBuffer = indexBuffer->getIndexBuffer();
-    translated->serial = indexBuffer->getSerial();
+    translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial();
     translated->startIndex = streamOffset / indexTypeSize(destinationIndexType);
     translated->startOffset = streamOffset;
 
diff --git a/src/libGLESv2/renderer/IndexDataManager.h b/src/libGLESv2/renderer/IndexDataManager.h
index 2f71acf..fe9ca60 100644
--- a/src/libGLESv2/renderer/IndexDataManager.h
+++ b/src/libGLESv2/renderer/IndexDataManager.h
@@ -35,6 +35,7 @@
     UINT startOffset;   // In bytes
 
     IndexBuffer *indexBuffer;
+    BufferStorage *storage;
     unsigned int serial;
 };
 
diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp
index 88af239..83a2cc0 100644
--- a/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/libGLESv2/renderer/Renderer11.cpp
@@ -906,12 +906,28 @@
 
     if (err == GL_NO_ERROR)
     {
-        if (indexInfo->serial != mAppliedIBSerial || indexInfo->startOffset != mAppliedIBOffset)
+        if (indexInfo->storage)
+        {
+            if (indexInfo->serial != mAppliedStorageIBSerial || indexInfo->startOffset != mAppliedIBOffset)
+            {
+                BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage);
+                IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
+
+                mDeviceContext->IASetIndexBuffer(storage->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset);
+
+                mAppliedIBSerial = 0;
+                mAppliedStorageIBSerial = storage->getSerial();
+                mAppliedIBOffset = indexInfo->startOffset;
+            }
+        }
+        else if (indexInfo->serial != mAppliedIBSerial || indexInfo->startOffset != mAppliedIBOffset)
         {
             IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
 
             mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset);
+
             mAppliedIBSerial = indexInfo->serial;
+            mAppliedStorageIBSerial = 0;
             mAppliedIBOffset = indexInfo->startOffset;
         }
     }
@@ -1046,6 +1062,7 @@
 
         mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset);
         mAppliedIBSerial = mLineLoopIB->getSerial();
+        mAppliedStorageIBSerial = 0;
         mAppliedIBOffset = indexBufferOffset;
     }
 
@@ -1144,6 +1161,7 @@
 
         mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset);
         mAppliedIBSerial = mTriangleFanIB->getSerial();
+        mAppliedStorageIBSerial = 0;
         mAppliedIBOffset = indexBufferOffset;
     }
 
@@ -1696,6 +1714,7 @@
     mForceSetViewport = true;
 
     mAppliedIBSerial = 0;
+    mAppliedStorageIBSerial = 0;
     mAppliedIBOffset = 0;
 
     mAppliedProgramBinarySerial = 0;
diff --git a/src/libGLESv2/renderer/Renderer11.h b/src/libGLESv2/renderer/Renderer11.h
index e6c8db6..86088b4 100644
--- a/src/libGLESv2/renderer/Renderer11.h
+++ b/src/libGLESv2/renderer/Renderer11.h
@@ -284,6 +284,7 @@
     float mCurFar;
 
     unsigned int mAppliedIBSerial;
+    unsigned int mAppliedStorageIBSerial;
     unsigned int mAppliedIBOffset;
 
     unsigned int mAppliedProgramBinarySerial;
diff --git a/src/libGLESv2/renderer/Renderer9.cpp b/src/libGLESv2/renderer/Renderer9.cpp
index d837192..305a22f 100644
--- a/src/libGLESv2/renderer/Renderer9.cpp
+++ b/src/libGLESv2/renderer/Renderer9.cpp
@@ -1362,6 +1362,9 @@
 
     if (err == GL_NO_ERROR)
     {
+        // Directly binding the storage buffer is not supported for d3d9
+        ASSERT(indexInfo->storage == NULL);
+
         if (indexInfo->serial != mAppliedIBSerial)
         {
             IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer);