Allow unbudgeted resources to be recycled by the cache as scratch.
Review URL: https://codereview.chromium.org/870743002
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index 6b7d68c..f98aaf1 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -97,8 +97,10 @@
this->registerWithCache();
}
- static TestResource* CreateScratchTestResource(GrGpu* gpu, SimulatedProperty property) {
- return SkNEW_ARGS(TestResource, (gpu, property, kScratchConstructor));
+ static TestResource* CreateScratchTestResource(GrGpu* gpu,
+ SimulatedProperty property,
+ bool cached = true) {
+ return SkNEW_ARGS(TestResource, (gpu, property, cached, kScratchConstructor));
}
~TestResource() {
@@ -132,8 +134,8 @@
private:
static const int kScratchKeyFieldCnt = 6;
- TestResource(GrGpu* gpu, SimulatedProperty property, ScratchConstructor)
- : INHERITED(gpu, kCached_LifeCycle)
+ TestResource(GrGpu* gpu, SimulatedProperty property, bool cached, ScratchConstructor)
+ : INHERITED(gpu, cached ? kCached_LifeCycle : kUncached_LifeCycle)
, fToDelete(NULL)
, fSize(kDefaultSize)
, fProperty(property) {
@@ -154,16 +156,29 @@
};
int TestResource::fNumAlive = 0;
-static void test_no_key(skiatest::Reporter* reporter) {
- SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
- REPORTER_ASSERT(reporter, SkToBool(context));
- if (NULL == context) {
- return;
+class Mock {
+public:
+ Mock(int maxCnt, size_t maxBytes) {
+ fContext.reset(GrContext::CreateMockContext());
+ SkASSERT(fContext);
+ fContext->setResourceCacheLimits(maxCnt, maxBytes);
+ GrResourceCache2* cache2 = fContext->getResourceCache2();
+ cache2->purgeAllUnlocked();
+ SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
}
- context->setResourceCacheLimits(10, 30000);
- GrResourceCache2* cache2 = context->getResourceCache2();
- cache2->purgeAllUnlocked();
- SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
+
+ GrResourceCache2* cache() { return fContext->getResourceCache2(); }
+
+ GrContext* context() { return fContext; }
+
+private:
+ SkAutoTUnref<GrContext> fContext;
+};
+
+static void test_no_key(skiatest::Reporter* reporter) {
+ Mock mock(10, 30000);
+ GrContext* context = mock.context();
+ GrResourceCache2* cache2 = mock.cache();
// Create a bunch of resources with no keys
TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
@@ -217,16 +232,9 @@
}
static void test_budgeting(skiatest::Reporter* reporter) {
- SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
- REPORTER_ASSERT(reporter, SkToBool(context));
- if (NULL == context) {
- return;
- }
- context->setResourceCacheLimits(10, 300);
- GrResourceCache2* cache2 = context->getResourceCache2();
- cache2->purgeAllUnlocked();
- SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
- SkASSERT(0 == cache2->getBudgetedResourceCount() && 0 == cache2->getBudgetedResourceBytes());
+ Mock mock(10, 300);
+ GrContext* context = mock.context();
+ GrResourceCache2* cache2 = mock.cache();
GrContentKey contentKey;
make_content_key<0>(&contentKey, 0);
@@ -310,16 +318,9 @@
}
static void test_unbudgeted(skiatest::Reporter* reporter) {
- SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
- REPORTER_ASSERT(reporter, SkToBool(context));
- if (NULL == context) {
- return;
- }
- context->setResourceCacheLimits(10, 300);
- GrResourceCache2* cache2 = context->getResourceCache2();
- cache2->purgeAllUnlocked();
- SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
- SkASSERT(0 == cache2->getBudgetedResourceCount() && 0 == cache2->getBudgetedResourceBytes());
+ Mock mock(10, 30000);
+ GrContext* context = mock.context();
+ GrResourceCache2* cache2 = mock.cache();
GrContentKey contentKey;
make_content_key<0>(&contentKey, 0);
@@ -382,16 +383,70 @@
REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceBytes());
}
-static void test_duplicate_scratch_key(skiatest::Reporter* reporter) {
- SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
- REPORTER_ASSERT(reporter, SkToBool(context));
- if (NULL == context) {
- return;
+static void test_unbudgeted_to_scratch(skiatest::Reporter* reporter) {
+ Mock mock(10, 300);
+ GrContext* context = mock.context();
+ GrResourceCache2* cache2 = mock.cache();
+
+ TestResource* resource =
+ TestResource::CreateScratchTestResource(context->getGpu(),
+ TestResource::kProperty1_SimulatedProperty, false);
+ GrScratchKey key;
+ TestResource::ComputeScratchKey(TestResource::kProperty1_SimulatedProperty, &key);
+
+ size_t size = resource->gpuMemorySize();
+ for (int i = 0; i < 2; ++i) {
+ // Since this resource is unbudgeted, it should not be reachable as scratch.
+ REPORTER_ASSERT(reporter, resource->cacheAccess().getScratchKey() == key);
+ REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch());
+ REPORTER_ASSERT(reporter, !resource->cacheAccess().isBudgeted());
+ REPORTER_ASSERT(reporter, NULL == cache2->findAndRefScratchResource(key));
+ REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
+ REPORTER_ASSERT(reporter, size == cache2->getResourceBytes());
+ REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceCount());
+ REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceBytes());
+
+ // Once it is unrefed, it should become available as scratch.
+ resource->unref();
+ REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
+ REPORTER_ASSERT(reporter, size == cache2->getResourceBytes());
+ REPORTER_ASSERT(reporter, 1 == cache2->getBudgetedResourceCount());
+ REPORTER_ASSERT(reporter, size == cache2->getBudgetedResourceBytes());
+ resource = static_cast<TestResource*>(cache2->findAndRefScratchResource(key));
+ REPORTER_ASSERT(reporter, resource);
+ REPORTER_ASSERT(reporter, resource->cacheAccess().getScratchKey() == key);
+ REPORTER_ASSERT(reporter, resource->cacheAccess().isScratch());
+ REPORTER_ASSERT(reporter, resource->cacheAccess().isBudgeted());
+
+ if (0 == i) {
+ // If made unbudgeted, it should return to original state: ref'ed and unbudgeted. Try
+ // the above tests again.
+ resource->cacheAccess().makeUnbudgeted();
+ } else {
+ // After the second time around, try removing the scratch key
+ resource->cacheAccess().removeScratchKey();
+ REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
+ REPORTER_ASSERT(reporter, size == cache2->getResourceBytes());
+ REPORTER_ASSERT(reporter, 1 == cache2->getBudgetedResourceCount());
+ REPORTER_ASSERT(reporter, size == cache2->getBudgetedResourceBytes());
+ REPORTER_ASSERT(reporter, !resource->cacheAccess().getScratchKey().isValid());
+ REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch());
+ REPORTER_ASSERT(reporter, resource->cacheAccess().isBudgeted());
+
+ // now when it is unrefed it should die since it has no key.
+ resource->unref();
+ REPORTER_ASSERT(reporter, 0 == cache2->getResourceCount());
+ REPORTER_ASSERT(reporter, 0 == cache2->getResourceBytes());
+ REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceCount());
+ REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceBytes());
+ }
}
- context->setResourceCacheLimits(5, 30000);
- GrResourceCache2* cache2 = context->getResourceCache2();
- cache2->purgeAllUnlocked();
- SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
+}
+
+static void test_duplicate_scratch_key(skiatest::Reporter* reporter) {
+ Mock mock(5, 30000);
+ GrContext* context = mock.context();
+ GrResourceCache2* cache2 = mock.cache();
// Create two resources that have the same scratch key.
TestResource* a =
@@ -436,15 +491,9 @@
}
static void test_remove_scratch_key(skiatest::Reporter* reporter) {
- SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
- REPORTER_ASSERT(reporter, SkToBool(context));
- if (NULL == context) {
- return;
- }
- context->setResourceCacheLimits(5, 30000);
- GrResourceCache2* cache2 = context->getResourceCache2();
- cache2->purgeAllUnlocked();
- SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
+ Mock mock(5, 30000);
+ GrContext* context = mock.context();
+ GrResourceCache2* cache2 = mock.cache();
// Create two resources that have the same scratch key.
TestResource* a =
@@ -504,15 +553,9 @@
}
static void test_scratch_key_consistency(skiatest::Reporter* reporter) {
- SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
- REPORTER_ASSERT(reporter, SkToBool(context));
- if (NULL == context) {
- return;
- }
- context->setResourceCacheLimits(5, 30000);
- GrResourceCache2* cache2 = context->getResourceCache2();
- cache2->purgeAllUnlocked();
- SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
+ Mock mock(5, 30000);
+ GrContext* context = mock.context();
+ GrResourceCache2* cache2 = mock.cache();
// Create two resources that have the same scratch key.
TestResource* a =
@@ -571,15 +614,9 @@
}
static void test_duplicate_content_key(skiatest::Reporter* reporter) {
- SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
- REPORTER_ASSERT(reporter, SkToBool(context));
- if (NULL == context) {
- return;
- }
- context->setResourceCacheLimits(5, 30000);
- GrResourceCache2* cache2 = context->getResourceCache2();
- cache2->purgeAllUnlocked();
- SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
+ Mock mock(5, 30000);
+ GrContext* context = mock.context();
+ GrResourceCache2* cache2 = mock.cache();
GrContentKey key;
make_content_key<0>(&key, 0);
@@ -624,22 +661,15 @@
}
static void test_purge_invalidated(skiatest::Reporter* reporter) {
- SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
- REPORTER_ASSERT(reporter, SkToBool(context));
- if (NULL == context) {
- return;
- }
+ Mock mock(5, 30000);
+ GrContext* context = mock.context();
+ GrResourceCache2* cache2 = mock.cache();
GrContentKey key1, key2, key3;
make_content_key<0>(&key1, 1);
make_content_key<0>(&key2, 2);
make_content_key<0>(&key3, 3);
- context->setResourceCacheLimits(5, 30000);
- GrResourceCache2* cache2 = context->getResourceCache2();
- cache2->purgeAllUnlocked();
- SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
-
// Add three resources to the cache.
TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
@@ -685,67 +715,52 @@
}
static void test_cache_chained_purge(skiatest::Reporter* reporter) {
- SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
- REPORTER_ASSERT(reporter, SkToBool(context));
- if (NULL == context) {
- return;
- }
+ Mock mock(3, 30000);
+ GrContext* context = mock.context();
+ GrResourceCache2* cache2 = mock.cache();
GrContentKey key1, key2;
make_content_key<0>(&key1, 1);
make_content_key<0>(&key2, 2);
- {
- context->setResourceCacheLimits(3, 30000);
- GrResourceCache2* cache2 = context->getResourceCache2();
- cache2->purgeAllUnlocked();
- SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
- TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
- TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
- a->cacheAccess().setContentKey(key1);
- b->cacheAccess().setContentKey(key2);
+ TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
+ TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
+ a->cacheAccess().setContentKey(key1);
+ b->cacheAccess().setContentKey(key2);
- // Make a cycle
- a->setUnrefWhenDestroyed(b);
- b->setUnrefWhenDestroyed(a);
+ // Make a cycle
+ a->setUnrefWhenDestroyed(b);
+ b->setUnrefWhenDestroyed(a);
- REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
+ REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
- a->unref();
- b->unref();
+ a->unref();
+ b->unref();
- REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
+ REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
- cache2->purgeAllUnlocked();
- REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
+ cache2->purgeAllUnlocked();
+ REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
- // Break the cycle
- a->setUnrefWhenDestroyed(NULL);
- REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
+ // Break the cycle
+ a->setUnrefWhenDestroyed(NULL);
+ REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
- cache2->purgeAllUnlocked();
- REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
- }
+ cache2->purgeAllUnlocked();
+ REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
}
static void test_resource_size_changed(skiatest::Reporter* reporter) {
- SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
- REPORTER_ASSERT(reporter, SkToBool(context));
- if (NULL == context) {
- return;
- }
-
GrContentKey key1, key2;
make_content_key<0>(&key1, 1);
make_content_key<0>(&key2, 2);
// Test changing resources sizes (both increase & decrease).
{
- context->setResourceCacheLimits(3, 30000);
- GrResourceCache2* cache2 = context->getResourceCache2();
- cache2->purgeAllUnlocked();
- SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
+ Mock mock(3, 30000);
+ GrContext* context = mock.context();
+ GrResourceCache2* cache2 = mock.cache();
TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
a->cacheAccess().setContentKey(key1);
@@ -770,10 +785,9 @@
// Test increasing a resources size beyond the cache budget.
{
- context->setResourceCacheLimits(2, 300);
- GrResourceCache2* cache2 = context->getResourceCache2();
- cache2->purgeAllUnlocked();
- SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
+ Mock mock(2, 300);
+ GrContext* context = mock.context();
+ GrResourceCache2* cache2 = mock.cache();
TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
a->setSize(100);
@@ -800,21 +814,14 @@
}
static void test_large_resource_count(skiatest::Reporter* reporter) {
- SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
- REPORTER_ASSERT(reporter, SkToBool(context));
- if (NULL == context) {
- return;
- }
-
- static const int kResourceCnt = 2000;
// Set the cache size to double the resource count because we're going to create 2x that number
// resources, using two different key domains. Add a little slop to the bytes because we resize
// down to 1 byte after creating the resource.
- context->setResourceCacheLimits(2 * kResourceCnt, 2 * kResourceCnt + 1000);
- GrResourceCache2* cache2 = context->getResourceCache2();
- cache2->purgeAllUnlocked();
- SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
+ static const int kResourceCnt = 2000;
+ Mock mock(2 * kResourceCnt, 2 * kResourceCnt + 1000);
+ GrContext* context = mock.context();
+ GrResourceCache2* cache2 = mock.cache();
for (int i = 0; i < kResourceCnt; ++i) {
GrContentKey key1, key2;
@@ -892,6 +899,7 @@
test_no_key(reporter);
test_budgeting(reporter);
test_unbudgeted(reporter);
+ test_unbudgeted_to_scratch(reporter);
test_duplicate_content_key(reporter);
test_duplicate_scratch_key(reporter);
test_remove_scratch_key(reporter);