Copy on write for wrapped backend texture surfaces.
Makes SkImage_Gpu backed by two proxies, an original and a copy. The
image uses the original until a new render task is bound to it at which
point further uses of the image will use the copy. If the image is ever
used off a GrDirectContext we fall over to the copy. If the copy is
never used and never can be used by the next flush then the render
task that populates it is marked "skipped" and we don't perform the
copy.
Bug: skia:11208
Change-Id: Id255f4a733acc608c8a53c1a5633207aeafc404b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/366282
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrCopyRenderTask.cpp b/src/gpu/GrCopyRenderTask.cpp
index f2887e3..eb65dd5 100644
--- a/src/gpu/GrCopyRenderTask.cpp
+++ b/src/gpu/GrCopyRenderTask.cpp
@@ -29,13 +29,12 @@
return nullptr;
}
- sk_sp<GrCopyRenderTask> task(new GrCopyRenderTask(drawingMgr,
- std::move(src),
- srcRect,
- std::move(dst),
- dstPoint,
- origin));
- return std::move(task);
+ return sk_sp<GrRenderTask>(new GrCopyRenderTask(drawingMgr,
+ std::move(src),
+ srcRect,
+ std::move(dst),
+ dstPoint,
+ origin));
}
GrCopyRenderTask::GrCopyRenderTask(GrDrawingManager* drawingMgr,
@@ -49,6 +48,10 @@
}
void GrCopyRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
+ if (!fSrc) {
+ alloc->incOps();
+ return;
+ }
// This renderTask doesn't have "normal" ops. In this case we still need to add an interval (so
// fEndOfOpsTaskOpIndices will remain in sync), so we create a fake op# to capture the fact that
// we read fSrcView and copy to target view.
@@ -61,6 +64,8 @@
GrRenderTask::ExpectedOutcome GrCopyRenderTask::onMakeClosed(const GrCaps&,
SkIRect* targetUpdateBounds) {
+ // We don't expect to be marked skippable before being closed.
+ SkASSERT(fSrc);
*targetUpdateBounds = GrNativeRect::MakeIRectRelativeTo(
fOrigin,
this->target(0)->height(),
@@ -69,6 +74,10 @@
}
bool GrCopyRenderTask::onExecute(GrOpFlushState* flushState) {
+ if (!fSrc) {
+ // Did nothing, just like we're supposed to.
+ return true;
+ }
GrSurfaceProxy* dstProxy = this->target(0);
if (!fSrc->isInstantiated() || !dstProxy->isInstantiated()) {
return false;