blob: 7a3355f1629d94240ab1204f31fa32b61898b454 [file] [log] [blame]
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +00008#if SK_SUPPORT_GPU
tfarina@chromium.org4ee16bf2014-01-10 22:08:27 +00009
bsalomonbcf0a522014-10-08 08:40:09 -070010#include "GrContext.h"
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000011#include "GrContextFactory.h"
bsalomonbcf0a522014-10-08 08:40:09 -070012#include "GrGpu.h"
bsalomon33435572014-11-05 14:47:41 -080013#include "GrResourceCache2.h"
bsalomonbcf0a522014-10-08 08:40:09 -070014#include "SkCanvas.h"
bsalomon71cb0c22014-11-14 12:10:14 -080015#include "SkGr.h"
16#include "SkMessageBus.h"
reed69f6f002014-09-18 06:09:44 -070017#include "SkSurface.h"
tfarina@chromium.org4ee16bf2014-01-10 22:08:27 +000018#include "Test.h"
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000019
20static const int gWidth = 640;
21static const int gHeight = 480;
22
23////////////////////////////////////////////////////////////////////////////////
bsalomon33435572014-11-05 14:47:41 -080024static void test_cache(skiatest::Reporter* reporter, GrContext* context, SkCanvas* canvas) {
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000025 const SkIRect size = SkIRect::MakeWH(gWidth, gHeight);
26
27 SkBitmap src;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +000028 src.allocN32Pixels(size.width(), size.height());
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000029 src.eraseColor(SK_ColorBLACK);
30 size_t srcSize = src.getSize();
31
commit-bot@chromium.org95c20032014-05-09 14:29:32 +000032 size_t initialCacheSize;
33 context->getResourceCacheUsage(NULL, &initialCacheSize);
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000034
35 int oldMaxNum;
36 size_t oldMaxBytes;
commit-bot@chromium.org95c20032014-05-09 14:29:32 +000037 context->getResourceCacheLimits(&oldMaxNum, &oldMaxBytes);
skia.committer@gmail.com17f1ae62013-08-09 07:01:22 +000038
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000039 // Set the cache limits so we can fit 10 "src" images and the
40 // max number of textures doesn't matter
41 size_t maxCacheSize = initialCacheSize + 10*srcSize;
commit-bot@chromium.org95c20032014-05-09 14:29:32 +000042 context->setResourceCacheLimits(1000, maxCacheSize);
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000043
44 SkBitmap readback;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +000045 readback.allocN32Pixels(size.width(), size.height());
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000046
47 for (int i = 0; i < 100; ++i) {
48 canvas->drawBitmap(src, 0, 0);
49 canvas->readPixels(size, &readback);
50
51 // "modify" the src texture
52 src.notifyPixelsChanged();
53
commit-bot@chromium.org95c20032014-05-09 14:29:32 +000054 size_t curCacheSize;
55 context->getResourceCacheUsage(NULL, &curCacheSize);
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000056
57 // we should never go over the size limit
58 REPORTER_ASSERT(reporter, curCacheSize <= maxCacheSize);
59 }
60
commit-bot@chromium.org95c20032014-05-09 14:29:32 +000061 context->setResourceCacheLimits(oldMaxNum, oldMaxBytes);
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000062}
63
bsalomon6d3fe022014-07-25 08:35:45 -070064class TestResource : public GrGpuResource {
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +000065 static const size_t kDefaultSize = 100;
bsalomon1c60dfe2015-01-21 09:32:40 -080066 enum ScratchConstructor { kScratchConstructor };
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +000067public:
68 SK_DECLARE_INST_COUNT(TestResource);
bsalomon1c60dfe2015-01-21 09:32:40 -080069 /** Property that distinctly categorizes the resource.
70 * For example, textures have width, height, ... */
bsalomon23e619c2015-02-06 11:54:28 -080071 enum SimulatedProperty { kA_SimulatedProperty, kB_SimulatedProperty };
bsalomon1c60dfe2015-01-21 09:32:40 -080072
bsalomon5236cf42015-01-14 10:42:08 -080073 TestResource(GrGpu* gpu, size_t size, GrGpuResource::LifeCycle lifeCycle)
74 : INHERITED(gpu, lifeCycle)
75 , fToDelete(NULL)
bsalomon1c60dfe2015-01-21 09:32:40 -080076 , fSize(size)
bsalomon23e619c2015-02-06 11:54:28 -080077 , fProperty(kA_SimulatedProperty) {
bsalomon5236cf42015-01-14 10:42:08 -080078 ++fNumAlive;
79 this->registerWithCache();
80 }
81
82 TestResource(GrGpu* gpu, GrGpuResource::LifeCycle lifeCycle)
83 : INHERITED(gpu, lifeCycle)
bsalomondace19e2014-11-17 07:34:06 -080084 , fToDelete(NULL)
bsalomon1c60dfe2015-01-21 09:32:40 -080085 , fSize(kDefaultSize)
bsalomon23e619c2015-02-06 11:54:28 -080086 , fProperty(kA_SimulatedProperty) {
bsalomondace19e2014-11-17 07:34:06 -080087 ++fNumAlive;
88 this->registerWithCache();
89 }
90
bsalomon8b79d232014-11-10 10:19:06 -080091 TestResource(GrGpu* gpu)
bsalomon5236cf42015-01-14 10:42:08 -080092 : INHERITED(gpu, kCached_LifeCycle)
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +000093 , fToDelete(NULL)
bsalomon1c60dfe2015-01-21 09:32:40 -080094 , fSize(kDefaultSize)
bsalomon23e619c2015-02-06 11:54:28 -080095 , fProperty(kA_SimulatedProperty) {
bsalomon8b79d232014-11-10 10:19:06 -080096 ++fNumAlive;
97 this->registerWithCache();
98 }
99
bsalomon23e619c2015-02-06 11:54:28 -0800100 static TestResource* CreateScratch(GrGpu* gpu, SimulatedProperty property, bool cached = true) {
bsalomonc2f35b72015-01-23 07:19:22 -0800101 return SkNEW_ARGS(TestResource, (gpu, property, cached, kScratchConstructor));
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000102 }
103
104 ~TestResource() {
bsalomon33435572014-11-05 14:47:41 -0800105 --fNumAlive;
bsalomon71cb0c22014-11-14 12:10:14 -0800106 SkSafeUnref(fToDelete);
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000107 }
108
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000109 void setSize(size_t size) {
110 fSize = size;
111 this->didChangeGpuMemorySize();
112 }
113
bsalomon33435572014-11-05 14:47:41 -0800114 static int NumAlive() { return fNumAlive; }
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000115
bsalomon71cb0c22014-11-14 12:10:14 -0800116 void setUnrefWhenDestroyed(TestResource* resource) {
117 SkRefCnt_SafeAssign(fToDelete, resource);
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000118 }
119
bsalomon1c60dfe2015-01-21 09:32:40 -0800120 static void ComputeScratchKey(SimulatedProperty property, GrScratchKey* key) {
121 static GrScratchKey::ResourceType t = GrScratchKey::GenerateResourceType();
122 GrScratchKey::Builder builder(key, t, kScratchKeyFieldCnt);
bsalomon24db3b12015-01-23 04:24:04 -0800123 for (int i = 0; i < kScratchKeyFieldCnt; ++i) {
124 builder[i] = static_cast<uint32_t>(i + property);
bsalomon1c60dfe2015-01-21 09:32:40 -0800125 }
126 }
127
128 static size_t ExpectedScratchKeySize() {
129 return sizeof(uint32_t) * (kScratchKeyFieldCnt + GrScratchKey::kMetaDataCnt);
130 }
131
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000132private:
bsalomon24db3b12015-01-23 04:24:04 -0800133 static const int kScratchKeyFieldCnt = 6;
bsalomon1c60dfe2015-01-21 09:32:40 -0800134
bsalomonc2f35b72015-01-23 07:19:22 -0800135 TestResource(GrGpu* gpu, SimulatedProperty property, bool cached, ScratchConstructor)
136 : INHERITED(gpu, cached ? kCached_LifeCycle : kUncached_LifeCycle)
bsalomon1c60dfe2015-01-21 09:32:40 -0800137 , fToDelete(NULL)
138 , fSize(kDefaultSize)
139 , fProperty(property) {
140 GrScratchKey scratchKey;
141 ComputeScratchKey(fProperty, &scratchKey);
142 this->setScratchKey(scratchKey);
143 ++fNumAlive;
144 this->registerWithCache();
145 }
146
bsalomon69ed47f2014-11-12 11:13:39 -0800147 size_t onGpuMemorySize() const SK_OVERRIDE { return fSize; }
148
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000149 TestResource* fToDelete;
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000150 size_t fSize;
bsalomon33435572014-11-05 14:47:41 -0800151 static int fNumAlive;
bsalomon1c60dfe2015-01-21 09:32:40 -0800152 SimulatedProperty fProperty;
bsalomon6d3fe022014-07-25 08:35:45 -0700153 typedef GrGpuResource INHERITED;
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000154};
bsalomon33435572014-11-05 14:47:41 -0800155int TestResource::fNumAlive = 0;
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000156
bsalomonc2f35b72015-01-23 07:19:22 -0800157class Mock {
158public:
159 Mock(int maxCnt, size_t maxBytes) {
160 fContext.reset(GrContext::CreateMockContext());
161 SkASSERT(fContext);
162 fContext->setResourceCacheLimits(maxCnt, maxBytes);
163 GrResourceCache2* cache2 = fContext->getResourceCache2();
164 cache2->purgeAllUnlocked();
165 SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
bsalomon71cb0c22014-11-14 12:10:14 -0800166 }
bsalomonc2f35b72015-01-23 07:19:22 -0800167
168 GrResourceCache2* cache() { return fContext->getResourceCache2(); }
169
170 GrContext* context() { return fContext; }
171
172private:
173 SkAutoTUnref<GrContext> fContext;
174};
175
176static void test_no_key(skiatest::Reporter* reporter) {
177 Mock mock(10, 30000);
178 GrContext* context = mock.context();
179 GrResourceCache2* cache2 = mock.cache();
bsalomon71cb0c22014-11-14 12:10:14 -0800180
181 // Create a bunch of resources with no keys
bsalomon5236cf42015-01-14 10:42:08 -0800182 TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
183 TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
184 TestResource* c = SkNEW_ARGS(TestResource, (context->getGpu()));
185 TestResource* d = SkNEW_ARGS(TestResource, (context->getGpu()));
bsalomon71cb0c22014-11-14 12:10:14 -0800186 a->setSize(11);
187 b->setSize(12);
188 c->setSize(13);
189 d->setSize(14);
190
191 REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
192 REPORTER_ASSERT(reporter, 4 == cache2->getResourceCount());
193 REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() + c->gpuMemorySize() +
194 d->gpuMemorySize() == cache2->getResourceBytes());
195
196 // Should be safe to purge without deleting the resources since we still have refs.
197 cache2->purgeAllUnlocked();
198 REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
199
200 // Since the resources have neither content nor scratch keys, delete immediately upon unref.
201
202 a->unref();
203 REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
204 REPORTER_ASSERT(reporter, 3 == cache2->getResourceCount());
205 REPORTER_ASSERT(reporter, b->gpuMemorySize() + c->gpuMemorySize() + d->gpuMemorySize() ==
206 cache2->getResourceBytes());
207
208 c->unref();
209 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
210 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
211 REPORTER_ASSERT(reporter, b->gpuMemorySize() + d->gpuMemorySize() ==
212 cache2->getResourceBytes());
213
214 d->unref();
215 REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
216 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
217 REPORTER_ASSERT(reporter, b->gpuMemorySize() == cache2->getResourceBytes());
218
219 b->unref();
220 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
221 REPORTER_ASSERT(reporter, 0 == cache2->getResourceCount());
222 REPORTER_ASSERT(reporter, 0 == cache2->getResourceBytes());
223}
224
bsalomon24db3b12015-01-23 04:24:04 -0800225// Each integer passed as a template param creates a new domain.
226template <int> static void make_content_key(GrContentKey* key, int data) {
227 static GrContentKey::Domain d = GrContentKey::GenerateDomain();
228 GrContentKey::Builder builder(key, d, 1);
229 builder[0] = data;
230}
231
bsalomon84c8e622014-11-17 09:33:27 -0800232static void test_budgeting(skiatest::Reporter* reporter) {
bsalomonc2f35b72015-01-23 07:19:22 -0800233 Mock mock(10, 300);
234 GrContext* context = mock.context();
235 GrResourceCache2* cache2 = mock.cache();
bsalomondace19e2014-11-17 07:34:06 -0800236
bsalomon24db3b12015-01-23 04:24:04 -0800237 GrContentKey contentKey;
238 make_content_key<0>(&contentKey, 0);
bsalomondace19e2014-11-17 07:34:06 -0800239
240 // Create a scratch, a content, and a wrapped resource
bsalomon1c60dfe2015-01-21 09:32:40 -0800241 TestResource* scratch =
bsalomon23e619c2015-02-06 11:54:28 -0800242 TestResource::CreateScratch(context->getGpu(), TestResource::kB_SimulatedProperty);
bsalomondace19e2014-11-17 07:34:06 -0800243 scratch->setSize(10);
bsalomon5236cf42015-01-14 10:42:08 -0800244 TestResource* content = SkNEW_ARGS(TestResource, (context->getGpu()));
245 content->setSize(11);
bsalomondace19e2014-11-17 07:34:06 -0800246 REPORTER_ASSERT(reporter, content->cacheAccess().setContentKey(contentKey));
bsalomon5236cf42015-01-14 10:42:08 -0800247 TestResource* wrapped = SkNEW_ARGS(TestResource,
248 (context->getGpu(), GrGpuResource::kWrapped_LifeCycle));
249 wrapped->setSize(12);
250 TestResource* unbudgeted = SkNEW_ARGS(TestResource,
251 (context->getGpu(), GrGpuResource::kUncached_LifeCycle));
bsalomon84c8e622014-11-17 09:33:27 -0800252 unbudgeted->setSize(13);
bsalomondace19e2014-11-17 07:34:06 -0800253
254 // Make sure we can't add a content key to the wrapped resource
bsalomon24db3b12015-01-23 04:24:04 -0800255 GrContentKey contentKey2;
256 make_content_key<0>(&contentKey2, 1);
bsalomondace19e2014-11-17 07:34:06 -0800257 REPORTER_ASSERT(reporter, !wrapped->cacheAccess().setContentKey(contentKey2));
258 REPORTER_ASSERT(reporter, NULL == cache2->findAndRefContentResource(contentKey2));
259
260 // Make sure sizes are as we expect
bsalomon84c8e622014-11-17 09:33:27 -0800261 REPORTER_ASSERT(reporter, 4 == cache2->getResourceCount());
bsalomondace19e2014-11-17 07:34:06 -0800262 REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + content->gpuMemorySize() +
bsalomon84c8e622014-11-17 09:33:27 -0800263 wrapped->gpuMemorySize() + unbudgeted->gpuMemorySize() ==
264 cache2->getResourceBytes());
bsalomondace19e2014-11-17 07:34:06 -0800265 REPORTER_ASSERT(reporter, 2 == cache2->getBudgetedResourceCount());
266 REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + content->gpuMemorySize() ==
267 cache2->getBudgetedResourceBytes());
268
bsalomon63c992f2015-01-23 12:47:59 -0800269 // Our refs mean that the resources are non purgeable.
bsalomondace19e2014-11-17 07:34:06 -0800270 cache2->purgeAllUnlocked();
bsalomon84c8e622014-11-17 09:33:27 -0800271 REPORTER_ASSERT(reporter, 4 == cache2->getResourceCount());
bsalomondace19e2014-11-17 07:34:06 -0800272 REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + content->gpuMemorySize() +
bsalomon84c8e622014-11-17 09:33:27 -0800273 wrapped->gpuMemorySize() + unbudgeted->gpuMemorySize() ==
274 cache2->getResourceBytes());
bsalomondace19e2014-11-17 07:34:06 -0800275 REPORTER_ASSERT(reporter, 2 == cache2->getBudgetedResourceCount());
276 REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + content->gpuMemorySize() ==
277 cache2->getBudgetedResourceBytes());
278
279 // Unreffing the wrapped resource should free it right away.
280 wrapped->unref();
bsalomon84c8e622014-11-17 09:33:27 -0800281 REPORTER_ASSERT(reporter, 3 == cache2->getResourceCount());
282 REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + content->gpuMemorySize() +
283 unbudgeted->gpuMemorySize() == cache2->getResourceBytes());
bsalomondace19e2014-11-17 07:34:06 -0800284
bsalomon84c8e622014-11-17 09:33:27 -0800285 // Now try freeing the budgeted resources first
bsalomon5236cf42015-01-14 10:42:08 -0800286 wrapped = SkNEW_ARGS(TestResource, (context->getGpu(), GrGpuResource::kWrapped_LifeCycle));
bsalomondace19e2014-11-17 07:34:06 -0800287 scratch->setSize(12);
288 content->unref();
289 cache2->purgeAllUnlocked();
bsalomon84c8e622014-11-17 09:33:27 -0800290 REPORTER_ASSERT(reporter, 3 == cache2->getResourceCount());
291 REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + wrapped->gpuMemorySize() +
292 unbudgeted->gpuMemorySize() == cache2->getResourceBytes());
bsalomondace19e2014-11-17 07:34:06 -0800293 REPORTER_ASSERT(reporter, 1 == cache2->getBudgetedResourceCount());
294 REPORTER_ASSERT(reporter, scratch->gpuMemorySize() == cache2->getBudgetedResourceBytes());
295
296 scratch->unref();
297 cache2->purgeAllUnlocked();
bsalomon84c8e622014-11-17 09:33:27 -0800298 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
299 REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() + wrapped->gpuMemorySize() ==
300 cache2->getResourceBytes());
bsalomondace19e2014-11-17 07:34:06 -0800301 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceCount());
302 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceBytes());
303
304 wrapped->unref();
bsalomon84c8e622014-11-17 09:33:27 -0800305 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
306 REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() == cache2->getResourceBytes());
307 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceCount());
308 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceBytes());
309
310 unbudgeted->unref();
bsalomondace19e2014-11-17 07:34:06 -0800311 REPORTER_ASSERT(reporter, 0 == cache2->getResourceCount());
312 REPORTER_ASSERT(reporter, 0 == cache2->getResourceBytes());
bsalomon84c8e622014-11-17 09:33:27 -0800313 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceCount());
314 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceBytes());
bsalomondace19e2014-11-17 07:34:06 -0800315}
316
bsalomon5236cf42015-01-14 10:42:08 -0800317static void test_unbudgeted(skiatest::Reporter* reporter) {
bsalomonc2f35b72015-01-23 07:19:22 -0800318 Mock mock(10, 30000);
319 GrContext* context = mock.context();
320 GrResourceCache2* cache2 = mock.cache();
bsalomon5236cf42015-01-14 10:42:08 -0800321
bsalomon24db3b12015-01-23 04:24:04 -0800322 GrContentKey contentKey;
323 make_content_key<0>(&contentKey, 0);
bsalomon5236cf42015-01-14 10:42:08 -0800324
325 TestResource* scratch;
326 TestResource* content;
327 TestResource* wrapped;
328 TestResource* unbudgeted;
329
330 // A large uncached or wrapped resource shouldn't evict anything.
bsalomon23e619c2015-02-06 11:54:28 -0800331 scratch = TestResource::CreateScratch(context->getGpu(), TestResource::kB_SimulatedProperty);
bsalomon5236cf42015-01-14 10:42:08 -0800332 scratch->setSize(10);
333 scratch->unref();
334 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
335 REPORTER_ASSERT(reporter, 10 == cache2->getResourceBytes());
336 REPORTER_ASSERT(reporter, 1 == cache2->getBudgetedResourceCount());
337 REPORTER_ASSERT(reporter, 10 == cache2->getBudgetedResourceBytes());
338
339 content = SkNEW_ARGS(TestResource, (context->getGpu()));
340 content->setSize(11);
341 REPORTER_ASSERT(reporter, content->cacheAccess().setContentKey(contentKey));
342 content->unref();
343 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
344 REPORTER_ASSERT(reporter, 21 == cache2->getResourceBytes());
345 REPORTER_ASSERT(reporter, 2 == cache2->getBudgetedResourceCount());
346 REPORTER_ASSERT(reporter, 21 == cache2->getBudgetedResourceBytes());
347
348 size_t large = 2 * cache2->getResourceBytes();
349 unbudgeted = SkNEW_ARGS(TestResource,
350 (context->getGpu(), large, GrGpuResource::kUncached_LifeCycle));
351 REPORTER_ASSERT(reporter, 3 == cache2->getResourceCount());
352 REPORTER_ASSERT(reporter, 21 + large == cache2->getResourceBytes());
353 REPORTER_ASSERT(reporter, 2 == cache2->getBudgetedResourceCount());
354 REPORTER_ASSERT(reporter, 21 == cache2->getBudgetedResourceBytes());
355
356 unbudgeted->unref();
357 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
358 REPORTER_ASSERT(reporter, 21 == cache2->getResourceBytes());
359 REPORTER_ASSERT(reporter, 2 == cache2->getBudgetedResourceCount());
360 REPORTER_ASSERT(reporter, 21 == cache2->getBudgetedResourceBytes());
361
362 wrapped = SkNEW_ARGS(TestResource,
363 (context->getGpu(), large, GrGpuResource::kWrapped_LifeCycle));
364 REPORTER_ASSERT(reporter, 3 == cache2->getResourceCount());
365 REPORTER_ASSERT(reporter, 21 + large == cache2->getResourceBytes());
366 REPORTER_ASSERT(reporter, 2 == cache2->getBudgetedResourceCount());
367 REPORTER_ASSERT(reporter, 21 == cache2->getBudgetedResourceBytes());
368
369 wrapped->unref();
370 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
371 REPORTER_ASSERT(reporter, 21 == cache2->getResourceBytes());
372 REPORTER_ASSERT(reporter, 2 == cache2->getBudgetedResourceCount());
373 REPORTER_ASSERT(reporter, 21 == cache2->getBudgetedResourceBytes());
374
375 cache2->purgeAllUnlocked();
376 REPORTER_ASSERT(reporter, 0 == cache2->getResourceCount());
377 REPORTER_ASSERT(reporter, 0 == cache2->getResourceBytes());
378 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceCount());
379 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceBytes());
380}
381
bsalomonc2f35b72015-01-23 07:19:22 -0800382static void test_unbudgeted_to_scratch(skiatest::Reporter* reporter) {
383 Mock mock(10, 300);
384 GrContext* context = mock.context();
385 GrResourceCache2* cache2 = mock.cache();
386
387 TestResource* resource =
bsalomon23e619c2015-02-06 11:54:28 -0800388 TestResource::CreateScratch(context->getGpu(), TestResource::kA_SimulatedProperty, false);
bsalomonc2f35b72015-01-23 07:19:22 -0800389 GrScratchKey key;
bsalomon23e619c2015-02-06 11:54:28 -0800390 TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &key);
bsalomonc2f35b72015-01-23 07:19:22 -0800391
392 size_t size = resource->gpuMemorySize();
393 for (int i = 0; i < 2; ++i) {
394 // Since this resource is unbudgeted, it should not be reachable as scratch.
395 REPORTER_ASSERT(reporter, resource->cacheAccess().getScratchKey() == key);
396 REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch());
397 REPORTER_ASSERT(reporter, !resource->cacheAccess().isBudgeted());
398 REPORTER_ASSERT(reporter, NULL == cache2->findAndRefScratchResource(key));
399 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
400 REPORTER_ASSERT(reporter, size == cache2->getResourceBytes());
401 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceCount());
402 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceBytes());
403
404 // Once it is unrefed, it should become available as scratch.
405 resource->unref();
406 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
407 REPORTER_ASSERT(reporter, size == cache2->getResourceBytes());
408 REPORTER_ASSERT(reporter, 1 == cache2->getBudgetedResourceCount());
409 REPORTER_ASSERT(reporter, size == cache2->getBudgetedResourceBytes());
410 resource = static_cast<TestResource*>(cache2->findAndRefScratchResource(key));
411 REPORTER_ASSERT(reporter, resource);
412 REPORTER_ASSERT(reporter, resource->cacheAccess().getScratchKey() == key);
413 REPORTER_ASSERT(reporter, resource->cacheAccess().isScratch());
414 REPORTER_ASSERT(reporter, resource->cacheAccess().isBudgeted());
415
416 if (0 == i) {
417 // If made unbudgeted, it should return to original state: ref'ed and unbudgeted. Try
418 // the above tests again.
419 resource->cacheAccess().makeUnbudgeted();
420 } else {
421 // After the second time around, try removing the scratch key
422 resource->cacheAccess().removeScratchKey();
423 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
424 REPORTER_ASSERT(reporter, size == cache2->getResourceBytes());
425 REPORTER_ASSERT(reporter, 1 == cache2->getBudgetedResourceCount());
426 REPORTER_ASSERT(reporter, size == cache2->getBudgetedResourceBytes());
427 REPORTER_ASSERT(reporter, !resource->cacheAccess().getScratchKey().isValid());
428 REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch());
429 REPORTER_ASSERT(reporter, resource->cacheAccess().isBudgeted());
430
431 // now when it is unrefed it should die since it has no key.
432 resource->unref();
433 REPORTER_ASSERT(reporter, 0 == cache2->getResourceCount());
434 REPORTER_ASSERT(reporter, 0 == cache2->getResourceBytes());
435 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceCount());
436 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceBytes());
437 }
bsalomon8b79d232014-11-10 10:19:06 -0800438 }
bsalomonc2f35b72015-01-23 07:19:22 -0800439}
440
441static void test_duplicate_scratch_key(skiatest::Reporter* reporter) {
442 Mock mock(5, 30000);
443 GrContext* context = mock.context();
444 GrResourceCache2* cache2 = mock.cache();
bsalomon8b79d232014-11-10 10:19:06 -0800445
bsalomon8b79d232014-11-10 10:19:06 -0800446 // Create two resources that have the same scratch key.
bsalomon23e619c2015-02-06 11:54:28 -0800447 TestResource* a = TestResource::CreateScratch(context->getGpu(),
448 TestResource::kB_SimulatedProperty);
449 TestResource* b = TestResource::CreateScratch(context->getGpu(),
450 TestResource::kB_SimulatedProperty);
bsalomon8b79d232014-11-10 10:19:06 -0800451 a->setSize(11);
452 b->setSize(12);
bsalomon1c60dfe2015-01-21 09:32:40 -0800453 GrScratchKey scratchKey1;
bsalomon23e619c2015-02-06 11:54:28 -0800454 TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey1);
bsalomon1c60dfe2015-01-21 09:32:40 -0800455 // Check for negative case consistency. (leaks upon test failure.)
456 REPORTER_ASSERT(reporter, NULL == cache2->findAndRefScratchResource(scratchKey1));
457
458 GrScratchKey scratchKey;
bsalomon23e619c2015-02-06 11:54:28 -0800459 TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
bsalomon1c60dfe2015-01-21 09:32:40 -0800460
bsalomon8b79d232014-11-10 10:19:06 -0800461 // Scratch resources are registered with GrResourceCache2 just by existing. There are 2.
bsalomon8b79d232014-11-10 10:19:06 -0800462 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
463 SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache2->countScratchEntriesForKey(scratchKey));)
bsalomon71cb0c22014-11-14 12:10:14 -0800464 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
465 REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() ==
466 cache2->getResourceBytes());
bsalomon8b79d232014-11-10 10:19:06 -0800467
bsalomon63c992f2015-01-23 12:47:59 -0800468 // Our refs mean that the resources are non purgeable.
bsalomon71cb0c22014-11-14 12:10:14 -0800469 cache2->purgeAllUnlocked();
bsalomon8b79d232014-11-10 10:19:06 -0800470 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
bsalomon71cb0c22014-11-14 12:10:14 -0800471 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
bsalomon8b79d232014-11-10 10:19:06 -0800472
473 // Unref but don't purge
474 a->unref();
475 b->unref();
476 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
477 SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache2->countScratchEntriesForKey(scratchKey));)
478
bsalomon63c992f2015-01-23 12:47:59 -0800479 // Purge again. This time resources should be purgeable.
bsalomon71cb0c22014-11-14 12:10:14 -0800480 cache2->purgeAllUnlocked();
bsalomon8b79d232014-11-10 10:19:06 -0800481 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
bsalomon71cb0c22014-11-14 12:10:14 -0800482 REPORTER_ASSERT(reporter, 0 == cache2->getResourceCount());
bsalomon8b79d232014-11-10 10:19:06 -0800483 SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache2->countScratchEntriesForKey(scratchKey));)
484}
485
bsalomon10e23ca2014-11-25 05:52:06 -0800486static void test_remove_scratch_key(skiatest::Reporter* reporter) {
bsalomonc2f35b72015-01-23 07:19:22 -0800487 Mock mock(5, 30000);
488 GrContext* context = mock.context();
489 GrResourceCache2* cache2 = mock.cache();
bsalomon10e23ca2014-11-25 05:52:06 -0800490
bsalomon10e23ca2014-11-25 05:52:06 -0800491 // Create two resources that have the same scratch key.
bsalomon23e619c2015-02-06 11:54:28 -0800492 TestResource* a = TestResource::CreateScratch(context->getGpu(),
493 TestResource::kB_SimulatedProperty);
494 TestResource* b = TestResource::CreateScratch(context->getGpu(),
495 TestResource::kB_SimulatedProperty);
bsalomon10e23ca2014-11-25 05:52:06 -0800496 a->unref();
497 b->unref();
498
bsalomon1c60dfe2015-01-21 09:32:40 -0800499
500 GrScratchKey scratchKey;
501 // Ensure that scratch key lookup is correct for negative case.
bsalomon23e619c2015-02-06 11:54:28 -0800502 TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
bsalomon1c60dfe2015-01-21 09:32:40 -0800503 // (following leaks upon test failure).
504 REPORTER_ASSERT(reporter, cache2->findAndRefScratchResource(scratchKey) == NULL);
505
bsalomon10e23ca2014-11-25 05:52:06 -0800506 // Scratch resources are registered with GrResourceCache2 just by existing. There are 2.
bsalomon23e619c2015-02-06 11:54:28 -0800507 TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
bsalomon10e23ca2014-11-25 05:52:06 -0800508 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
509 SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache2->countScratchEntriesForKey(scratchKey));)
510 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
511
512 // Find the first resource and remove its scratch key
513 GrGpuResource* find;
514 find = cache2->findAndRefScratchResource(scratchKey);
515 find->cacheAccess().removeScratchKey();
516 // It's still alive, but not cached by scratch key anymore
517 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
518 SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache2->countScratchEntriesForKey(scratchKey));)
519 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
520
521 // The cache should immediately delete it when it's unrefed since it isn't accessible.
522 find->unref();
523 REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
524 SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache2->countScratchEntriesForKey(scratchKey));)
525 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
526
527 // Repeat for the second resource.
528 find = cache2->findAndRefScratchResource(scratchKey);
529 find->cacheAccess().removeScratchKey();
530 REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
531 SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache2->countScratchEntriesForKey(scratchKey));)
532 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
533
534 // Should be able to call this multiple times with no problem.
535 find->cacheAccess().removeScratchKey();
536 REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
537 SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache2->countScratchEntriesForKey(scratchKey));)
538 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
539
540 find->unref();
541 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
542 SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache2->countScratchEntriesForKey(scratchKey));)
543 REPORTER_ASSERT(reporter, 0 == cache2->getResourceCount());
544}
545
bsalomon1c60dfe2015-01-21 09:32:40 -0800546static void test_scratch_key_consistency(skiatest::Reporter* reporter) {
bsalomonc2f35b72015-01-23 07:19:22 -0800547 Mock mock(5, 30000);
548 GrContext* context = mock.context();
549 GrResourceCache2* cache2 = mock.cache();
bsalomon1c60dfe2015-01-21 09:32:40 -0800550
551 // Create two resources that have the same scratch key.
bsalomon23e619c2015-02-06 11:54:28 -0800552 TestResource* a = TestResource::CreateScratch(context->getGpu(),
553 TestResource::kB_SimulatedProperty);
554 TestResource* b = TestResource::CreateScratch(context->getGpu(),
555 TestResource::kB_SimulatedProperty);
bsalomon1c60dfe2015-01-21 09:32:40 -0800556 a->unref();
557 b->unref();
558
559 GrScratchKey scratchKey;
560 // Ensure that scratch key comparison and assignment is consistent.
561 GrScratchKey scratchKey1;
bsalomon23e619c2015-02-06 11:54:28 -0800562 TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey1);
bsalomon1c60dfe2015-01-21 09:32:40 -0800563 GrScratchKey scratchKey2;
bsalomon23e619c2015-02-06 11:54:28 -0800564 TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey2);
bsalomon1c60dfe2015-01-21 09:32:40 -0800565 REPORTER_ASSERT(reporter, scratchKey1.size() == TestResource::ExpectedScratchKeySize());
566 REPORTER_ASSERT(reporter, scratchKey1 != scratchKey2);
567 REPORTER_ASSERT(reporter, scratchKey2 != scratchKey1);
568 scratchKey = scratchKey1;
569 REPORTER_ASSERT(reporter, scratchKey.size() == TestResource::ExpectedScratchKeySize());
570 REPORTER_ASSERT(reporter, scratchKey1 == scratchKey);
571 REPORTER_ASSERT(reporter, scratchKey == scratchKey1);
572 REPORTER_ASSERT(reporter, scratchKey2 != scratchKey);
573 REPORTER_ASSERT(reporter, scratchKey != scratchKey2);
574 scratchKey = scratchKey2;
575 REPORTER_ASSERT(reporter, scratchKey.size() == TestResource::ExpectedScratchKeySize());
576 REPORTER_ASSERT(reporter, scratchKey1 != scratchKey);
577 REPORTER_ASSERT(reporter, scratchKey != scratchKey1);
578 REPORTER_ASSERT(reporter, scratchKey2 == scratchKey);
579 REPORTER_ASSERT(reporter, scratchKey == scratchKey2);
580
581 // Ensure that scratch key lookup is correct for negative case.
bsalomon23e619c2015-02-06 11:54:28 -0800582 TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
bsalomon1c60dfe2015-01-21 09:32:40 -0800583 // (following leaks upon test failure).
584 REPORTER_ASSERT(reporter, cache2->findAndRefScratchResource(scratchKey) == NULL);
585
586 // Find the first resource with a scratch key and a copy of a scratch key.
bsalomon23e619c2015-02-06 11:54:28 -0800587 TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
bsalomon1c60dfe2015-01-21 09:32:40 -0800588 GrGpuResource* find = cache2->findAndRefScratchResource(scratchKey);
589 REPORTER_ASSERT(reporter, find != NULL);
590 find->unref();
591
592 scratchKey2 = scratchKey;
593 find = cache2->findAndRefScratchResource(scratchKey2);
594 REPORTER_ASSERT(reporter, find != NULL);
595 REPORTER_ASSERT(reporter, find == a || find == b);
596
597 GrGpuResource* find2 = cache2->findAndRefScratchResource(scratchKey2);
598 REPORTER_ASSERT(reporter, find2 != NULL);
599 REPORTER_ASSERT(reporter, find2 == a || find2 == b);
600 REPORTER_ASSERT(reporter, find2 != find);
601 find2->unref();
602 find->unref();
603}
604
bsalomon8b79d232014-11-10 10:19:06 -0800605static void test_duplicate_content_key(skiatest::Reporter* reporter) {
bsalomonc2f35b72015-01-23 07:19:22 -0800606 Mock mock(5, 30000);
607 GrContext* context = mock.context();
608 GrResourceCache2* cache2 = mock.cache();
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000609
bsalomon24db3b12015-01-23 04:24:04 -0800610 GrContentKey key;
611 make_content_key<0>(&key, 0);
bsalomon8b79d232014-11-10 10:19:06 -0800612
bsalomon8b79d232014-11-10 10:19:06 -0800613 // Create two resources that we will attempt to register with the same content key.
bsalomon5236cf42015-01-14 10:42:08 -0800614 TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
615 TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
bsalomon8b79d232014-11-10 10:19:06 -0800616 a->setSize(11);
617 b->setSize(12);
bsalomon71cb0c22014-11-14 12:10:14 -0800618
619 // Can't set the same content key on two resources.
620 REPORTER_ASSERT(reporter, a->cacheAccess().setContentKey(key));
621 REPORTER_ASSERT(reporter, !b->cacheAccess().setContentKey(key));
622
623 // Still have two resources because b is still reffed.
624 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
625 REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() ==
626 cache2->getResourceBytes());
bsalomon8b79d232014-11-10 10:19:06 -0800627 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
628
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000629 b->unref();
bsalomon71cb0c22014-11-14 12:10:14 -0800630 // Now b should be gone.
631 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
632 REPORTER_ASSERT(reporter, a->gpuMemorySize() == cache2->getResourceBytes());
bsalomon8b79d232014-11-10 10:19:06 -0800633 REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000634
bsalomon71cb0c22014-11-14 12:10:14 -0800635 cache2->purgeAllUnlocked();
636 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
637 REPORTER_ASSERT(reporter, a->gpuMemorySize() == cache2->getResourceBytes());
638 REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
639
640 // Drop the ref on a but it isn't immediately purged as it still has a valid scratch key.
bsalomon8b79d232014-11-10 10:19:06 -0800641 a->unref();
bsalomon71cb0c22014-11-14 12:10:14 -0800642 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
643 REPORTER_ASSERT(reporter, a->gpuMemorySize() == cache2->getResourceBytes());
644 REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
645
646 cache2->purgeAllUnlocked();
647 REPORTER_ASSERT(reporter, 0 == cache2->getResourceCount());
648 REPORTER_ASSERT(reporter, 0 == cache2->getResourceBytes());
bsalomon33435572014-11-05 14:47:41 -0800649 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000650}
651
bsalomon8b79d232014-11-10 10:19:06 -0800652static void test_purge_invalidated(skiatest::Reporter* reporter) {
bsalomonc2f35b72015-01-23 07:19:22 -0800653 Mock mock(5, 30000);
654 GrContext* context = mock.context();
655 GrResourceCache2* cache2 = mock.cache();
bsalomon8b79d232014-11-10 10:19:06 -0800656
bsalomon24db3b12015-01-23 04:24:04 -0800657 GrContentKey key1, key2, key3;
658 make_content_key<0>(&key1, 1);
659 make_content_key<0>(&key2, 2);
660 make_content_key<0>(&key3, 3);
bsalomon8b79d232014-11-10 10:19:06 -0800661
bsalomon23e619c2015-02-06 11:54:28 -0800662 // Add three resources to the cache. Only c is usable as scratch.
bsalomon5236cf42015-01-14 10:42:08 -0800663 TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
664 TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
bsalomon23e619c2015-02-06 11:54:28 -0800665 TestResource* c = TestResource::CreateScratch(context->getGpu(),
666 TestResource::kA_SimulatedProperty);
bsalomon71cb0c22014-11-14 12:10:14 -0800667 a->cacheAccess().setContentKey(key1);
668 b->cacheAccess().setContentKey(key2);
669 c->cacheAccess().setContentKey(key3);
bsalomon8b79d232014-11-10 10:19:06 -0800670 a->unref();
bsalomon23e619c2015-02-06 11:54:28 -0800671 // hold b until *after* the message is sent.
bsalomon8b79d232014-11-10 10:19:06 -0800672 c->unref();
673
674 REPORTER_ASSERT(reporter, cache2->hasContentKey(key1));
675 REPORTER_ASSERT(reporter, cache2->hasContentKey(key2));
676 REPORTER_ASSERT(reporter, cache2->hasContentKey(key3));
bsalomon8b79d232014-11-10 10:19:06 -0800677 REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
bsalomon23e619c2015-02-06 11:54:28 -0800678
679 typedef GrContentKeyInvalidatedMessage Msg;
680 typedef SkMessageBus<GrContentKeyInvalidatedMessage> Bus;
681
682 // Invalidate two of the three, they should be purged and no longer accessible via their keys.
683 Bus::Post(Msg(key1));
684 Bus::Post(Msg(key2));
bsalomon71cb0c22014-11-14 12:10:14 -0800685 cache2->purgeAsNeeded();
bsalomon23e619c2015-02-06 11:54:28 -0800686 // a should be deleted now, but we still have a ref on b.
bsalomon8b79d232014-11-10 10:19:06 -0800687 REPORTER_ASSERT(reporter, !cache2->hasContentKey(key1));
688 REPORTER_ASSERT(reporter, !cache2->hasContentKey(key2));
bsalomon23e619c2015-02-06 11:54:28 -0800689 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
bsalomon8b79d232014-11-10 10:19:06 -0800690 REPORTER_ASSERT(reporter, cache2->hasContentKey(key3));
691
692 // Invalidate the third.
bsalomon23e619c2015-02-06 11:54:28 -0800693 Bus::Post(Msg(key3));
bsalomon71cb0c22014-11-14 12:10:14 -0800694 cache2->purgeAsNeeded();
bsalomon23e619c2015-02-06 11:54:28 -0800695 // we still have a ref on b, c should be recycled as scratch.
696 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
bsalomon8b79d232014-11-10 10:19:06 -0800697 REPORTER_ASSERT(reporter, !cache2->hasContentKey(key3));
bsalomon71cb0c22014-11-14 12:10:14 -0800698
bsalomon23e619c2015-02-06 11:54:28 -0800699 // make b purgeable. It should be immediately deleted since it has no key.
700 b->unref();
701 REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
702
703 // Make sure we actually get to c via it's scratch key, before we say goodbye.
704 GrScratchKey scratchKey;
705 TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
706 GrGpuResource* scratch = cache2->findAndRefScratchResource(scratchKey);
707 REPORTER_ASSERT(reporter, scratch == c);
708 SkSafeUnref(scratch);
709
710 // Get rid of c.
bsalomon71cb0c22014-11-14 12:10:14 -0800711 cache2->purgeAllUnlocked();
bsalomon23e619c2015-02-06 11:54:28 -0800712 scratch = cache2->findAndRefScratchResource(scratchKey);
bsalomon71cb0c22014-11-14 12:10:14 -0800713 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
714 REPORTER_ASSERT(reporter, 0 == cache2->getResourceCount());
715 REPORTER_ASSERT(reporter, 0 == cache2->getResourceBytes());
bsalomon23e619c2015-02-06 11:54:28 -0800716 REPORTER_ASSERT(reporter, !scratch);
717 SkSafeUnref(scratch);
bsalomon8b79d232014-11-10 10:19:06 -0800718}
719
bsalomon71cb0c22014-11-14 12:10:14 -0800720static void test_cache_chained_purge(skiatest::Reporter* reporter) {
bsalomonc2f35b72015-01-23 07:19:22 -0800721 Mock mock(3, 30000);
722 GrContext* context = mock.context();
723 GrResourceCache2* cache2 = mock.cache();
bsalomon8b79d232014-11-10 10:19:06 -0800724
bsalomon24db3b12015-01-23 04:24:04 -0800725 GrContentKey key1, key2;
726 make_content_key<0>(&key1, 1);
727 make_content_key<0>(&key2, 2);
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000728
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000729
bsalomonc2f35b72015-01-23 07:19:22 -0800730 TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
731 TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
732 a->cacheAccess().setContentKey(key1);
733 b->cacheAccess().setContentKey(key2);
bsalomon820dd6c2014-11-05 12:09:45 -0800734
bsalomonc2f35b72015-01-23 07:19:22 -0800735 // Make a cycle
736 a->setUnrefWhenDestroyed(b);
737 b->setUnrefWhenDestroyed(a);
bsalomon71cb0c22014-11-14 12:10:14 -0800738
bsalomonc2f35b72015-01-23 07:19:22 -0800739 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
bsalomon33435572014-11-05 14:47:41 -0800740
bsalomonc2f35b72015-01-23 07:19:22 -0800741 a->unref();
742 b->unref();
bsalomon8b79d232014-11-10 10:19:06 -0800743
bsalomonc2f35b72015-01-23 07:19:22 -0800744 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
bsalomon8b79d232014-11-10 10:19:06 -0800745
bsalomonc2f35b72015-01-23 07:19:22 -0800746 cache2->purgeAllUnlocked();
747 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
bsalomon8b79d232014-11-10 10:19:06 -0800748
bsalomonc2f35b72015-01-23 07:19:22 -0800749 // Break the cycle
750 a->setUnrefWhenDestroyed(NULL);
751 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
bsalomon33435572014-11-05 14:47:41 -0800752
bsalomonc2f35b72015-01-23 07:19:22 -0800753 cache2->purgeAllUnlocked();
754 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000755}
756
bsalomon8b79d232014-11-10 10:19:06 -0800757static void test_resource_size_changed(skiatest::Reporter* reporter) {
bsalomon24db3b12015-01-23 04:24:04 -0800758 GrContentKey key1, key2;
759 make_content_key<0>(&key1, 1);
760 make_content_key<0>(&key2, 2);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000761
762 // Test changing resources sizes (both increase & decrease).
763 {
bsalomonc2f35b72015-01-23 07:19:22 -0800764 Mock mock(3, 30000);
765 GrContext* context = mock.context();
766 GrResourceCache2* cache2 = mock.cache();
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000767
bsalomon5236cf42015-01-14 10:42:08 -0800768 TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
bsalomon71cb0c22014-11-14 12:10:14 -0800769 a->cacheAccess().setContentKey(key1);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000770 a->unref();
771
bsalomon5236cf42015-01-14 10:42:08 -0800772 TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
bsalomon71cb0c22014-11-14 12:10:14 -0800773 b->cacheAccess().setContentKey(key2);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000774 b->unref();
775
bsalomon71cb0c22014-11-14 12:10:14 -0800776 REPORTER_ASSERT(reporter, 200 == cache2->getResourceBytes());
777 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
bsalomon8b79d232014-11-10 10:19:06 -0800778 {
779 SkAutoTUnref<TestResource> find2(static_cast<TestResource*>(cache2->findAndRefContentResource(key2)));
780 find2->setSize(200);
781 SkAutoTUnref<TestResource> find1(static_cast<TestResource*>(cache2->findAndRefContentResource(key1)));
782 find1->setSize(50);
783 }
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000784
bsalomon71cb0c22014-11-14 12:10:14 -0800785 REPORTER_ASSERT(reporter, 250 == cache2->getResourceBytes());
786 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000787 }
788
789 // Test increasing a resources size beyond the cache budget.
790 {
bsalomonc2f35b72015-01-23 07:19:22 -0800791 Mock mock(2, 300);
792 GrContext* context = mock.context();
793 GrResourceCache2* cache2 = mock.cache();
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000794
bsalomon5236cf42015-01-14 10:42:08 -0800795 TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
bsalomon8b79d232014-11-10 10:19:06 -0800796 a->setSize(100);
bsalomon71cb0c22014-11-14 12:10:14 -0800797 a->cacheAccess().setContentKey(key1);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000798 a->unref();
799
bsalomon5236cf42015-01-14 10:42:08 -0800800 TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
bsalomon8b79d232014-11-10 10:19:06 -0800801 b->setSize(100);
bsalomon71cb0c22014-11-14 12:10:14 -0800802 b->cacheAccess().setContentKey(key2);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000803 b->unref();
804
bsalomon71cb0c22014-11-14 12:10:14 -0800805 REPORTER_ASSERT(reporter, 200 == cache2->getResourceBytes());
806 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000807
bsalomon8b79d232014-11-10 10:19:06 -0800808 {
809 SkAutoTUnref<TestResource> find2(static_cast<TestResource*>(cache2->findAndRefContentResource(key2)));
810 find2->setSize(201);
811 }
812 REPORTER_ASSERT(reporter, !cache2->hasContentKey(key1));
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000813
bsalomon71cb0c22014-11-14 12:10:14 -0800814 REPORTER_ASSERT(reporter, 201 == cache2->getResourceBytes());
815 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000816 }
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000817}
818
bsalomon10e23ca2014-11-25 05:52:06 -0800819static void test_large_resource_count(skiatest::Reporter* reporter) {
bsalomon10e23ca2014-11-25 05:52:06 -0800820 // Set the cache size to double the resource count because we're going to create 2x that number
821 // resources, using two different key domains. Add a little slop to the bytes because we resize
822 // down to 1 byte after creating the resource.
bsalomonc2f35b72015-01-23 07:19:22 -0800823 static const int kResourceCnt = 2000;
bsalomon10e23ca2014-11-25 05:52:06 -0800824
bsalomonc2f35b72015-01-23 07:19:22 -0800825 Mock mock(2 * kResourceCnt, 2 * kResourceCnt + 1000);
826 GrContext* context = mock.context();
827 GrResourceCache2* cache2 = mock.cache();
bsalomon10e23ca2014-11-25 05:52:06 -0800828
829 for (int i = 0; i < kResourceCnt; ++i) {
bsalomon24db3b12015-01-23 04:24:04 -0800830 GrContentKey key1, key2;
831 make_content_key<1>(&key1, i);
832 make_content_key<2>(&key2, i);
bsalomon10e23ca2014-11-25 05:52:06 -0800833
bsalomon24db3b12015-01-23 04:24:04 -0800834 TestResource* resource;
835
bsalomon10e23ca2014-11-25 05:52:06 -0800836 resource = SkNEW_ARGS(TestResource, (context->getGpu()));
bsalomon24db3b12015-01-23 04:24:04 -0800837 resource->cacheAccess().setContentKey(key1);
bsalomon10e23ca2014-11-25 05:52:06 -0800838 resource->setSize(1);
839 resource->unref();
840
bsalomon10e23ca2014-11-25 05:52:06 -0800841 resource = SkNEW_ARGS(TestResource, (context->getGpu()));
bsalomon24db3b12015-01-23 04:24:04 -0800842 resource->cacheAccess().setContentKey(key2);
bsalomon10e23ca2014-11-25 05:52:06 -0800843 resource->setSize(1);
844 resource->unref();
845 }
846
847 REPORTER_ASSERT(reporter, TestResource::NumAlive() == 2 * kResourceCnt);
848 REPORTER_ASSERT(reporter, cache2->getBudgetedResourceBytes() == 2 * kResourceCnt);
849 REPORTER_ASSERT(reporter, cache2->getBudgetedResourceCount() == 2 * kResourceCnt);
850 REPORTER_ASSERT(reporter, cache2->getResourceBytes() == 2 * kResourceCnt);
851 REPORTER_ASSERT(reporter, cache2->getResourceCount() == 2 * kResourceCnt);
852 for (int i = 0; i < kResourceCnt; ++i) {
bsalomon24db3b12015-01-23 04:24:04 -0800853 GrContentKey key1, key2;
854 make_content_key<1>(&key1, i);
855 make_content_key<2>(&key2, i);
856
bsalomon10e23ca2014-11-25 05:52:06 -0800857 REPORTER_ASSERT(reporter, cache2->hasContentKey(key1));
bsalomon24db3b12015-01-23 04:24:04 -0800858 REPORTER_ASSERT(reporter, cache2->hasContentKey(key2));
bsalomon10e23ca2014-11-25 05:52:06 -0800859 }
860
861 cache2->purgeAllUnlocked();
862 REPORTER_ASSERT(reporter, TestResource::NumAlive() == 0);
863 REPORTER_ASSERT(reporter, cache2->getBudgetedResourceBytes() == 0);
864 REPORTER_ASSERT(reporter, cache2->getBudgetedResourceCount() == 0);
865 REPORTER_ASSERT(reporter, cache2->getResourceBytes() == 0);
866 REPORTER_ASSERT(reporter, cache2->getResourceCount() == 0);
867
868 for (int i = 0; i < kResourceCnt; ++i) {
bsalomon24db3b12015-01-23 04:24:04 -0800869 GrContentKey key1, key2;
870 make_content_key<1>(&key1, i);
871 make_content_key<2>(&key2, i);
872
bsalomon10e23ca2014-11-25 05:52:06 -0800873 REPORTER_ASSERT(reporter, !cache2->hasContentKey(key1));
bsalomon24db3b12015-01-23 04:24:04 -0800874 REPORTER_ASSERT(reporter, !cache2->hasContentKey(key2));
bsalomon10e23ca2014-11-25 05:52:06 -0800875 }
876}
877
878
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000879////////////////////////////////////////////////////////////////////////////////
tfarina@chromium.org4ee16bf2014-01-10 22:08:27 +0000880DEF_GPUTEST(ResourceCache, reporter, factory) {
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000881 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
882 GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
883 if (!GrContextFactory::IsRenderingGLContext(glType)) {
884 continue;
885 }
886 GrContext* context = factory->get(glType);
bsalomonfdcf2c02014-11-05 12:30:32 -0800887 if (NULL == context) {
888 continue;
889 }
bsalomonf2703d82014-10-28 14:33:06 -0700890 GrSurfaceDesc desc;
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000891 desc.fConfig = kSkia8888_GrPixelConfig;
bsalomonf2703d82014-10-28 14:33:06 -0700892 desc.fFlags = kRenderTarget_GrSurfaceFlag;
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000893 desc.fWidth = gWidth;
894 desc.fHeight = gHeight;
reed69f6f002014-09-18 06:09:44 -0700895 SkImageInfo info = SkImageInfo::MakeN32Premul(gWidth, gHeight);
bsalomonafe30052015-01-16 07:32:33 -0800896 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context,
897 SkSurface::kNo_Budgeted, info));
reed69f6f002014-09-18 06:09:44 -0700898 test_cache(reporter, context, surface->getCanvas());
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000899 }
bsalomon33435572014-11-05 14:47:41 -0800900
bsalomon8b79d232014-11-10 10:19:06 -0800901 // The below tests create their own mock contexts.
bsalomon71cb0c22014-11-14 12:10:14 -0800902 test_no_key(reporter);
bsalomon84c8e622014-11-17 09:33:27 -0800903 test_budgeting(reporter);
bsalomon5236cf42015-01-14 10:42:08 -0800904 test_unbudgeted(reporter);
bsalomonc2f35b72015-01-23 07:19:22 -0800905 test_unbudgeted_to_scratch(reporter);
bsalomon8b79d232014-11-10 10:19:06 -0800906 test_duplicate_content_key(reporter);
907 test_duplicate_scratch_key(reporter);
bsalomon10e23ca2014-11-25 05:52:06 -0800908 test_remove_scratch_key(reporter);
bsalomon1c60dfe2015-01-21 09:32:40 -0800909 test_scratch_key_consistency(reporter);
bsalomon8b79d232014-11-10 10:19:06 -0800910 test_purge_invalidated(reporter);
bsalomon71cb0c22014-11-14 12:10:14 -0800911 test_cache_chained_purge(reporter);
bsalomon8b79d232014-11-10 10:19:06 -0800912 test_resource_size_changed(reporter);
bsalomon10e23ca2014-11-25 05:52:06 -0800913 test_large_resource_count(reporter);
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000914}
915
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000916#endif