Make methods on GrGpuResource safe to call on abandoned resource

BUG=chromium:528908

Review URL: https://codereview.chromium.org/1367533004
This commit is contained in:
bsalomon 2015-09-24 07:07:40 -07:00 committed by Commit bot
parent 14eaaa61ca
commit c6363ef7b4
2 changed files with 42 additions and 2 deletions

View File

@ -46,6 +46,9 @@ void GrGpuResource::release() {
} }
void GrGpuResource::abandon() { void GrGpuResource::abandon() {
if (this->wasDestroyed()) {
return;
}
SkASSERT(fGpu); SkASSERT(fGpu);
this->onAbandon(); this->onAbandon();
get_resource_cache(fGpu)->resourceAccess().removeResource(this); get_resource_cache(fGpu)->resourceAccess().removeResource(this);
@ -104,6 +107,9 @@ void GrGpuResource::didChangeGpuMemorySize() const {
} }
void GrGpuResource::removeUniqueKey() { void GrGpuResource::removeUniqueKey() {
if (this->wasDestroyed()) {
return;
}
SkASSERT(fUniqueKey.isValid()); SkASSERT(fUniqueKey.isValid());
get_resource_cache(fGpu)->resourceAccess().removeUniqueKey(this); get_resource_cache(fGpu)->resourceAccess().removeUniqueKey(this);
} }
@ -177,14 +183,15 @@ void GrGpuResource::removeScratchKey() {
} }
void GrGpuResource::makeBudgeted() { void GrGpuResource::makeBudgeted() {
if (GrGpuResource::kUncached_LifeCycle == fLifeCycle) { if (!this->wasDestroyed() && GrGpuResource::kUncached_LifeCycle == fLifeCycle) {
fLifeCycle = kCached_LifeCycle; fLifeCycle = kCached_LifeCycle;
get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this); get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this);
} }
} }
void GrGpuResource::makeUnbudgeted() { void GrGpuResource::makeUnbudgeted() {
if (GrGpuResource::kCached_LifeCycle == fLifeCycle && !fUniqueKey.isValid()) { if (!this->wasDestroyed() && GrGpuResource::kCached_LifeCycle == fLifeCycle &&
!fUniqueKey.isValid()) {
fLifeCycle = kUncached_LifeCycle; fLifeCycle = kUncached_LifeCycle;
get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this); get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this);
} }

View File

@ -1250,6 +1250,38 @@ static void test_custom_data(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, *(int*) key3.getCustomData()->data() == 4132); 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<SkData> 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) { DEF_GPUTEST(ResourceCache, reporter, factory) {
for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
@ -1290,6 +1322,7 @@ DEF_GPUTEST(ResourceCache, reporter, factory) {
test_flush(reporter); test_flush(reporter);
test_large_resource_count(reporter); test_large_resource_count(reporter);
test_custom_data(reporter); test_custom_data(reporter);
test_abandoned(reporter);
} }
#endif #endif