Add GrResourceAllocator::reset

This is used in the fallback code when reordering produces
a DAG that goes over our memory budget.

Bug: skia:10877
Change-Id: I13772b30e270eb546957b88586ded1cf42d2dbeb
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/397136
Commit-Queue: Adlai Holler <adlai@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index a85436a..99c8e69 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -205,7 +205,7 @@
     bool flushed = false;
 
     {
-        GrResourceAllocator alloc(dContext SkDEBUGCODE(, fDAG.count()));
+        GrResourceAllocator alloc(dContext);
         for (const auto& task : fDAG) {
             SkASSERT(task);
             task->gatherProxyIntervals(&alloc);
diff --git a/src/gpu/GrResourceAllocator.cpp b/src/gpu/GrResourceAllocator.cpp
index 1dff77d..68b36d2 100644
--- a/src/gpu/GrResourceAllocator.cpp
+++ b/src/gpu/GrResourceAllocator.cpp
@@ -387,7 +387,25 @@
     return fDContext->priv().getResourceCache()->purgeToMakeHeadroom(additionalBytesNeeded);
 }
 
+void GrResourceAllocator::reset() {
+    // NOTE: We do not reset the failedInstantiation flag because we currently do not attempt
+    // to recover from failed instantiations. The user is responsible for checking this flag and
+    // bailing early.
+    SkDEBUGCODE(fPlanned = false;)
+    SkDEBUGCODE(fAssigned = false;)
+    SkASSERT(fActiveIntvls.empty());
+    fFinishedIntvls = IntervalList();
+    fIntvlList = IntervalList();
+    fIntvlHash.reset();
+    fUniqueKeyRegisters.reset();
+    fFreePool.reset();
+    fInternalAllocator.reset();
+}
+
 bool GrResourceAllocator::assign() {
+    if (fFailedInstantiation) {
+        return false;
+    }
     SkASSERT(fPlanned && !fAssigned);
     SkDEBUGCODE(fAssigned = true;)
     auto resourceProvider = fDContext->priv().resourceProvider();
diff --git a/src/gpu/GrResourceAllocator.h b/src/gpu/GrResourceAllocator.h
index 8175dca..348d9b4 100644
--- a/src/gpu/GrResourceAllocator.h
+++ b/src/gpu/GrResourceAllocator.h
@@ -68,7 +68,7 @@
  */
 class GrResourceAllocator {
 public:
-    GrResourceAllocator(GrDirectContext* dContext SkDEBUGCODE(, int numOpsTasks))
+    GrResourceAllocator(GrDirectContext* dContext)
             : fDContext(dContext) {}
 
     ~GrResourceAllocator();
@@ -91,6 +91,8 @@
     void addInterval(GrSurfaceProxy*, unsigned int start, unsigned int end, ActualUse actualUse
                      SkDEBUGCODE(, bool isDirectDstRead = false));
 
+    bool failedInstantiation() const { return fFailedInstantiation; }
+
     // Generate an internal plan for resource allocation. After this you can optionally call
     // `makeBudgetHeadroom` to check whether that plan would go over our memory budget.
     // Fully-lazy proxies are also instantiated at this point so that their size can
@@ -101,6 +103,9 @@
     // purge them and return true. Otherwise return false.
     bool makeBudgetHeadroom();
 
+    // Clear all internal state in preparation for a new set of intervals.
+    void reset();
+
     // Instantiate and assign resources to all proxies.
     bool assign();
 
@@ -129,7 +134,7 @@
     };
     typedef SkTMultiMap<Register, GrScratchKey, FreePoolTraits> FreePoolMultiMap;
 
-    typedef SkTHashMap<uint32_t, Interval*, GrCheapHash>    IntvlHash;
+    typedef SkTHashMap<uint32_t, Interval*, GrCheapHash>        IntvlHash;
 
     struct UniqueKeyHash {
         uint32_t operator()(const GrUniqueKey& key) const { return key.hash(); }
@@ -235,10 +240,7 @@
     class IntervalList {
     public:
         IntervalList() = default;
-        ~IntervalList() {
-            // The only time we delete an IntervalList is in the GrResourceAllocator dtor.
-            // Since the arena allocator will clean up for us we don't bother here.
-        }
+        // N.B. No need for a destructor – the arena allocator will clean up for us.
 
         bool empty() const {
             SkASSERT(SkToBool(fHead) == SkToBool(fTail));
@@ -275,8 +277,8 @@
     SkDEBUGCODE(bool             fPlanned = false;)
     SkDEBUGCODE(bool             fAssigned = false;)
 
-    SkSTArenaAlloc<kInitialArenaSize>   fInternalAllocator; // intervals & registers live here
-    bool                                fFailedInstantiation = false;
+    SkSTArenaAllocWithReset<kInitialArenaSize>   fInternalAllocator; // intervals & registers
+    bool                                         fFailedInstantiation = false;
 };
 
 #endif // GrResourceAllocator_DEFINED