SkSurface copy-on-write can yield stale GPU render targets.
Prepare_rt_for_external_access() grabs the render target and then fires
access notifications.
But the notification handlers may trigger copy-on-write, causing the
returned render target to be stale (pointing at the detached snapshot).
We should grab the render target after firing notifications.
R=reed@google.com,bsalomon@google.com
Review URL: https://codereview.chromium.org/1276713002
diff --git a/tests/SurfaceTest.cpp b/tests/SurfaceTest.cpp
index 192abd7..157ccf6 100644
--- a/tests/SurfaceTest.cpp
+++ b/tests/SurfaceTest.cpp
@@ -622,6 +622,19 @@
}
}
+static void test_backend_cow(skiatest::Reporter* reporter, SkSurface* surface,
+ SkSurface::BackendHandleAccess mode,
+ GrBackendObject (*func)(SkSurface*, SkSurface::BackendHandleAccess)) {
+ GrBackendObject obj1 = func(surface, mode);
+ SkAutoTUnref<SkImage> snap1(surface->newImageSnapshot());
+
+ GrBackendObject obj2 = func(surface, mode);
+ SkAutoTUnref<SkImage> snap2(surface->newImageSnapshot());
+
+ // If the access mode triggers CoW, then the backend objects should reflect it.
+ REPORTER_ASSERT(reporter, (obj1 == obj2) == (snap1 == snap2));
+}
+
static void TestSurfaceCopyOnWrite(skiatest::Reporter* reporter, SurfaceType surfaceType,
GrContext* context) {
// Verify that the right canvas commands trigger a copy on write
@@ -700,6 +713,28 @@
testPaint))
EXPECT_COPY_ON_WRITE(drawTextOnPath(testText.c_str(), testText.size(), testPath, NULL, \
testPaint))
+
+ const SkSurface::BackendHandleAccess accessModes[] = {
+ SkSurface::kFlushRead_BackendHandleAccess,
+ SkSurface::kFlushWrite_BackendHandleAccess,
+ SkSurface::kDiscardWrite_BackendHandleAccess,
+ };
+
+ for (auto access : accessModes) {
+ test_backend_cow(reporter, surface, access,
+ [](SkSurface* s, SkSurface::BackendHandleAccess a) -> GrBackendObject {
+ return s->getTextureHandle(a);
+ });
+
+ test_backend_cow(reporter, surface, access,
+ [](SkSurface* s, SkSurface::BackendHandleAccess a) -> GrBackendObject {
+ GrBackendObject result;
+ if (!s->getRenderTargetHandle(&result, a)) {
+ return 0;
+ }
+ return result;
+ });
+ }
}
static void TestSurfaceWritableAfterSnapshotRelease(skiatest::Reporter* reporter,