ccpr: Remove GrCCDrawPathsOp's back-pointer into CCPR

Bug: skia:7988
Change-Id: Ia05173e90fa2cda28de6ae2a9aaee577eaf4bc65
Reviewed-on: https://skia-review.googlesource.com/129621
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
index 0c1b493..ee0dbde 100644
--- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
+++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
@@ -13,8 +13,8 @@
 #include "SkMakeUnique.h"
 #include "SkPathOps.h"
 #include "ccpr/GrCCClipProcessor.h"
+#include "ccpr/GrCCDrawPathsOp.h"
 #include "ccpr/GrCCPathParser.h"
-#include "ccpr/GrCCPerFlushResources.h"
 
 using PathInstance = GrCCPathProcessor::Instance;
 
@@ -47,14 +47,22 @@
     return sk_sp<GrCoverageCountingPathRenderer>(ccpr);
 }
 
-GrCoverageCountingPathRenderer::GrCoverageCountingPathRenderer(bool drawCachablePaths)
-        : fDrawCachablePaths(drawCachablePaths) {
+GrCCPerOpListPaths* GrCoverageCountingPathRenderer::lookupPendingPaths(uint32_t opListID) {
+    auto it = fPendingPaths.find(opListID);
+    if (fPendingPaths.end() == it) {
+        auto paths = skstd::make_unique<GrCCPerOpListPaths>();
+        it = fPendingPaths.insert(std::make_pair(opListID, std::move(paths))).first;
+    }
+    return it->second.get();
 }
 
-GrCoverageCountingPathRenderer::~GrCoverageCountingPathRenderer() {
-    // Ensure no Ops exist that could have a dangling pointer back into this class.
-    SkASSERT(fRTPendingPathsMap.empty());
-    SkASSERT(0 == fNumOutstandingDrawOps);
+void GrCoverageCountingPathRenderer::adoptAndRecordOp(GrCCDrawPathsOp* op,
+                                                      const DrawPathArgs& args) {
+    GrRenderTargetContext* rtc = args.fRenderTargetContext;
+    if (uint32_t opListID = rtc->addDrawOp(*args.fClip, std::unique_ptr<GrDrawOp>(op))) {
+        // If the Op wasn't dropped or combined, give it a pointer to its owning GrCCPerOpListPaths.
+        op->wasRecorded(this->lookupPendingPaths(opListID));
+    }
 }
 
 GrPathRenderer::CanDrawPath GrCoverageCountingPathRenderer::onCanDrawPath(
@@ -112,25 +120,17 @@
         SkPath croppedPath;
         path.transform(*args.fViewMatrix, &croppedPath);
         crop_path(croppedPath, clipIBounds, &croppedPath);
-        this->adoptAndRecordOp(new GrCCDrawPathsOp(this, std::move(args.fPaint), clipIBounds,
+        this->adoptAndRecordOp(new GrCCDrawPathsOp(std::move(args.fPaint), clipIBounds,
                                                    SkMatrix::I(), croppedPath,
                                                    croppedPath.getBounds()), args);
         return true;
     }
 
-    this->adoptAndRecordOp(new GrCCDrawPathsOp(this, std::move(args.fPaint), clipIBounds,
+    this->adoptAndRecordOp(new GrCCDrawPathsOp(std::move(args.fPaint), clipIBounds,
                                                *args.fViewMatrix, path, devBounds), args);
     return true;
 }
 
-void GrCoverageCountingPathRenderer::adoptAndRecordOp(GrCCDrawPathsOp* op,
-                                                      const DrawPathArgs& args) {
-    GrRenderTargetContext* rtc = args.fRenderTargetContext;
-    if (uint32_t opListID = rtc->addDrawOp(*args.fClip, std::unique_ptr<GrDrawOp>(op))) {
-        op->wasRecorded(&fRTPendingPathsMap[opListID]);
-    }
-}
-
 std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipProcessor(
         GrProxyProvider* proxyProvider,
         uint32_t opListID, const SkPath& deviceSpacePath, const SkIRect& accessRect,
@@ -140,7 +140,7 @@
     SkASSERT(!fFlushing);
 
     GrCCClipPath& clipPath =
-            fRTPendingPathsMap[opListID].fClipPaths[deviceSpacePath.getGenerationID()];
+            this->lookupPendingPaths(opListID)->fClipPaths[deviceSpacePath.getGenerationID()];
     if (!clipPath.isInitialized()) {
         // This ClipPath was just created during lookup. Initialize it.
         const SkRect& pathDevBounds = deviceSpacePath.getBounds();
@@ -166,56 +166,55 @@
                                               const uint32_t* opListIDs, int numOpListIDs,
                                               SkTArray<sk_sp<GrRenderTargetContext>>* atlasDraws) {
     SkASSERT(!fFlushing);
-    SkASSERT(!fPerFlushResources);
+    SkASSERT(fFlushingPaths.empty());
     SkDEBUGCODE(fFlushing = true);
 
-    if (fRTPendingPathsMap.empty()) {
+    if (fPendingPaths.empty()) {
         return;  // Nothing to draw.
     }
 
-    // Count up the paths about to be flushed so we can preallocate buffers.
+    // Move the per-opList paths that are about to be flushed from fPendingPaths to fFlushingPaths,
+    // and count up the paths about to be flushed so we can preallocate buffers.
     int numPathDraws = 0;
     int numClipPaths = 0;
     GrCCPathParser::PathStats flushingPathStats;
-    fFlushingRTPathIters.reserve(numOpListIDs);
+    fFlushingPaths.reserve(numOpListIDs);
     for (int i = 0; i < numOpListIDs; ++i) {
-        auto iter = fRTPendingPathsMap.find(opListIDs[i]);
-        if (fRTPendingPathsMap.end() == iter) {
-            continue;
+        auto iter = fPendingPaths.find(opListIDs[i]);
+        if (fPendingPaths.end() == iter) {
+            continue;  // No paths on this opList.
         }
-        const GrCCRTPendingPaths& rtPendingPaths = iter->second;
 
-        for (const GrCCDrawPathsOp* op : rtPendingPaths.fDrawOps) {
+        fFlushingPaths.push_back(std::move(iter->second)).get();
+        fPendingPaths.erase(iter);
+
+        for (const GrCCDrawPathsOp* op : fFlushingPaths.back()->fDrawOps) {
             numPathDraws += op->countPaths(&flushingPathStats);
         }
-        for (const auto& clipsIter : rtPendingPaths.fClipPaths) {
+        for (const auto& clipsIter : fFlushingPaths.back()->fClipPaths) {
             flushingPathStats.statPath(clipsIter.second.deviceSpacePath());
         }
-        numClipPaths += rtPendingPaths.fClipPaths.size();
-
-        fFlushingRTPathIters.push_back(std::move(iter));
+        numClipPaths += fFlushingPaths.back()->fClipPaths.size();
     }
 
     if (0 == numPathDraws + numClipPaths) {
         return;  // Nothing to draw.
     }
 
-    auto resources = skstd::make_unique<GrCCPerFlushResources>(onFlushRP, numPathDraws,
-                                                               numClipPaths, flushingPathStats);
+    auto resources = sk_make_sp<GrCCPerFlushResources>(onFlushRP, numPathDraws, numClipPaths,
+                                                       flushingPathStats);
     if (!resources->isMapped()) {
         return;  // Some allocation failed.
     }
 
     // Layout atlas(es) and parse paths.
     SkDEBUGCODE(int numSkippedPaths = 0);
-    for (const auto& iter : fFlushingRTPathIters) {
-        GrCCRTPendingPaths* rtPendingPaths = &iter->second;
-
-        for (GrCCDrawPathsOp* op : rtPendingPaths->fDrawOps) {
+    for (const auto& flushingPaths : fFlushingPaths) {
+        for (GrCCDrawPathsOp* op : flushingPaths->fDrawOps) {
             op->setupResources(resources.get(), onFlushRP);
             SkDEBUGCODE(numSkippedPaths += op->numSkippedInstances_debugOnly());
         }
-        for (auto& clipsIter : rtPendingPaths->fClipPaths) {
+        for (auto& clipsIter : flushingPaths->fClipPaths) {
             clipsIter.second.placePathInAtlas(resources.get(), onFlushRP);
         }
     }
@@ -226,17 +225,16 @@
         return;
     }
 
-    fPerFlushResources = std::move(resources);
+    // Commit flushing paths to the resources once they are successfully completed.
+    for (auto& flushingPaths : fFlushingPaths) {
+        flushingPaths->fFlushResources = resources;
+    }
 }
 
 void GrCoverageCountingPathRenderer::postFlush(GrDeferredUploadToken, const uint32_t* opListIDs,
                                                int numOpListIDs) {
     SkASSERT(fFlushing);
-    fPerFlushResources.reset();
     // We wait to erase these until after flush, once Ops and FPs are done accessing their data.
-    for (const auto& iter : fFlushingRTPathIters) {
-        fRTPendingPathsMap.erase(iter);
-    }
-    fFlushingRTPathIters.reset();
+    fFlushingPaths.reset();
     SkDEBUGCODE(fFlushing = false);
 }