Add a shell GrResourceAllocator::Register class

The vision here is for Register to be a not-yet-allocated
surface, so that we can allocate Registers, then check
the memory consumption of that allocation before committing
to it.

Bug: skia:10877
Change-Id: I06cd3a66b9794b702bfd08ab30c644d0d2f2c945
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/385496
Commit-Queue: Adlai Holler <adlai@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrResourceAllocator.cpp b/src/gpu/GrResourceAllocator.cpp
index 5cb4cb2..67480ec 100644
--- a/src/gpu/GrResourceAllocator.cpp
+++ b/src/gpu/GrResourceAllocator.cpp
@@ -14,17 +14,26 @@
 #include "src/gpu/GrSurfaceProxy.h"
 #include "src/gpu/GrSurfaceProxyPriv.h"
 
-#if GR_TRACK_INTERVAL_CREATION
-    #include <atomic>
+#ifdef SK_DEBUG
+#include <atomic>
 
-    uint32_t GrResourceAllocator::Interval::CreateUniqueID() {
-        static std::atomic<uint32_t> nextID{1};
-        uint32_t id;
-        do {
-            id = nextID.fetch_add(1, std::memory_order_relaxed);
-        } while (id == SK_InvalidUniqueID);
-        return id;
-    }
+uint32_t GrResourceAllocator::Interval::CreateUniqueID() {
+    static std::atomic<uint32_t> nextID{1};
+    uint32_t id;
+    do {
+        id = nextID.fetch_add(1, std::memory_order_relaxed);
+    } while (id == SK_InvalidUniqueID);
+    return id;
+}
+
+uint32_t GrResourceAllocator::Register::CreateUniqueID() {
+    static std::atomic<uint32_t> nextID{1};
+    uint32_t id;
+    do {
+        id = nextID.fetch_add(1, std::memory_order_relaxed);
+    } while (id == SK_InvalidUniqueID);
+    return id;
+}
 #endif
 
 GrResourceAllocator::~GrResourceAllocator() {
@@ -80,7 +89,7 @@
         intvl->extendEnd(end);
         return;
     }
-    Interval* newIntvl = fIntervalAllocator.make<Interval>(proxy, start, end);
+    Interval* newIntvl = fInternalAllocator.make<Interval>(proxy, start, end);
 
     if (ActualUse::kYes == actualUse) {
         newIntvl->addUse();
@@ -186,34 +195,36 @@
 #endif
 
 // 'surface' can be reused. Add it back to the free pool.
-void GrResourceAllocator::recycleSurface(sk_sp<GrSurface> surface) {
-    const GrScratchKey &key = surface->resourcePriv().getScratchKey();
+void GrResourceAllocator::recycleRegister(Register* r) {
+    const GrScratchKey &key = r->scratchKey();
 
     if (!key.isValid()) {
         return; // can't do it w/o a valid scratch key
     }
 
+    GrSurface* surface = r->surface();
     if (surface->getUniqueKey().isValid()) {
         // If the surface has a unique key we throw it back into the resource cache.
-        // If things get really tight 'findSurfaceFor' may pull it back out but there is
+        // If things get really tight 'findRegisterFor' may pull it back out but there is
         // no need to have it in tight rotation.
         return;
     }
 
 #if GR_ALLOCATION_SPEW
-    SkDebugf("putting surface %d back into pool\n", surface->uniqueID().asUInt());
+    SkDebugf("putting register %d back into pool\n", r->uniqueID());
 #endif
     // TODO: fix this insertion so we get a more LRU-ish behavior
-    fFreePool.insert(key, surface.release());
+    fFreePool.insert(key, r);
 }
 
-// First try to reuse one of the recently allocated/used GrSurfaces in the free pool.
-// If we can't find a useable one, create a new one.
-sk_sp<GrSurface> GrResourceAllocator::findSurfaceFor(const GrSurfaceProxy* proxy) {
+// First try to reuse one of the recently allocated/used registers in the free pool.
+// If we can't find a usable one, try to instantiate a surface and wrap it in a new one.
+GrResourceAllocator::Register* GrResourceAllocator::findRegisterFor(const GrSurfaceProxy* proxy) {
     if (const auto& uniqueKey = proxy->getUniqueKey(); uniqueKey.isValid()) {
         // First try to reattach to a cached surface if the proxy is uniquely keyed
         if (sk_sp<GrSurface> surface = fResourceProvider->findByUniqueKey<GrSurface>(uniqueKey)) {
-            return surface;
+            // TODO: Find the register if we've encountered this unique key before.
+            return fInternalAllocator.make<Register>(std::move(surface));
         }
     }
 
@@ -222,11 +233,11 @@
 
     proxy->priv().computeScratchKey(*fResourceProvider->caps(), &key);
 
-    auto filter = [] (const GrSurface* s) {
+    auto filter = [] (const Register* r) {
         return true;
     };
-    sk_sp<GrSurface> surface(fFreePool.findAndRemove(key, filter));
-    if (surface) {
+    if (Register* r = fFreePool.findAndRemove(key, filter)) {
+        GrSurface* surface = r->surface();
         if (SkBudgeted::kYes == proxy->isBudgeted() &&
             GrBudgetedType::kBudgeted != surface->resourcePriv().budgetedType()) {
             // This gets the job done but isn't quite correct. It would be better to try to
@@ -234,11 +245,13 @@
             surface->resourcePriv().makeBudgeted();
         }
         SkASSERT(!surface->getUniqueKey().isValid());
-        return surface;
+        return r;
     }
 
-    // Failing that, try to grab a new one from the resource cache
-    return proxy->priv().createSurface(fResourceProvider);
+    if (sk_sp<GrSurface> surf = proxy->priv().createSurface(fResourceProvider)) {
+        return fInternalAllocator.make<Register>(std::move(surf));
+    }
+    return nullptr;
 }
 
 // Remove any intervals that end before the current index. Return their GrSurfaces
@@ -248,9 +261,9 @@
         Interval* intvl = fActiveIntvls.popHead();
         SkASSERT(!intvl->next());
 
-        if (GrSurface* surf = intvl->proxy()->peekSurface()) {
+        if (Register* r = intvl->getRegister()) {
             if (intvl->isSurfaceRecyclable()) {
-                this->recycleSurface(sk_ref_sp(surf));
+                this->recycleRegister(r);
             }
         }
     }
@@ -283,7 +296,10 @@
             if (!cur->proxy()->priv().doLazyInstantiation(fResourceProvider)) {
                 fFailedInstantiation = true;
             }
-        } else if (sk_sp<GrSurface> surface = this->findSurfaceFor(cur->proxy())) {
+        } else if (Register* r = this->findRegisterFor(cur->proxy())) {
+            sk_sp<GrSurface> surface = r->refSurface();
+
+            // propagate the proxy unique key to the surface if we have one.
             if (const auto& uniqueKey = cur->proxy()->getUniqueKey(); uniqueKey.isValid()) {
                 if (!surface->getUniqueKey().isValid()) {
                     fResourceProvider->assignUniqueKeyToResource(uniqueKey, surface.get());
@@ -298,6 +314,8 @@
 #endif
 
             SkASSERT(!cur->proxy()->peekSurface());
+            cur->setRegister(r);
+            // TODO: surface creation and assignment should happen later
             cur->proxy()->priv().assign(std::move(surface));
         } else {
             SkASSERT(!cur->proxy()->isInstantiated());