Fix deleting of GrGpuResource when abanonded and refs go to zero.

Abandoning would cause us to unref all the command buffer usages, but
then in notifyARefIsZero we would delete the abandoned resources even
though we still had a real ref. Then when that ref went away we would
crash.

Change-Id: I05dc2ba9a67c35c36a36704f4b81d6eef4e860e6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/382916
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Greg Daniel 2021-03-10 12:45:36 -05:00 committed by Skia Commit-Bot
parent 93330c9c4d
commit 9b6e30bd67
2 changed files with 20 additions and 2 deletions

View File

@ -160,8 +160,10 @@ void GrGpuResource::setUniqueKey(const GrUniqueKey& key) {
void GrGpuResource::notifyARefCntIsZero(LastRemovedRef removedRef) const {
if (this->wasDestroyed()) {
// We've already been removed from the cache. Goodbye cruel world!
delete this;
if (this->hasNoCommandBufferUsages() && !this->hasRef()) {
// We've already been removed from the cache. Goodbye cruel world!
delete this;
}
return;
}

View File

@ -370,6 +370,22 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessIDs_Gpu, reporter,
}
}
// No CPU test.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceAbandonPostFlush_Gpu, reporter, ctxInfo) {
auto direct = ctxInfo.directContext();
sk_sp<SkSurface> surface = create_gpu_surface(direct, kPremul_SkAlphaType, nullptr);
if (!surface) {
return;
}
// This flush can put command buffer refs on the GrGpuResource for the surface.
surface->flush();
direct->abandonContext();
// We pass the test if we don't hit any asserts or crashes when the ref on the surface goes away
// after we abanonded the context. One thing specifically this checks is to make sure we're
// correctly handling the mix of normal refs and command buffer refs, and correctly deleting
// the object at the right time.
}
// Verify that the right canvas commands trigger a copy on write.
static void test_copy_on_write(skiatest::Reporter* reporter, SkSurface* surface) {
SkCanvas* canvas = surface->getCanvas();