blob: 45e28425d057d1b7691454568fa9ce8c9c5c11b6 [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;
66
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +000067public:
68 SK_DECLARE_INST_COUNT(TestResource);
bsalomondace19e2014-11-17 07:34:06 -080069 TestResource(GrGpu* gpu, bool isWrapped)
70 : INHERITED(gpu, isWrapped)
71 , fToDelete(NULL)
72 , fSize(kDefaultSize) {
73 ++fNumAlive;
74 this->registerWithCache();
75 }
76
bsalomon8b79d232014-11-10 10:19:06 -080077 TestResource(GrGpu* gpu)
bsalomonc44be0e2014-07-25 07:32:33 -070078 : INHERITED(gpu, false)
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +000079 , fToDelete(NULL)
bsalomon8b79d232014-11-10 10:19:06 -080080 , fSize(kDefaultSize) {
81 ++fNumAlive;
82 this->registerWithCache();
83 }
84
85 TestResource(GrGpu* gpu, const GrResourceKey& scratchKey)
86 : INHERITED(gpu, false)
bsalomon8b79d232014-11-10 10:19:06 -080087 , fToDelete(NULL)
88 , fSize(kDefaultSize) {
89 this->setScratchKey(scratchKey);
bsalomon33435572014-11-05 14:47:41 -080090 ++fNumAlive;
bsalomon16961262014-08-26 14:01:07 -070091 this->registerWithCache();
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +000092 }
93
94 ~TestResource() {
bsalomon33435572014-11-05 14:47:41 -080095 --fNumAlive;
bsalomon71cb0c22014-11-14 12:10:14 -080096 SkSafeUnref(fToDelete);
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +000097 }
98
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +000099 void setSize(size_t size) {
100 fSize = size;
101 this->didChangeGpuMemorySize();
102 }
103
bsalomon33435572014-11-05 14:47:41 -0800104 static int NumAlive() { return fNumAlive; }
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000105
bsalomon71cb0c22014-11-14 12:10:14 -0800106 void setUnrefWhenDestroyed(TestResource* resource) {
107 SkRefCnt_SafeAssign(fToDelete, resource);
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000108 }
109
110private:
bsalomon69ed47f2014-11-12 11:13:39 -0800111 size_t onGpuMemorySize() const SK_OVERRIDE { return fSize; }
112
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000113 TestResource* fToDelete;
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000114 size_t fSize;
bsalomon33435572014-11-05 14:47:41 -0800115 static int fNumAlive;
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000116
bsalomon6d3fe022014-07-25 08:35:45 -0700117 typedef GrGpuResource INHERITED;
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000118};
bsalomon33435572014-11-05 14:47:41 -0800119int TestResource::fNumAlive = 0;
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000120
bsalomon71cb0c22014-11-14 12:10:14 -0800121static void test_no_key(skiatest::Reporter* reporter) {
122 SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
123 REPORTER_ASSERT(reporter, SkToBool(context));
124 if (NULL == context) {
125 return;
126 }
127 context->setResourceCacheLimits(10, 30000);
128 GrResourceCache2* cache2 = context->getResourceCache2();
129 cache2->purgeAllUnlocked();
130 SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
131
132 // Create a bunch of resources with no keys
133 TestResource* a = new TestResource(context->getGpu());
134 TestResource* b = new TestResource(context->getGpu());
135 TestResource* c = new TestResource(context->getGpu());
136 TestResource* d = new TestResource(context->getGpu());
137 a->setSize(11);
138 b->setSize(12);
139 c->setSize(13);
140 d->setSize(14);
141
142 REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
143 REPORTER_ASSERT(reporter, 4 == cache2->getResourceCount());
144 REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() + c->gpuMemorySize() +
145 d->gpuMemorySize() == cache2->getResourceBytes());
146
147 // Should be safe to purge without deleting the resources since we still have refs.
148 cache2->purgeAllUnlocked();
149 REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
150
151 // Since the resources have neither content nor scratch keys, delete immediately upon unref.
152
153 a->unref();
154 REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
155 REPORTER_ASSERT(reporter, 3 == cache2->getResourceCount());
156 REPORTER_ASSERT(reporter, b->gpuMemorySize() + c->gpuMemorySize() + d->gpuMemorySize() ==
157 cache2->getResourceBytes());
158
159 c->unref();
160 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
161 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
162 REPORTER_ASSERT(reporter, b->gpuMemorySize() + d->gpuMemorySize() ==
163 cache2->getResourceBytes());
164
165 d->unref();
166 REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
167 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
168 REPORTER_ASSERT(reporter, b->gpuMemorySize() == cache2->getResourceBytes());
169
170 b->unref();
171 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
172 REPORTER_ASSERT(reporter, 0 == cache2->getResourceCount());
173 REPORTER_ASSERT(reporter, 0 == cache2->getResourceBytes());
174}
175
bsalomon84c8e622014-11-17 09:33:27 -0800176static void test_budgeting(skiatest::Reporter* reporter) {
bsalomondace19e2014-11-17 07:34:06 -0800177 SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
178 REPORTER_ASSERT(reporter, SkToBool(context));
179 if (NULL == context) {
180 return;
181 }
182 context->setResourceCacheLimits(10, 300);
183 GrResourceCache2* cache2 = context->getResourceCache2();
184 cache2->purgeAllUnlocked();
185 SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
186 SkASSERT(0 == cache2->getBudgetedResourceCount() && 0 == cache2->getBudgetedResourceBytes());
187
188 GrCacheID::Key keyData;
189 memset(&keyData, 0, sizeof(keyData));
190 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();
191 GrResourceKey scratchKey(GrCacheID(GrResourceKey::ScratchDomain(), keyData), t, 0);
192 GrResourceKey contentKey(GrCacheID(GrCacheID::GenerateDomain(), keyData), t, 0);
193
194 // Create a scratch, a content, and a wrapped resource
195 TestResource* scratch = new TestResource(context->getGpu(), scratchKey);
196 scratch->setSize(10);
197 TestResource* content = new TestResource(context->getGpu());
198 scratch->setSize(11);
199 REPORTER_ASSERT(reporter, content->cacheAccess().setContentKey(contentKey));
200 TestResource* wrapped = new TestResource(context->getGpu(), true);
201 scratch->setSize(12);
bsalomon84c8e622014-11-17 09:33:27 -0800202 TestResource* unbudgeted = new TestResource(context->getGpu());
203 unbudgeted->setSize(13);
204 unbudgeted->cacheAccess().setBudgeted(false);
bsalomondace19e2014-11-17 07:34:06 -0800205
206 // Make sure we can't add a content key to the wrapped resource
207 keyData.fData8[0] = 1;
208 GrResourceKey contentKey2(GrCacheID(GrCacheID::GenerateDomain(), keyData), t, 0);
209 REPORTER_ASSERT(reporter, !wrapped->cacheAccess().setContentKey(contentKey2));
210 REPORTER_ASSERT(reporter, NULL == cache2->findAndRefContentResource(contentKey2));
211
212 // Make sure sizes are as we expect
bsalomon84c8e622014-11-17 09:33:27 -0800213 REPORTER_ASSERT(reporter, 4 == cache2->getResourceCount());
bsalomondace19e2014-11-17 07:34:06 -0800214 REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + content->gpuMemorySize() +
bsalomon84c8e622014-11-17 09:33:27 -0800215 wrapped->gpuMemorySize() + unbudgeted->gpuMemorySize() ==
216 cache2->getResourceBytes());
bsalomondace19e2014-11-17 07:34:06 -0800217 REPORTER_ASSERT(reporter, 2 == cache2->getBudgetedResourceCount());
218 REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + content->gpuMemorySize() ==
219 cache2->getBudgetedResourceBytes());
220
221 // Our refs mean that the resources are non purgable.
222 cache2->purgeAllUnlocked();
bsalomon84c8e622014-11-17 09:33:27 -0800223 REPORTER_ASSERT(reporter, 4 == cache2->getResourceCount());
bsalomondace19e2014-11-17 07:34:06 -0800224 REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + content->gpuMemorySize() +
bsalomon84c8e622014-11-17 09:33:27 -0800225 wrapped->gpuMemorySize() + unbudgeted->gpuMemorySize() ==
226 cache2->getResourceBytes());
bsalomondace19e2014-11-17 07:34:06 -0800227 REPORTER_ASSERT(reporter, 2 == cache2->getBudgetedResourceCount());
228 REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + content->gpuMemorySize() ==
229 cache2->getBudgetedResourceBytes());
230
231 // Unreffing the wrapped resource should free it right away.
232 wrapped->unref();
bsalomon84c8e622014-11-17 09:33:27 -0800233 REPORTER_ASSERT(reporter, 3 == cache2->getResourceCount());
234 REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + content->gpuMemorySize() +
235 unbudgeted->gpuMemorySize() == cache2->getResourceBytes());
bsalomondace19e2014-11-17 07:34:06 -0800236
bsalomon84c8e622014-11-17 09:33:27 -0800237 // Now try freeing the budgeted resources first
bsalomondace19e2014-11-17 07:34:06 -0800238 wrapped = new TestResource(context->getGpu(), true);
239 scratch->setSize(12);
240 content->unref();
241 cache2->purgeAllUnlocked();
bsalomon84c8e622014-11-17 09:33:27 -0800242 REPORTER_ASSERT(reporter, 3 == cache2->getResourceCount());
243 REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + wrapped->gpuMemorySize() +
244 unbudgeted->gpuMemorySize() == cache2->getResourceBytes());
bsalomondace19e2014-11-17 07:34:06 -0800245 REPORTER_ASSERT(reporter, 1 == cache2->getBudgetedResourceCount());
246 REPORTER_ASSERT(reporter, scratch->gpuMemorySize() == cache2->getBudgetedResourceBytes());
247
248 scratch->unref();
249 cache2->purgeAllUnlocked();
bsalomon84c8e622014-11-17 09:33:27 -0800250 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
251 REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() + wrapped->gpuMemorySize() ==
252 cache2->getResourceBytes());
bsalomondace19e2014-11-17 07:34:06 -0800253 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceCount());
254 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceBytes());
255
256 wrapped->unref();
bsalomon84c8e622014-11-17 09:33:27 -0800257 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
258 REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() == cache2->getResourceBytes());
259 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceCount());
260 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceBytes());
261
262 unbudgeted->unref();
bsalomondace19e2014-11-17 07:34:06 -0800263 REPORTER_ASSERT(reporter, 0 == cache2->getResourceCount());
264 REPORTER_ASSERT(reporter, 0 == cache2->getResourceBytes());
bsalomon84c8e622014-11-17 09:33:27 -0800265 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceCount());
266 REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceBytes());
bsalomondace19e2014-11-17 07:34:06 -0800267}
268
bsalomon8b79d232014-11-10 10:19:06 -0800269static void test_duplicate_scratch_key(skiatest::Reporter* reporter) {
270 SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
271 REPORTER_ASSERT(reporter, SkToBool(context));
272 if (NULL == context) {
273 return;
274 }
275 context->setResourceCacheLimits(5, 30000);
bsalomon71cb0c22014-11-14 12:10:14 -0800276 GrResourceCache2* cache2 = context->getResourceCache2();
277 cache2->purgeAllUnlocked();
278 SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
bsalomon8b79d232014-11-10 10:19:06 -0800279
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000280 GrCacheID::Key keyData;
bsalomon48ea2022014-11-12 10:28:17 -0800281 memset(&keyData, 0, sizeof(keyData));
bsalomon8b79d232014-11-10 10:19:06 -0800282 GrCacheID::Domain domain = GrResourceKey::ScratchDomain();
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000283 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();
bsalomon8b79d232014-11-10 10:19:06 -0800284 GrResourceKey scratchKey(GrCacheID(domain, keyData), t, 0);
285
286 // Create two resources that have the same scratch key.
287 TestResource* a = new TestResource(context->getGpu(), scratchKey);
288 TestResource* b = new TestResource(context->getGpu(), scratchKey);
289 a->setSize(11);
290 b->setSize(12);
291 // Scratch resources are registered with GrResourceCache2 just by existing. There are 2.
bsalomon8b79d232014-11-10 10:19:06 -0800292 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
293 SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache2->countScratchEntriesForKey(scratchKey));)
bsalomon71cb0c22014-11-14 12:10:14 -0800294 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
295 REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() ==
296 cache2->getResourceBytes());
bsalomon8b79d232014-11-10 10:19:06 -0800297
298 // Our refs mean that the resources are non purgable.
bsalomon71cb0c22014-11-14 12:10:14 -0800299 cache2->purgeAllUnlocked();
bsalomon8b79d232014-11-10 10:19:06 -0800300 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
bsalomon71cb0c22014-11-14 12:10:14 -0800301 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
bsalomon8b79d232014-11-10 10:19:06 -0800302
303 // Unref but don't purge
304 a->unref();
305 b->unref();
306 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
307 SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache2->countScratchEntriesForKey(scratchKey));)
308
309 // Purge again. This time resources should be purgable.
bsalomon71cb0c22014-11-14 12:10:14 -0800310 cache2->purgeAllUnlocked();
bsalomon8b79d232014-11-10 10:19:06 -0800311 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
bsalomon71cb0c22014-11-14 12:10:14 -0800312 REPORTER_ASSERT(reporter, 0 == cache2->getResourceCount());
bsalomon8b79d232014-11-10 10:19:06 -0800313 SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache2->countScratchEntriesForKey(scratchKey));)
314}
315
316static void test_duplicate_content_key(skiatest::Reporter* reporter) {
317 SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
318 REPORTER_ASSERT(reporter, SkToBool(context));
319 if (NULL == context) {
320 return;
321 }
bsalomon33435572014-11-05 14:47:41 -0800322 context->setResourceCacheLimits(5, 30000);
bsalomon71cb0c22014-11-14 12:10:14 -0800323 GrResourceCache2* cache2 = context->getResourceCache2();
324 cache2->purgeAllUnlocked();
325 SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000326
bsalomon8b79d232014-11-10 10:19:06 -0800327 GrCacheID::Domain domain = GrCacheID::GenerateDomain();
328 GrCacheID::Key keyData;
329 memset(&keyData, 0, sizeof(keyData));
330 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();
331 GrResourceKey key(GrCacheID(domain, keyData), t, 0);
332
bsalomon8b79d232014-11-10 10:19:06 -0800333 // Create two resources that we will attempt to register with the same content key.
bsalomonc44be0e2014-07-25 07:32:33 -0700334 TestResource* a = new TestResource(context->getGpu());
335 TestResource* b = new TestResource(context->getGpu());
bsalomon8b79d232014-11-10 10:19:06 -0800336 a->setSize(11);
337 b->setSize(12);
bsalomon71cb0c22014-11-14 12:10:14 -0800338
339 // Can't set the same content key on two resources.
340 REPORTER_ASSERT(reporter, a->cacheAccess().setContentKey(key));
341 REPORTER_ASSERT(reporter, !b->cacheAccess().setContentKey(key));
342
343 // Still have two resources because b is still reffed.
344 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
345 REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() ==
346 cache2->getResourceBytes());
bsalomon8b79d232014-11-10 10:19:06 -0800347 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
348
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000349 b->unref();
bsalomon71cb0c22014-11-14 12:10:14 -0800350 // Now b should be gone.
351 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
352 REPORTER_ASSERT(reporter, a->gpuMemorySize() == cache2->getResourceBytes());
bsalomon8b79d232014-11-10 10:19:06 -0800353 REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000354
bsalomon71cb0c22014-11-14 12:10:14 -0800355 cache2->purgeAllUnlocked();
356 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
357 REPORTER_ASSERT(reporter, a->gpuMemorySize() == cache2->getResourceBytes());
358 REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
359
360 // 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 -0800361 a->unref();
bsalomon71cb0c22014-11-14 12:10:14 -0800362 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
363 REPORTER_ASSERT(reporter, a->gpuMemorySize() == cache2->getResourceBytes());
364 REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
365
366 cache2->purgeAllUnlocked();
367 REPORTER_ASSERT(reporter, 0 == cache2->getResourceCount());
368 REPORTER_ASSERT(reporter, 0 == cache2->getResourceBytes());
bsalomon33435572014-11-05 14:47:41 -0800369 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000370}
371
bsalomon8b79d232014-11-10 10:19:06 -0800372static void test_purge_invalidated(skiatest::Reporter* reporter) {
373 SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
374 REPORTER_ASSERT(reporter, SkToBool(context));
375 if (NULL == context) {
376 return;
377 }
378
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000379 GrCacheID::Domain domain = GrCacheID::GenerateDomain();
380 GrCacheID::Key keyData;
bsalomon8b79d232014-11-10 10:19:06 -0800381 memset(&keyData, 0, sizeof(keyData));
382
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000383 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();
384
bsalomon8b79d232014-11-10 10:19:06 -0800385 keyData.fData64[0] = 1;
386 GrResourceKey key1(GrCacheID(domain, keyData), t, 0);
387 keyData.fData64[0] = 2;
388 GrResourceKey key2(GrCacheID(domain, keyData), t, 0);
389 keyData.fData64[0] = 3;
390 GrResourceKey key3(GrCacheID(domain, keyData), t, 0);
391
392 context->setResourceCacheLimits(5, 30000);
bsalomon8b79d232014-11-10 10:19:06 -0800393 GrResourceCache2* cache2 = context->getResourceCache2();
bsalomon71cb0c22014-11-14 12:10:14 -0800394 cache2->purgeAllUnlocked();
395 SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
bsalomon8b79d232014-11-10 10:19:06 -0800396
397 // Add three resources to the cache.
398 TestResource* a = new TestResource(context->getGpu());
399 TestResource* b = new TestResource(context->getGpu());
400 TestResource* c = new TestResource(context->getGpu());
bsalomon71cb0c22014-11-14 12:10:14 -0800401 a->cacheAccess().setContentKey(key1);
402 b->cacheAccess().setContentKey(key2);
403 c->cacheAccess().setContentKey(key3);
bsalomon8b79d232014-11-10 10:19:06 -0800404 a->unref();
405 b->unref();
406 c->unref();
407
408 REPORTER_ASSERT(reporter, cache2->hasContentKey(key1));
409 REPORTER_ASSERT(reporter, cache2->hasContentKey(key2));
410 REPORTER_ASSERT(reporter, cache2->hasContentKey(key3));
411
412 // Invalidate two of the three, they should be purged and destroyed.
413 REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
414 const GrResourceInvalidatedMessage msg1 = { key1 };
415 SkMessageBus<GrResourceInvalidatedMessage>::Post(msg1);
416 const GrResourceInvalidatedMessage msg2 = { key2 };
417 SkMessageBus<GrResourceInvalidatedMessage>::Post(msg2);
bsalomon6d4488c2014-11-11 07:27:16 -0800418#if 0 // Disabled until reimplemented in GrResourceCache2.
bsalomon71cb0c22014-11-14 12:10:14 -0800419 cache2->purgeAsNeeded();
bsalomon8b79d232014-11-10 10:19:06 -0800420 REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
421 REPORTER_ASSERT(reporter, !cache2->hasContentKey(key1));
422 REPORTER_ASSERT(reporter, !cache2->hasContentKey(key2));
423 REPORTER_ASSERT(reporter, cache2->hasContentKey(key3));
bsalomon6d4488c2014-11-11 07:27:16 -0800424#endif
bsalomon8b79d232014-11-10 10:19:06 -0800425
426 // Invalidate the third.
427 const GrResourceInvalidatedMessage msg3 = { key3 };
428 SkMessageBus<GrResourceInvalidatedMessage>::Post(msg3);
bsalomon6d4488c2014-11-11 07:27:16 -0800429#if 0 // Disabled until reimplemented in GrResourceCache2.
bsalomon71cb0c22014-11-14 12:10:14 -0800430 cache2->purgeAsNeeded();
bsalomon8b79d232014-11-10 10:19:06 -0800431 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
432 REPORTER_ASSERT(reporter, !cache2->hasContentKey(key3));
bsalomon6d4488c2014-11-11 07:27:16 -0800433#endif
bsalomon71cb0c22014-11-14 12:10:14 -0800434
435 cache2->purgeAllUnlocked();
436 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
437 REPORTER_ASSERT(reporter, 0 == cache2->getResourceCount());
438 REPORTER_ASSERT(reporter, 0 == cache2->getResourceBytes());
bsalomon8b79d232014-11-10 10:19:06 -0800439}
440
bsalomon71cb0c22014-11-14 12:10:14 -0800441static void test_cache_chained_purge(skiatest::Reporter* reporter) {
bsalomon8b79d232014-11-10 10:19:06 -0800442 SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
443 REPORTER_ASSERT(reporter, SkToBool(context));
444 if (NULL == context) {
445 return;
446 }
447
448 GrCacheID::Domain domain = GrCacheID::GenerateDomain();
449 GrCacheID::Key keyData;
450 memset(&keyData, 0, sizeof(keyData));
451 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();
452
453 keyData.fData64[0] = 1;
454 GrResourceKey key1(GrCacheID(domain, keyData), t, 0);
455
456 keyData.fData64[0] = 2;
457 GrResourceKey key2(GrCacheID(domain, keyData), t, 0);
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000458
459 {
bsalomon33435572014-11-05 14:47:41 -0800460 context->setResourceCacheLimits(3, 30000);
bsalomon71cb0c22014-11-14 12:10:14 -0800461 GrResourceCache2* cache2 = context->getResourceCache2();
462 cache2->purgeAllUnlocked();
463 SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000464
bsalomon820dd6c2014-11-05 12:09:45 -0800465 TestResource* a = new TestResource(context->getGpu());
466 TestResource* b = new TestResource(context->getGpu());
bsalomon71cb0c22014-11-14 12:10:14 -0800467 a->cacheAccess().setContentKey(key1);
468 b->cacheAccess().setContentKey(key2);
bsalomon820dd6c2014-11-05 12:09:45 -0800469
bsalomon71cb0c22014-11-14 12:10:14 -0800470 // Make a cycle
471 a->setUnrefWhenDestroyed(b);
472 b->setUnrefWhenDestroyed(a);
473
474 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
bsalomon33435572014-11-05 14:47:41 -0800475
476 a->unref();
477 b->unref();
bsalomon8b79d232014-11-10 10:19:06 -0800478
bsalomon33435572014-11-05 14:47:41 -0800479 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
bsalomon8b79d232014-11-10 10:19:06 -0800480
bsalomon71cb0c22014-11-14 12:10:14 -0800481 cache2->purgeAllUnlocked();
482 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
bsalomon8b79d232014-11-10 10:19:06 -0800483
bsalomon71cb0c22014-11-14 12:10:14 -0800484 // Break the cycle
485 a->setUnrefWhenDestroyed(NULL);
486 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
bsalomon33435572014-11-05 14:47:41 -0800487
bsalomon71cb0c22014-11-14 12:10:14 -0800488 cache2->purgeAllUnlocked();
bsalomon33435572014-11-05 14:47:41 -0800489 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000490 }
491}
492
bsalomon8b79d232014-11-10 10:19:06 -0800493static void test_resource_size_changed(skiatest::Reporter* reporter) {
494 SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
495 REPORTER_ASSERT(reporter, SkToBool(context));
496 if (NULL == context) {
497 return;
498 }
499
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000500 GrCacheID::Domain domain = GrCacheID::GenerateDomain();
501 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();
502
503 GrCacheID::Key key1Data;
504 key1Data.fData64[0] = 0;
505 key1Data.fData64[1] = 0;
506 GrResourceKey key1(GrCacheID(domain, key1Data), t, 0);
507
508 GrCacheID::Key key2Data;
509 key2Data.fData64[0] = 1;
510 key2Data.fData64[1] = 0;
511 GrResourceKey key2(GrCacheID(domain, key2Data), t, 0);
512
513 // Test changing resources sizes (both increase & decrease).
514 {
bsalomon33435572014-11-05 14:47:41 -0800515 context->setResourceCacheLimits(3, 30000);
bsalomon8b79d232014-11-10 10:19:06 -0800516 GrResourceCache2* cache2 = context->getResourceCache2();
bsalomon71cb0c22014-11-14 12:10:14 -0800517 cache2->purgeAllUnlocked();
518 SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000519
bsalomonc44be0e2014-07-25 07:32:33 -0700520 TestResource* a = new TestResource(context->getGpu());
bsalomon71cb0c22014-11-14 12:10:14 -0800521 a->cacheAccess().setContentKey(key1);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000522 a->unref();
523
bsalomonc44be0e2014-07-25 07:32:33 -0700524 TestResource* b = new TestResource(context->getGpu());
bsalomon71cb0c22014-11-14 12:10:14 -0800525 b->cacheAccess().setContentKey(key2);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000526 b->unref();
527
bsalomon71cb0c22014-11-14 12:10:14 -0800528 REPORTER_ASSERT(reporter, 200 == cache2->getResourceBytes());
529 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
bsalomon8b79d232014-11-10 10:19:06 -0800530 {
531 SkAutoTUnref<TestResource> find2(static_cast<TestResource*>(cache2->findAndRefContentResource(key2)));
532 find2->setSize(200);
533 SkAutoTUnref<TestResource> find1(static_cast<TestResource*>(cache2->findAndRefContentResource(key1)));
534 find1->setSize(50);
535 }
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000536
bsalomon71cb0c22014-11-14 12:10:14 -0800537 REPORTER_ASSERT(reporter, 250 == cache2->getResourceBytes());
538 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000539 }
540
541 // Test increasing a resources size beyond the cache budget.
542 {
bsalomon33435572014-11-05 14:47:41 -0800543 context->setResourceCacheLimits(2, 300);
bsalomon8b79d232014-11-10 10:19:06 -0800544 GrResourceCache2* cache2 = context->getResourceCache2();
bsalomon71cb0c22014-11-14 12:10:14 -0800545 cache2->purgeAllUnlocked();
546 SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000547
bsalomon8b79d232014-11-10 10:19:06 -0800548 TestResource* a = new TestResource(context->getGpu());
549 a->setSize(100);
bsalomon71cb0c22014-11-14 12:10:14 -0800550 a->cacheAccess().setContentKey(key1);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000551 a->unref();
552
bsalomon8b79d232014-11-10 10:19:06 -0800553 TestResource* b = new TestResource(context->getGpu());
554 b->setSize(100);
bsalomon71cb0c22014-11-14 12:10:14 -0800555 b->cacheAccess().setContentKey(key2);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000556 b->unref();
557
bsalomon71cb0c22014-11-14 12:10:14 -0800558 REPORTER_ASSERT(reporter, 200 == cache2->getResourceBytes());
559 REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000560
bsalomon8b79d232014-11-10 10:19:06 -0800561 {
562 SkAutoTUnref<TestResource> find2(static_cast<TestResource*>(cache2->findAndRefContentResource(key2)));
563 find2->setSize(201);
564 }
565 REPORTER_ASSERT(reporter, !cache2->hasContentKey(key1));
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000566
bsalomon71cb0c22014-11-14 12:10:14 -0800567 REPORTER_ASSERT(reporter, 201 == cache2->getResourceBytes());
568 REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000569 }
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000570}
571
bsalomon4e4303f2014-11-24 08:25:05 -0800572static void test_large_resource_count(skiatest::Reporter* reporter) {
573 SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
574 REPORTER_ASSERT(reporter, SkToBool(context));
575 if (NULL == context) {
576 return;
577 }
578
579 static const int kResourceCnt = 2000;
580 // Set the cache size to double the resource count because we're going to create 2x that number
581 // resources, using two different key domains. Add a little slop to the bytes because we resize
582 // down to 1 byte after creating the resource.
583 context->setResourceCacheLimits(2 * kResourceCnt, 2 * kResourceCnt + 1000);
584 GrResourceCache2* cache2 = context->getResourceCache2();
585 cache2->purgeAllUnlocked();
586 SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
587
588 GrCacheID::Domain domain0 = GrCacheID::GenerateDomain();
589 GrCacheID::Domain domain1 = GrCacheID::GenerateDomain();
590 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();
591
592 GrCacheID::Key keyData;
593 memset(&keyData, 0, sizeof(keyData));
594
595 for (int i = 0; i < kResourceCnt; ++i) {
596 TestResource* resource;
597 keyData.fData32[0] = i;
598
599 GrResourceKey key0(GrCacheID(domain0, keyData), t, 0);
600 resource = SkNEW_ARGS(TestResource, (context->getGpu()));
601 resource->cacheAccess().setContentKey(key0);
602 resource->setSize(1);
603 resource->unref();
604
605 GrResourceKey key1(GrCacheID(domain1, keyData), t, 0);
606 resource = SkNEW_ARGS(TestResource, (context->getGpu()));
607 resource->cacheAccess().setContentKey(key1);
608 resource->setSize(1);
609 resource->unref();
610 }
611
612 REPORTER_ASSERT(reporter, TestResource::NumAlive() == 2 * kResourceCnt);
613 REPORTER_ASSERT(reporter, cache2->getBudgetedResourceBytes() == 2 * kResourceCnt);
614 REPORTER_ASSERT(reporter, cache2->getBudgetedResourceCount() == 2 * kResourceCnt);
615 REPORTER_ASSERT(reporter, cache2->getResourceBytes() == 2 * kResourceCnt);
616 REPORTER_ASSERT(reporter, cache2->getResourceCount() == 2 * kResourceCnt);
617 for (int i = 0; i < kResourceCnt; ++i) {
618 keyData.fData32[0] = i;
619 GrResourceKey key0(GrCacheID(domain0, keyData), t, 0);
620 REPORTER_ASSERT(reporter, cache2->hasContentKey(key0));
621 GrResourceKey key1(GrCacheID(domain0, keyData), t, 0);
622 REPORTER_ASSERT(reporter, cache2->hasContentKey(key1));
623 }
624
625 cache2->purgeAllUnlocked();
626 REPORTER_ASSERT(reporter, TestResource::NumAlive() == 0);
627 REPORTER_ASSERT(reporter, cache2->getBudgetedResourceBytes() == 0);
628 REPORTER_ASSERT(reporter, cache2->getBudgetedResourceCount() == 0);
629 REPORTER_ASSERT(reporter, cache2->getResourceBytes() == 0);
630 REPORTER_ASSERT(reporter, cache2->getResourceCount() == 0);
631
632 for (int i = 0; i < kResourceCnt; ++i) {
633 keyData.fData32[0] = i;
634 GrResourceKey key0(GrCacheID(domain0, keyData), t, 0);
635 REPORTER_ASSERT(reporter, !cache2->hasContentKey(key0));
636 GrResourceKey key1(GrCacheID(domain0, keyData), t, 0);
637 REPORTER_ASSERT(reporter, !cache2->hasContentKey(key1));
638 }
639}
640
641
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000642////////////////////////////////////////////////////////////////////////////////
tfarina@chromium.org4ee16bf2014-01-10 22:08:27 +0000643DEF_GPUTEST(ResourceCache, reporter, factory) {
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000644 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
645 GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
646 if (!GrContextFactory::IsRenderingGLContext(glType)) {
647 continue;
648 }
649 GrContext* context = factory->get(glType);
bsalomonfdcf2c02014-11-05 12:30:32 -0800650 if (NULL == context) {
651 continue;
652 }
bsalomonf2703d82014-10-28 14:33:06 -0700653 GrSurfaceDesc desc;
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000654 desc.fConfig = kSkia8888_GrPixelConfig;
bsalomonf2703d82014-10-28 14:33:06 -0700655 desc.fFlags = kRenderTarget_GrSurfaceFlag;
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000656 desc.fWidth = gWidth;
657 desc.fHeight = gHeight;
reed69f6f002014-09-18 06:09:44 -0700658 SkImageInfo info = SkImageInfo::MakeN32Premul(gWidth, gHeight);
reed4a8126e2014-09-22 07:29:03 -0700659 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context, info));
reed69f6f002014-09-18 06:09:44 -0700660 test_cache(reporter, context, surface->getCanvas());
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000661 }
bsalomon33435572014-11-05 14:47:41 -0800662
bsalomon8b79d232014-11-10 10:19:06 -0800663 // The below tests create their own mock contexts.
bsalomon71cb0c22014-11-14 12:10:14 -0800664 test_no_key(reporter);
bsalomon84c8e622014-11-17 09:33:27 -0800665 test_budgeting(reporter);
bsalomon8b79d232014-11-10 10:19:06 -0800666 test_duplicate_content_key(reporter);
667 test_duplicate_scratch_key(reporter);
668 test_purge_invalidated(reporter);
bsalomon71cb0c22014-11-14 12:10:14 -0800669 test_cache_chained_purge(reporter);
bsalomon8b79d232014-11-10 10:19:06 -0800670 test_resource_size_changed(reporter);
bsalomon4e4303f2014-11-24 08:25:05 -0800671 test_large_resource_count(reporter);
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000672}
673
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000674#endif