Make ScratchBuffer its own type.

This helper tool in Renderer11 can be useful in other back-ends,
or even in the front end.

BUG=angleproject:1635

Change-Id: I18ec19a891a9bdfa7b80dea1b8e308abf206906b
Reviewed-on: https://chromium-review.googlesource.com/450919
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/common/MemoryBuffer.cpp b/src/common/MemoryBuffer.cpp
index e7a3fb4..e720edc 100644
--- a/src/common/MemoryBuffer.cpp
+++ b/src/common/MemoryBuffer.cpp
@@ -11,19 +11,18 @@
 
 #include "common/debug.h"
 
-namespace rx
+namespace angle
 {
 
-MemoryBuffer::MemoryBuffer()
-    : mSize(0),
-      mData(NULL)
+// MemoryBuffer implementation.
+MemoryBuffer::MemoryBuffer() : mSize(0), mData(nullptr)
 {
 }
 
 MemoryBuffer::~MemoryBuffer()
 {
     free(mData);
-    mData = NULL;
+    mData = nullptr;
 }
 
 bool MemoryBuffer::resize(size_t size)
@@ -31,7 +30,7 @@
     if (size == 0)
     {
         free(mData);
-        mData = NULL;
+        mData = nullptr;
         mSize = 0;
         return true;
     }
@@ -43,7 +42,7 @@
 
     // Only reallocate if the size has changed.
     uint8_t *newMemory = reinterpret_cast<uint8_t*>(malloc(sizeof(uint8_t) * size));
-    if (newMemory == NULL)
+    if (newMemory == nullptr)
     {
         return false;
     }
@@ -77,4 +76,58 @@
     return mData;
 }
 
+// ScratchBuffer implementation.
+
+ScratchBuffer::ScratchBuffer(uint32_t lifetime) : mLifetime(lifetime), mResetCounter(lifetime)
+{
 }
+
+ScratchBuffer::~ScratchBuffer()
+{
+}
+
+bool ScratchBuffer::get(size_t requestedSize, MemoryBuffer **memoryBufferOut)
+{
+    if (mScratchMemory.size() == requestedSize)
+    {
+        mResetCounter    = mLifetime;
+        *memoryBufferOut = &mScratchMemory;
+        return true;
+    }
+
+    if (mScratchMemory.size() > requestedSize)
+    {
+        tick();
+    }
+
+    if (mResetCounter == 0 || mScratchMemory.size() < requestedSize)
+    {
+        mScratchMemory.resize(0);
+        if (!mScratchMemory.resize(requestedSize))
+        {
+            return false;
+        }
+        mResetCounter = mLifetime;
+    }
+
+    ASSERT(mScratchMemory.size() >= requestedSize);
+
+    *memoryBufferOut = &mScratchMemory;
+    return true;
+}
+
+void ScratchBuffer::tick()
+{
+    if (mResetCounter > 0)
+    {
+        --mResetCounter;
+    }
+}
+
+void ScratchBuffer::clear()
+{
+    mResetCounter = mLifetime;
+    mScratchMemory.resize(0);
+}
+
+}  // namespace angle