maintain RenderTask dependencies through merge

If they are not maintained, then the merge leaves links to
deleted RenderTarget nodes. This creates confusion while
trying to debug.

Change-Id: I9d98a4ed2887573ddc5dfa2bae1bb22d30879c5a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/402641
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Adlai Holler <adlai@google.com>
diff --git a/src/gpu/GrOpsTask.cpp b/src/gpu/GrOpsTask.cpp
index 20f97cc..6d36e48 100644
--- a/src/gpu/GrOpsTask.cpp
+++ b/src/gpu/GrOpsTask.cpp
@@ -715,38 +715,44 @@
         return 0;
     }
 
-    SkSpan<const sk_sp<GrOpsTask>> opsTasks(
+    SkSpan<const sk_sp<GrOpsTask>> mergingNodes(
             reinterpret_cast<const sk_sp<GrOpsTask>*>(tasks.data()), SkToSizeT(mergedCount));
     int addlDeferredProxyCount = 0;
     int addlProxyCount = 0;
     int addlOpChainCount = 0;
-    for (const auto& opsTask : opsTasks) {
-        addlDeferredProxyCount += opsTask->fDeferredProxies.count();
-        addlProxyCount += opsTask->fSampledProxies.count();
-        addlOpChainCount += opsTask->fOpChains.count();
-        fClippedContentBounds.join(opsTask->fClippedContentBounds);
-        fTotalBounds.join(opsTask->fTotalBounds);
-        fRenderPassXferBarriers |= opsTask->fRenderPassXferBarriers;
-        fUsesMSAASurface |= opsTask->fUsesMSAASurface;
-        SkDEBUGCODE(fNumClips += opsTask->fNumClips);
+    for (const auto& toMerge : mergingNodes) {
+        addlDeferredProxyCount += toMerge->fDeferredProxies.count();
+        addlProxyCount += toMerge->fSampledProxies.count();
+        addlOpChainCount += toMerge->fOpChains.count();
+        fClippedContentBounds.join(toMerge->fClippedContentBounds);
+        fTotalBounds.join(toMerge->fTotalBounds);
+        fRenderPassXferBarriers |= toMerge->fRenderPassXferBarriers;
+        fUsesMSAASurface |= toMerge->fUsesMSAASurface;
+        SkDEBUGCODE(fNumClips += toMerge->fNumClips);
     }
 
     fLastClipStackGenID = SK_InvalidUniqueID;
     fDeferredProxies.reserve_back(addlDeferredProxyCount);
     fSampledProxies.reserve_back(addlProxyCount);
     fOpChains.reserve_back(addlOpChainCount);
-    for (const auto& opsTask : opsTasks) {
-        fDeferredProxies.move_back_n(opsTask->fDeferredProxies.count(),
-                                     opsTask->fDeferredProxies.data());
-        fSampledProxies.move_back_n(opsTask->fSampledProxies.count(),
-                                    opsTask->fSampledProxies.data());
-        fOpChains.move_back_n(opsTask->fOpChains.count(),
-                              opsTask->fOpChains.data());
-        opsTask->fDeferredProxies.reset();
-        opsTask->fSampledProxies.reset();
-        opsTask->fOpChains.reset();
+    for (const auto& toMerge : mergingNodes) {
+        for (GrRenderTask* renderTask : toMerge->dependents()) {
+            renderTask->replaceDependency(toMerge.get(), this);
+        }
+        for (GrRenderTask* renderTask : toMerge->dependencies()) {
+            renderTask->replaceDependent(toMerge.get(), this);
+        }
+        fDeferredProxies.move_back_n(toMerge->fDeferredProxies.count(),
+                                     toMerge->fDeferredProxies.data());
+        fSampledProxies.move_back_n(toMerge->fSampledProxies.count(),
+                                    toMerge->fSampledProxies.data());
+        fOpChains.move_back_n(toMerge->fOpChains.count(),
+                              toMerge->fOpChains.data());
+        toMerge->fDeferredProxies.reset();
+        toMerge->fSampledProxies.reset();
+        toMerge->fOpChains.reset();
     }
-    fMustPreserveStencil = opsTasks.back()->fMustPreserveStencil;
+    fMustPreserveStencil = mergingNodes.back()->fMustPreserveStencil;
     return mergedCount;
 }
 
diff --git a/src/gpu/GrRenderTask.cpp b/src/gpu/GrRenderTask.cpp
index 9c8e06a..eedb84e 100644
--- a/src/gpu/GrRenderTask.cpp
+++ b/src/gpu/GrRenderTask.cpp
@@ -220,6 +220,26 @@
     }
 }
 
+void GrRenderTask::replaceDependency(const GrRenderTask* toReplace, GrRenderTask* replaceWith) {
+    for (auto& target : fDependencies) {
+        if (target == toReplace) {
+            target = replaceWith;
+            replaceWith->fDependents.push_back(this);
+            break;
+        }
+    }
+}
+
+void GrRenderTask::replaceDependent(const GrRenderTask* toReplace, GrRenderTask* replaceWith) {
+    for (auto& target : fDependents) {
+        if (target == toReplace) {
+            target = replaceWith;
+            replaceWith->fDependencies.push_back(this);
+            break;
+        }
+    }
+}
+
 bool GrRenderTask::dependsOn(const GrRenderTask* dependedOn) const {
     for (int i = 0; i < fDependencies.count(); ++i) {
         if (fDependencies[i] == dependedOn) {
diff --git a/src/gpu/GrRenderTask.h b/src/gpu/GrRenderTask.h
index 08da5dc..5c9d67f 100644
--- a/src/gpu/GrRenderTask.h
+++ b/src/gpu/GrRenderTask.h
@@ -79,6 +79,11 @@
     void addDependenciesFromOtherTask(GrRenderTask* otherTask);
 
     SkSpan<GrRenderTask*> dependencies() { return SkSpan<GrRenderTask*>(fDependencies); }
+    SkSpan<GrRenderTask*> dependents() { return SkSpan<GrRenderTask*>(fDependents); }
+
+    void replaceDependency(const GrRenderTask* toReplace, GrRenderTask* replaceWith);
+    void replaceDependent(const GrRenderTask* toReplace, GrRenderTask* replaceWith);
+
 
     /*
      * Does this renderTask depend on 'dependedOn'?