Allow multiple closed observers on GrOpsTask.

Bug: skia:10188

Change-Id: Ibed96f10c07feddbbf1e78d014c8ea346c91e53c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/287002
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrOpsTask.cpp b/src/gpu/GrOpsTask.cpp
index 976a186..c811883 100644
--- a/src/gpu/GrOpsTask.cpp
+++ b/src/gpu/GrOpsTask.cpp
@@ -378,7 +378,15 @@
     this->deleteOps();
 }
 
-////////////////////////////////////////////////////////////////////////////////
+void GrOpsTask::removeClosedObserver(GrOpsTaskClosedObserver* observer) {
+    SkASSERT(observer);
+    for (int i = 0; i < fClosedObservers.count(); ++i) {
+        if (fClosedObservers[i] == observer) {
+            fClosedObservers.removeShuffle(i);
+            --i;
+        }
+    }
+}
 
 void GrOpsTask::endFlush() {
     fLastClipStackGenID = SK_InvalidUniqueID;
@@ -877,11 +885,11 @@
 GrRenderTask::ExpectedOutcome GrOpsTask::onMakeClosed(
         const GrCaps& caps, SkIRect* targetUpdateBounds) {
     this->forwardCombine(caps);
-    SkScopeExit triggerObserver([&] {
-        if (fClosedObserver) {
-            fClosedObserver->wasClosed(*this);
-            fClosedObserver = nullptr;
+    SkScopeExit triggerObservers([&] {
+        for (const auto& o : fClosedObservers) {
+            o->wasClosed(*this);
         }
+        fClosedObservers.reset();
     });
     if (!this->isNoOp()) {
         GrSurfaceProxy* proxy = fTargetView.proxy();
diff --git a/src/gpu/GrOpsTask.h b/src/gpu/GrOpsTask.h
index bcc751d..0baf847 100644
--- a/src/gpu/GrOpsTask.h
+++ b/src/gpu/GrOpsTask.h
@@ -37,6 +37,10 @@
 class GrOpsTaskClosedObserver {
 public:
     virtual ~GrOpsTaskClosedObserver() = 0;
+    /**
+     * Called when the GrOpsTask is closed. Must not add/remove observers to 'task'.
+     * The GrOpsTask will remove all its observers after it finishes calling wasClosed().
+     */
     virtual void wasClosed(const GrOpsTask& task) = 0;
 };
 
@@ -52,8 +56,12 @@
 
     GrOpsTask* asOpsTask() override { return this; }
 
-    /** Each OpsTask supports a single observer at a time. */
-    void setClosedObserver(GrOpsTaskClosedObserver* observer) { fClosedObserver = observer; }
+    void addClosedObserver(GrOpsTaskClosedObserver* observer) {
+        SkASSERT(observer);
+        fClosedObservers.push_back(observer);
+    }
+
+    void removeClosedObserver(GrOpsTaskClosedObserver* observer);
 
     bool isEmpty() const { return fOpChains.empty(); }
 
@@ -295,7 +303,8 @@
     // into the owning DDL.
     GrRecordingContext::Arenas fArenas;
     GrAuditTrail*              fAuditTrail;
-    GrOpsTaskClosedObserver*   fClosedObserver = nullptr;
+
+    SkSTArray<2, GrOpsTaskClosedObserver*, true> fClosedObservers;
 
     GrLoadOp fColorLoadOp = GrLoadOp::kLoad;
     SkPMColor4f fLoadClearColor = SK_PMColor4fTRANSPARENT;
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index e1da02f..c0a3835 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -383,7 +383,7 @@
         , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
         , fManagedOpsTask(managedOpsTask) {
     if (fOpsTask) {
-        fOpsTask->setClosedObserver(this);
+        fOpsTask->addClosedObserver(this);
     }
     SkASSERT(this->asSurfaceProxy() == fWriteView.proxy());
     SkASSERT(this->origin() == fWriteView.origin());
@@ -403,7 +403,7 @@
 GrRenderTargetContext::~GrRenderTargetContext() {
     ASSERT_SINGLE_OWNER
     if (fOpsTask) {
-        fOpsTask->setClosedObserver(nullptr);
+        fOpsTask->removeClosedObserver(this);
     }
 }
 
@@ -441,7 +441,7 @@
             // values?
             newOpsTask->setInitialStencilContent(GrOpsTask::StencilContent::kPreserved);
         }
-        newOpsTask->setClosedObserver(this);
+        newOpsTask->addClosedObserver(this);
         fOpsTask = std::move(newOpsTask);
     }
     SkASSERT(!fOpsTask->isClosed());