Instantiate clip atlases directly

Calls assign() directly on clip atlas proxies instead of using the
scary, unprotected back-pointer from a callback function.

Bug: chromium:928984
Change-Id: I253fc0f3280b97b6af4f1fde2d0094d58dc5d125
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/387296
Reviewed-by: Adlai Holler <adlai@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
index ec08d69..92add62 100644
--- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
+++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
@@ -87,6 +87,62 @@
                                                            mustCheckBounds));
 }
 
+namespace {
+
+// Iterates all GrCCClipPaths in an array of non-empty maps.
+class ClipMapsIter {
+public:
+    ClipMapsIter(sk_sp<GrCCPerOpsTaskPaths>* mapsList) : fMapsList(mapsList) {}
+
+    bool operator!=(const ClipMapsIter& that) {
+        if (fMapsList != that.fMapsList) {
+            return true;
+        }
+        // fPerOpsTaskClipPaths will be null when we are on the first element.
+        if (fPerOpsTaskClipPaths != that.fPerOpsTaskClipPaths) {
+            return true;
+        }
+        return fPerOpsTaskClipPaths && fClipPathsIter != that.fClipPathsIter;
+    }
+
+    void operator++() {
+        // fPerOpsTaskClipPaths is null when we are on the first element.
+        if (!fPerOpsTaskClipPaths) {
+            fPerOpsTaskClipPaths = &(*fMapsList)->fClipPaths;
+            SkASSERT(!fPerOpsTaskClipPaths->empty());  // We don't handle empty lists.
+            fClipPathsIter = fPerOpsTaskClipPaths->begin();
+        }
+        if ((++fClipPathsIter) == fPerOpsTaskClipPaths->end()) {
+            ++fMapsList;
+            fPerOpsTaskClipPaths = nullptr;
+        }
+    }
+
+    GrCCClipPath* operator->() {
+        // fPerOpsTaskClipPaths is null when we are on the first element.
+        const auto& it = (!fPerOpsTaskClipPaths) ? (*fMapsList)->fClipPaths.begin()
+                                                 : fClipPathsIter;
+        return &(it->second);
+    }
+
+private:
+    sk_sp<GrCCPerOpsTaskPaths>* fMapsList;
+    std::map<uint32_t, GrCCClipPath>* fPerOpsTaskClipPaths = nullptr;
+    std::map<uint32_t, GrCCClipPath>::iterator fClipPathsIter;
+};
+
+}  // namespace
+
+static void assign_atlas_textures(GrTexture* atlasTexture, ClipMapsIter nextPathToAssign,
+                                  const ClipMapsIter& end) {
+    if (!atlasTexture) {
+        return;
+    }
+    for (; nextPathToAssign != end; ++nextPathToAssign) {
+        nextPathToAssign->assignAtlasTexture(sk_ref_sp(atlasTexture));
+    }
+}
+
 void GrCoverageCountingPathRenderer::preFlush(
         GrOnFlushResourceProvider* onFlushRP, SkSpan<const uint32_t> taskIDs) {
     SkASSERT(!fFlushing);
@@ -122,14 +178,21 @@
     fPerFlushResources = std::make_unique<GrCCPerFlushResources>(onFlushRP, specs);
 
     // Layout the atlas(es) and render paths.
-    for (const auto& flushingPaths : fFlushingPaths) {
-        for (auto& clipsIter : flushingPaths->fClipPaths) {
-            clipsIter.second.renderPathInAtlas(fPerFlushResources.get(), onFlushRP);
+    ClipMapsIter it(fFlushingPaths.begin());
+    ClipMapsIter end(fFlushingPaths.end());
+    ClipMapsIter nextPathToAssign = it;  // The next GrCCClipPath to call assignAtlasTexture on.
+    for (; it != end; ++it) {
+        if (const GrCCAtlas* retiredAtlas =
+                it->renderPathInAtlas(fPerFlushResources.get(), onFlushRP)) {
+            assign_atlas_textures(retiredAtlas->textureProxy()->peekTexture(), nextPathToAssign,
+                                  it);
+            nextPathToAssign = it;
         }
     }
 
     // Allocate resources and then render the atlas(es).
-    fPerFlushResources->finalize(onFlushRP);
+    const GrCCAtlas* atlas = fPerFlushResources->finalize(onFlushRP);
+    assign_atlas_textures(atlas->textureProxy()->peekTexture(), nextPathToAssign, end);
 }
 
 void GrCoverageCountingPathRenderer::postFlush(GrDeferredUploadToken,