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());