Add GrResourceAllocator::makeBudgetHeadroom

This allows the caller to decide whether a plan is feasible before
committing to it. In this CL the drawing manager doesn't actually
call it, but we test it. We'll call it in a follow-up CL

Bug: skia:10877
Change-Id: Ie3a6c14a0196f595c522a0c961aba7b10c980711
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/394157
Commit-Queue: Adlai Holler <adlai@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index 94211f2..64d470c 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -622,22 +622,27 @@
 
 bool GrResourceCache::purgeToMakeHeadroom(size_t desiredHeadroomBytes) {
     AutoValidate av(this);
+    if (desiredHeadroomBytes > fMaxBytes) {
+        return false;
+    }
     if (this->wouldFit(desiredHeadroomBytes)) {
         return true;
     }
     fPurgeableQueue.sort();
 
-    size_t headroom = this->overBudget() ? 0 : fMaxBytes - fBudgetedBytes;
+    size_t projectedBudget = fBudgetedBytes;
     int purgeCnt = 0;
     for (int i = 0; i < fPurgeableQueue.count(); i++) {
         GrGpuResource* resource = fPurgeableQueue.at(i);
-        headroom += resource->gpuMemorySize();
-        if (headroom >= desiredHeadroomBytes) {
+        if (GrBudgetedType::kBudgeted == resource->resourcePriv().budgetedType()) {
+            projectedBudget -= resource->gpuMemorySize();
+        }
+        if (projectedBudget + desiredHeadroomBytes <= fMaxBytes) {
             purgeCnt = i + 1;
             break;
         }
     }
-    if (headroom < desiredHeadroomBytes) {
+    if (purgeCnt == 0) {
         return false;
     }