diff --git a/src/gpu/GrGpuResource.cpp b/src/gpu/GrGpuResource.cpp index f8cb529314..a227fd2c0f 100644 --- a/src/gpu/GrGpuResource.cpp +++ b/src/gpu/GrGpuResource.cpp @@ -46,6 +46,9 @@ void GrGpuResource::release() { } void GrGpuResource::abandon() { + if (this->wasDestroyed()) { + return; + } SkASSERT(fGpu); this->onAbandon(); get_resource_cache(fGpu)->resourceAccess().removeResource(this); @@ -104,6 +107,9 @@ void GrGpuResource::didChangeGpuMemorySize() const { } void GrGpuResource::removeUniqueKey() { + if (this->wasDestroyed()) { + return; + } SkASSERT(fUniqueKey.isValid()); get_resource_cache(fGpu)->resourceAccess().removeUniqueKey(this); } @@ -177,14 +183,15 @@ void GrGpuResource::removeScratchKey() { } void GrGpuResource::makeBudgeted() { - if (GrGpuResource::kUncached_LifeCycle == fLifeCycle) { + if (!this->wasDestroyed() && GrGpuResource::kUncached_LifeCycle == fLifeCycle) { fLifeCycle = kCached_LifeCycle; get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this); } } void GrGpuResource::makeUnbudgeted() { - if (GrGpuResource::kCached_LifeCycle == fLifeCycle && !fUniqueKey.isValid()) { + if (!this->wasDestroyed() && GrGpuResource::kCached_LifeCycle == fLifeCycle && + !fUniqueKey.isValid()) { fLifeCycle = kUncached_LifeCycle; get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this); } diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp index 6370b92490..a4dd2a5940 100644 --- a/tests/ResourceCacheTest.cpp +++ b/tests/ResourceCacheTest.cpp @@ -1250,6 +1250,38 @@ static void test_custom_data(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, *(int*) key3.getCustomData()->data() == 4132); } +static void test_abandoned(skiatest::Reporter* reporter) { + Mock mock(10, 300); + GrContext* context = mock.context(); + TestResource* resource = new TestResource(context->getGpu()); + context->abandonContext(); + + REPORTER_ASSERT(reporter, resource->wasDestroyed()); + + // Call all the public methods on resource in the abandoned state. They shouldn't crash. + + int foo = 4132; + SkAutoTUnref data(SkData::NewWithCopy(&foo, sizeof(foo))); + resource->setCustomData(data.get()); + resource->getCustomData(); + resource->getUniqueID(); + resource->getUniqueKey(); + resource->wasDestroyed(); + resource->gpuMemorySize(); + resource->getContext(); + + resource->abandon(); + resource->resourcePriv().getScratchKey(); + resource->resourcePriv().isBudgeted(); + resource->resourcePriv().makeBudgeted(); + resource->resourcePriv().makeUnbudgeted(); + resource->resourcePriv().removeScratchKey(); + GrUniqueKey key; + make_unique_key<0>(&key, 1); + resource->resourcePriv().setUniqueKey(key); + resource->resourcePriv().removeUniqueKey(); +} + //////////////////////////////////////////////////////////////////////////////// DEF_GPUTEST(ResourceCache, reporter, factory) { for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { @@ -1290,6 +1322,7 @@ DEF_GPUTEST(ResourceCache, reporter, factory) { test_flush(reporter); test_large_resource_count(reporter); test_custom_data(reporter); + test_abandoned(reporter); } #endif