Heuristically optimize buffer usage.

TRAC #16343
Signed-off-by: Daniel Koch
Author: Nicolas Capens

git-svn-id: https://angleproject.googlecode.com/svn/trunk@616 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Buffer.cpp b/src/libGLESv2/Buffer.cpp
index 1873f28..2cd148e 100644
--- a/src/libGLESv2/Buffer.cpp
+++ b/src/libGLESv2/Buffer.cpp
@@ -23,15 +23,16 @@
     mSize = 0;
     mUsage = GL_DYNAMIC_DRAW;
 
-    mVertexBuffer = NULL;
-    mIndexBuffer = NULL;
+    mStaticVertexBuffer = NULL;
+    mStaticIndexBuffer = NULL;
+    mUnmodifiedDataUse = 0;
 }
 
 Buffer::~Buffer()
 {
     delete[] mContents;
-    delete mVertexBuffer;
-    delete mIndexBuffer;
+    delete mStaticVertexBuffer;
+    delete mStaticIndexBuffer;
 }
 
 void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
@@ -60,47 +61,55 @@
 
     if (usage == GL_STATIC_DRAW)
     {
-        mVertexBuffer = new StaticVertexBuffer(getDevice());
-        mIndexBuffer = new StaticIndexBuffer(getDevice());
+        mStaticVertexBuffer = new StaticVertexBuffer(getDevice());
+        mStaticIndexBuffer = new StaticIndexBuffer(getDevice());
     }
 }
 
 void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
 {
     memcpy(mContents + offset, data, size);
-
-    if ((mVertexBuffer && mVertexBuffer->size() != 0) || (mIndexBuffer && mIndexBuffer->size() != 0))
+    
+    if ((mStaticVertexBuffer && mStaticVertexBuffer->size() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->size() != 0))
     {
         invalidateStaticData();
-
-        if (mUsage == GL_STATIC_DRAW)
-        {
-            // If applications update the buffer data after it has already been used in a draw call,
-            // it most likely isn't used as a static buffer so we should fall back to streaming usage
-            // for best performance. So ignore the usage hint and don't create new static buffers.
-        //  mVertexBuffer = new StaticVertexBuffer(getDevice());
-        //  mIndexBuffer = new StaticIndexBuffer(getDevice());
-        }
     }
 }
 
-StaticVertexBuffer *Buffer::getVertexBuffer()
+StaticVertexBuffer *Buffer::getStaticVertexBuffer()
 {
-    return mVertexBuffer;
+    return mStaticVertexBuffer;
 }
 
-StaticIndexBuffer *Buffer::getIndexBuffer()
+StaticIndexBuffer *Buffer::getStaticIndexBuffer()
 {
-    return mIndexBuffer;
+    return mStaticIndexBuffer;
 }
 
 void Buffer::invalidateStaticData()
 {
-    delete mVertexBuffer;
-    mVertexBuffer = NULL;
+    delete mStaticVertexBuffer;
+    mStaticVertexBuffer = NULL;
 
-    delete mIndexBuffer;
-    mIndexBuffer = NULL;
+    delete mStaticIndexBuffer;
+    mStaticIndexBuffer = NULL;
+
+    mUnmodifiedDataUse = 0;
+}
+
+// Creates static buffers if sufficient used data has been left unmodified
+void Buffer::promoteStaticUsage(int dataSize)
+{
+    if (!mStaticVertexBuffer && !mStaticIndexBuffer)
+    {
+        mUnmodifiedDataUse += dataSize;
+
+        if (mUnmodifiedDataUse > 3 * mSize)
+        {
+            mStaticVertexBuffer = new StaticVertexBuffer(getDevice());
+            mStaticIndexBuffer = new StaticIndexBuffer(getDevice());
+        }
+    }
 }
 
 }