Move NullColorbuffer handling from Framebuffer to Renderer9

Trac #22229

Uses a 12-entry LRU cache to avoid recreating them unnecessarily.

Signed-off-by: Nicolas Capens
Signed-off-by: Shannon Woods

git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1567 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/renderer/Renderer9.cpp b/src/libGLESv2/renderer/Renderer9.cpp
index d2eac1c..715aade 100644
--- a/src/libGLESv2/renderer/Renderer9.cpp
+++ b/src/libGLESv2/renderer/Renderer9.cpp
@@ -95,6 +95,15 @@
     mVertexDataManager = NULL;
     mIndexDataManager = NULL;
     mLineLoopIB = NULL;
+
+    mMaxNullColorbufferLRU = 0;
+    for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+    {
+        mNullColorbufferCache[i].lruCount = 0;
+        mNullColorbufferCache[i].width = 0;
+        mNullColorbufferCache[i].height = 0;
+        mNullColorbufferCache[i].buffer = NULL;
+    }
 }
 
 Renderer9::~Renderer9()
@@ -991,6 +1000,51 @@
     return mPrimitiveCount > 0;
 }
 
+
+gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer)
+{
+    if (!depthbuffer)
+    {
+        ERR("Unexpected null depthbuffer for depth-only FBO.");
+        return NULL;
+    }
+
+    GLsizei width  = depthbuffer->getWidth();
+    GLsizei height = depthbuffer->getHeight();
+
+    // search cached nullcolorbuffers
+    for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+    {
+        if (mNullColorbufferCache[i].buffer != NULL &&
+            mNullColorbufferCache[i].width == width &&
+            mNullColorbufferCache[i].height == height)
+        {
+            mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU;
+            return mNullColorbufferCache[i].buffer;
+        }
+    }
+
+    gl::Renderbuffer *nullbuffer = new gl::Renderbuffer(this, 0, new gl::Colorbuffer(this, width, height, GL_NONE, 0));
+
+    // add nullbuffer to the cache
+    NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0];
+    for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+    {
+        if (mNullColorbufferCache[i].lruCount < oldest->lruCount)
+        {
+            oldest = &mNullColorbufferCache[i];
+        }
+    }
+
+    delete oldest->buffer;
+    oldest->buffer = nullbuffer;
+    oldest->lruCount = ++mMaxNullColorbufferLRU;
+    oldest->width = width;
+    oldest->height = height;
+
+    return nullbuffer;
+}
+
 bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
 {
     // if there is no color attachment we must synthesize a NULL colorattachment
@@ -1002,7 +1056,7 @@
     }
     else
     {
-        renderbufferObject = framebuffer->getNullColorbuffer();
+        renderbufferObject = getNullColorbuffer(framebuffer->getDepthbuffer());
     }
     if (!renderbufferObject)
     {
@@ -1603,6 +1657,13 @@
 
     delete mLineLoopIB;
     mLineLoopIB = NULL;
+
+    for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+    {
+        delete mNullColorbufferCache[i].buffer;
+        mNullColorbufferCache[i].buffer = NULL;
+    }
+
 }