Skip visiting for allocator gathering in GrTextureOp when all proxies
are not recyclable.

Change-Id: I5ff9c48b3d7b37531a3f052bd5188a8afcacf3cb
Reviewed-on: https://skia-review.googlesource.com/c/161860
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index cef10cc..ac2f6d6 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -775,7 +775,7 @@
 
     const char* name() const override { return "AAConvexPathOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
diff --git a/src/gpu/ops/GrAAFillRectOp.cpp b/src/gpu/ops/GrAAFillRectOp.cpp
index 9d66299..120f714 100644
--- a/src/gpu/ops/GrAAFillRectOp.cpp
+++ b/src/gpu/ops/GrAAFillRectOp.cpp
@@ -207,7 +207,7 @@
 
     const char* name() const override { return "AAFillRectOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
diff --git a/src/gpu/ops/GrAAHairLinePathRenderer.cpp b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
index 9bbcaf1..50bc406 100644
--- a/src/gpu/ops/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
@@ -822,7 +822,7 @@
 
     const char* name() const override { return "AAHairlineOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
diff --git a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
index c40aa71..4029b3d 100644
--- a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
@@ -185,7 +185,7 @@
 
     const char* name() const override { return "AAFlatteningConvexPathOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
diff --git a/src/gpu/ops/GrAAStrokeRectOp.cpp b/src/gpu/ops/GrAAStrokeRectOp.cpp
index 0362946..248f502 100644
--- a/src/gpu/ops/GrAAStrokeRectOp.cpp
+++ b/src/gpu/ops/GrAAStrokeRectOp.cpp
@@ -182,7 +182,7 @@
 
     const char* name() const override { return "AAStrokeRect"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index b45b2cf..b616c29 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -113,7 +113,7 @@
     this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
 }
 
-void GrAtlasTextOp::visitProxies(const VisitProxyFunc& func) const {
+void GrAtlasTextOp::visitProxies(const VisitProxyFunc& func, VisitorType) const {
     fProcessors.visitProxies(func);
 }
 
diff --git a/src/gpu/ops/GrAtlasTextOp.h b/src/gpu/ops/GrAtlasTextOp.h
index 174f04c..df2f11c 100644
--- a/src/gpu/ops/GrAtlasTextOp.h
+++ b/src/gpu/ops/GrAtlasTextOp.h
@@ -68,7 +68,7 @@
 
     const char* name() const override { return "AtlasTextOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override;
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override;
 
     SkString dumpInfo() const override;
 
diff --git a/src/gpu/ops/GrCopySurfaceOp.h b/src/gpu/ops/GrCopySurfaceOp.h
index b93cbb7..c0760ec 100644
--- a/src/gpu/ops/GrCopySurfaceOp.h
+++ b/src/gpu/ops/GrCopySurfaceOp.h
@@ -23,9 +23,7 @@
 
     const char* name() const override { return "CopySurface"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
-        func(fSrc.get());
-    }
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override { func(fSrc.get()); }
 
     SkString dumpInfo() const override {
         SkString string;
diff --git a/src/gpu/ops/GrDashOp.cpp b/src/gpu/ops/GrDashOp.cpp
index 7a53a62..08ca0f0 100644
--- a/src/gpu/ops/GrDashOp.cpp
+++ b/src/gpu/ops/GrDashOp.cpp
@@ -279,7 +279,7 @@
 
     const char* name() const override { return "DashOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fProcessorSet.visitProxies(func);
     }
 
diff --git a/src/gpu/ops/GrDefaultPathRenderer.cpp b/src/gpu/ops/GrDefaultPathRenderer.cpp
index 4e038df..a653941 100644
--- a/src/gpu/ops/GrDefaultPathRenderer.cpp
+++ b/src/gpu/ops/GrDefaultPathRenderer.cpp
@@ -357,7 +357,7 @@
 
     const char* name() const override { return "DefaultPathOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
diff --git a/src/gpu/ops/GrDrawAtlasOp.h b/src/gpu/ops/GrDrawAtlasOp.h
index d15bd3c..fdb3476 100644
--- a/src/gpu/ops/GrDrawAtlasOp.h
+++ b/src/gpu/ops/GrDrawAtlasOp.h
@@ -38,7 +38,7 @@
 
     const char* name() const override { return "DrawAtlasOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
diff --git a/src/gpu/ops/GrDrawPathOp.h b/src/gpu/ops/GrDrawPathOp.h
index 3016fd7..cdd955e 100644
--- a/src/gpu/ops/GrDrawPathOp.h
+++ b/src/gpu/ops/GrDrawPathOp.h
@@ -34,7 +34,7 @@
                 ? RequiresDstTexture::kYes : RequiresDstTexture::kNo;
     }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fProcessorSet.visitProxies(func);
     }
 
diff --git a/src/gpu/ops/GrDrawVerticesOp.h b/src/gpu/ops/GrDrawVerticesOp.h
index fd40e461..79a8309 100644
--- a/src/gpu/ops/GrDrawVerticesOp.h
+++ b/src/gpu/ops/GrDrawVerticesOp.h
@@ -51,7 +51,7 @@
 
     const char* name() const override { return "DrawVerticesOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index 7c3d4bf..6d7345b 100644
--- a/src/gpu/ops/GrLatticeOp.cpp
+++ b/src/gpu/ops/GrLatticeOp.cpp
@@ -172,7 +172,7 @@
 
     const char* name() const override { return "NonAALatticeOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         func(fProxy.get());
         fHelper.visitProxies(func);
     }
diff --git a/src/gpu/ops/GrNonAAFillRectOp.cpp b/src/gpu/ops/GrNonAAFillRectOp.cpp
index fd8a9b3..9e5a8e2 100644
--- a/src/gpu/ops/GrNonAAFillRectOp.cpp
+++ b/src/gpu/ops/GrNonAAFillRectOp.cpp
@@ -149,7 +149,7 @@
 
     const char* name() const override { return "NonAAFillRectOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
@@ -279,7 +279,7 @@
 
     const char* name() const override { return "NonAAFillRectPerspectiveOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
diff --git a/src/gpu/ops/GrNonAAStrokeRectOp.cpp b/src/gpu/ops/GrNonAAStrokeRectOp.cpp
index 500b2eb..e7b2b17 100644
--- a/src/gpu/ops/GrNonAAStrokeRectOp.cpp
+++ b/src/gpu/ops/GrNonAAStrokeRectOp.cpp
@@ -63,7 +63,7 @@
 
     const char* name() const override { return "NonAAStrokeRectOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
diff --git a/src/gpu/ops/GrOp.h b/src/gpu/ops/GrOp.h
index d23f781..018de66 100644
--- a/src/gpu/ops/GrOp.h
+++ b/src/gpu/ops/GrOp.h
@@ -68,7 +68,22 @@
 
     typedef std::function<void(GrSurfaceProxy*)> VisitProxyFunc;
 
-    virtual void visitProxies(const VisitProxyFunc&) const {
+    /**
+     * Knowning the type of visitor may enable an op to be more efficient by skipping irrelevant
+     * proxies on visitProxies.
+     */
+    enum class VisitorType : unsigned {
+        /**
+         * Ops *may* skip proxy visitation for allocation for proxies that have the
+         * canSkipResourceAllocator() property.
+         */
+        kAllocatorGather,
+        /**
+         * Ops should visit all proxies.
+         */
+        kOther,
+    };
+    virtual void visitProxies(const VisitProxyFunc&, VisitorType = VisitorType::kOther) const {
         // This default implementation assumes the op has no proxies
     }
 
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index 0f36c1b..d8809b0 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -1137,7 +1137,7 @@
 
     const char* name() const override { return "CircleOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
@@ -1650,7 +1650,9 @@
 
     const char* name() const override { return "ButtCappedDashedCircleOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override { fHelper.visitProxies(func); }
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
+        fHelper.visitProxies(func);
+    }
 
     SkString dumpInfo() const override {
         SkString string;
@@ -1962,7 +1964,7 @@
 
     const char* name() const override { return "EllipseOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
@@ -2199,7 +2201,7 @@
 
     const char* name() const override { return "DIEllipseOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
@@ -2532,7 +2534,7 @@
 
     const char* name() const override { return "CircularRRectOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
@@ -2896,7 +2898,7 @@
 
     const char* name() const override { return "EllipticalRRectOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
diff --git a/src/gpu/ops/GrRegionOp.cpp b/src/gpu/ops/GrRegionOp.cpp
index b876295..f78fa94 100644
--- a/src/gpu/ops/GrRegionOp.cpp
+++ b/src/gpu/ops/GrRegionOp.cpp
@@ -85,7 +85,7 @@
 
     const char* name() const override { return "GrRegionOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index 220b219..9ade557 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -271,7 +271,7 @@
 
     const char* name() const override { return "SmallPathOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
 
         const sk_sp<GrTextureProxy>* proxies = fAtlas->getProxies();
diff --git a/src/gpu/ops/GrTessellatingPathRenderer.cpp b/src/gpu/ops/GrTessellatingPathRenderer.cpp
index 75620d3..9235cce 100644
--- a/src/gpu/ops/GrTessellatingPathRenderer.cpp
+++ b/src/gpu/ops/GrTessellatingPathRenderer.cpp
@@ -184,7 +184,7 @@
 
     const char* name() const override { return "TessellatingPathOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
         fHelper.visitProxies(func);
     }
 
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index ee1af7c..12fe7ad 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -618,7 +618,10 @@
 
     const char* name() const override { return "TextureOp"; }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
+    void visitProxies(const VisitProxyFunc& func, VisitorType visitor) const override {
+        if (visitor == VisitorType::kAllocatorGather && fCanSkipAllocatorGather) {
+            return;
+        }
         for (unsigned p = 0; p < fProxyCnt; ++p) {
             func(fProxies[p].fProxy);
         }
@@ -733,6 +736,8 @@
         fProxies[0] = {proxy.release(), 1};
         this->setBounds(bounds, HasAABloat(this->aaType() == GrAAType::kCoverage), IsZeroArea::kNo);
         fDomain = static_cast<unsigned>(draw.domain());
+        fCanSkipAllocatorGather =
+                static_cast<unsigned>(fProxies[0].fProxy->canSkipResourceAllocator());
     }
     TextureOp(const GrRenderTargetContext::TextureSetEntry set[], int cnt,
               GrSamplerState::Filter filter, GrColor color, GrAAType aaType,
@@ -748,11 +753,15 @@
         fProxyCnt = SkToUInt(cnt);
         SkRect bounds = SkRectPriv::MakeLargestInverted();
         bool aa = false;
+        fCanSkipAllocatorGather = static_cast<unsigned>(true);
         for (unsigned p = 0; p < fProxyCnt; ++p) {
             fProxies[p].fProxy = SkRef(set[p].fProxy.get());
             fProxies[p].fQuadCnt = 1;
             SkASSERT(fProxies[p].fProxy->textureType() == fProxies[0].fProxy->textureType());
             SkASSERT(fProxies[p].fProxy->config() == fProxies[0].fProxy->config());
+            if (!fProxies[p].fProxy->canSkipResourceAllocator()) {
+                fCanSkipAllocatorGather = static_cast<unsigned>(false);
+            }
             auto quad = GrPerspQuad(set[p].fDstRect, viewMatrix);
             bounds.joinPossiblyEmptyRect(quad.bounds());
             GrQuadAAFlags aaFlags = set[p].fAAFlags;
@@ -1003,7 +1012,8 @@
     unsigned fDomain : 1;
     // Used to track whether fProxy is ref'ed or has a pending IO after finalize() is called.
     unsigned fFinalized : 1;
-    unsigned fProxyCnt : 32 - 5;
+    unsigned fCanSkipAllocatorGather : 1;
+    unsigned fProxyCnt : 32 - 6;
     Proxy fProxies[1];
 
     typedef GrMeshDrawOp INHERITED;