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
This commit is contained in:
parent
ebe06c0560
commit
e2639089bd
@ -28,7 +28,6 @@ SkSurface_Gpu::~SkSurface_Gpu() {
|
||||
|
||||
static GrRenderTarget* prepare_rt_for_external_access(SkSurface_Gpu* surface,
|
||||
SkSurface::BackendHandleAccess access) {
|
||||
GrRenderTarget* rt = surface->getDevice()->accessRenderTarget();
|
||||
switch (access) {
|
||||
case SkSurface::kFlushRead_BackendHandleAccess:
|
||||
break;
|
||||
@ -40,6 +39,9 @@ static GrRenderTarget* prepare_rt_for_external_access(SkSurface_Gpu* surface,
|
||||
surface->getDevice()->accessBitmap(false).notifyPixelsChanged();
|
||||
break;
|
||||
}
|
||||
|
||||
// Grab the render target *after* firing notifications, as it may get switched if CoW kicks in.
|
||||
GrRenderTarget* rt = surface->getDevice()->accessRenderTarget();
|
||||
rt->prepareForExternalIO();
|
||||
return rt;
|
||||
}
|
||||
|
@ -622,6 +622,19 @@ static void test_snap_alphatype(skiatest::Reporter* reporter, GrContextFactory*
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ static void TestSurfaceCopyOnWrite(skiatest::Reporter* reporter, SurfaceType sur
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user