blob: 44e41807d1f8783f0e6b0fc66b1607835c7f9ab8 [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"
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +000013#include "GrResourceCache.h"
bsalomon820dd6c2014-11-05 12:09:45 -080014#include "GrResourceCache2.h"
bsalomonbcf0a522014-10-08 08:40:09 -070015#include "SkCanvas.h"
reed69f6f002014-09-18 06:09:44 -070016#include "SkSurface.h"
tfarina@chromium.org4ee16bf2014-01-10 22:08:27 +000017#include "Test.h"
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000018
19static const int gWidth = 640;
20static const int gHeight = 480;
21
22////////////////////////////////////////////////////////////////////////////////
bsalomon820dd6c2014-11-05 12:09:45 -080023static void test_cache(skiatest::Reporter* reporter, GrContext* context, SkCanvas* canvas) {
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000024 const SkIRect size = SkIRect::MakeWH(gWidth, gHeight);
25
26 SkBitmap src;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +000027 src.allocN32Pixels(size.width(), size.height());
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000028 src.eraseColor(SK_ColorBLACK);
29 size_t srcSize = src.getSize();
30
commit-bot@chromium.org95c20032014-05-09 14:29:32 +000031 size_t initialCacheSize;
32 context->getResourceCacheUsage(NULL, &initialCacheSize);
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000033
34 int oldMaxNum;
35 size_t oldMaxBytes;
commit-bot@chromium.org95c20032014-05-09 14:29:32 +000036 context->getResourceCacheLimits(&oldMaxNum, &oldMaxBytes);
skia.committer@gmail.com17f1ae62013-08-09 07:01:22 +000037
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000038 // Set the cache limits so we can fit 10 "src" images and the
39 // max number of textures doesn't matter
40 size_t maxCacheSize = initialCacheSize + 10*srcSize;
commit-bot@chromium.org95c20032014-05-09 14:29:32 +000041 context->setResourceCacheLimits(1000, maxCacheSize);
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000042
43 SkBitmap readback;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +000044 readback.allocN32Pixels(size.width(), size.height());
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000045
46 for (int i = 0; i < 100; ++i) {
47 canvas->drawBitmap(src, 0, 0);
48 canvas->readPixels(size, &readback);
49
50 // "modify" the src texture
51 src.notifyPixelsChanged();
52
commit-bot@chromium.org95c20032014-05-09 14:29:32 +000053 size_t curCacheSize;
54 context->getResourceCacheUsage(NULL, &curCacheSize);
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000055
56 // we should never go over the size limit
57 REPORTER_ASSERT(reporter, curCacheSize <= maxCacheSize);
58 }
59
commit-bot@chromium.org95c20032014-05-09 14:29:32 +000060 context->setResourceCacheLimits(oldMaxNum, oldMaxBytes);
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000061}
62
bsalomon6d3fe022014-07-25 08:35:45 -070063class TestResource : public GrGpuResource {
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +000064 static const size_t kDefaultSize = 100;
65
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +000066public:
67 SK_DECLARE_INST_COUNT(TestResource);
bsalomonc44be0e2014-07-25 07:32:33 -070068 TestResource(GrGpu* gpu, size_t size = kDefaultSize)
69 : INHERITED(gpu, false)
70 , fCache(NULL)
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +000071 , fToDelete(NULL)
72 , fSize(size) {
bsalomon820dd6c2014-11-05 12:09:45 -080073 ++fNumAlive;
bsalomon16961262014-08-26 14:01:07 -070074 this->registerWithCache();
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +000075 }
76
77 ~TestResource() {
bsalomon820dd6c2014-11-05 12:09:45 -080078 --fNumAlive;
bsalomon49f085d2014-09-05 13:34:00 -070079 if (fToDelete) {
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +000080 // Breaks our little 2-element cycle below.
81 fToDelete->setDeleteWhenDestroyed(NULL, NULL);
82 fCache->deleteResource(fToDelete->getCacheEntry());
83 }
bsalomonc44be0e2014-07-25 07:32:33 -070084 this->release();
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +000085 }
86
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +000087 void setSize(size_t size) {
88 fSize = size;
89 this->didChangeGpuMemorySize();
90 }
91
92 size_t gpuMemorySize() const SK_OVERRIDE { return fSize; }
commit-bot@chromium.org089a7802014-05-02 21:38:22 +000093
bsalomon820dd6c2014-11-05 12:09:45 -080094 static int NumAlive() { return fNumAlive; }
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +000095
96 void setDeleteWhenDestroyed(GrResourceCache* cache, TestResource* resource) {
97 fCache = cache;
98 fToDelete = resource;
99 }
100
101private:
102 GrResourceCache* fCache;
103 TestResource* fToDelete;
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000104 size_t fSize;
bsalomon820dd6c2014-11-05 12:09:45 -0800105 static int fNumAlive;
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000106
bsalomon6d3fe022014-07-25 08:35:45 -0700107 typedef GrGpuResource INHERITED;
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000108};
bsalomon820dd6c2014-11-05 12:09:45 -0800109int TestResource::fNumAlive = 0;
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000110
111static void test_purge_invalidated(skiatest::Reporter* reporter, GrContext* context) {
112 GrCacheID::Domain domain = GrCacheID::GenerateDomain();
113 GrCacheID::Key keyData;
114 keyData.fData64[0] = 5;
115 keyData.fData64[1] = 18;
116 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();
117 GrResourceKey key(GrCacheID(domain, keyData), t, 0);
bsalomon820dd6c2014-11-05 12:09:45 -0800118
119 context->setResourceCacheLimits(5, 30000);
120 GrResourceCache* cache = context->getResourceCache();
121 cache->purgeAllUnlocked();
122 SkASSERT(0 == cache->getCachedResourceCount() && 0 == cache->getCachedResourceBytes());
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000123
124 // Add two resources with the same key that delete each other from the cache when destroyed.
bsalomonc44be0e2014-07-25 07:32:33 -0700125 TestResource* a = new TestResource(context->getGpu());
126 TestResource* b = new TestResource(context->getGpu());
bsalomon820dd6c2014-11-05 12:09:45 -0800127 cache->addResource(key, a);
128 cache->addResource(key, b);
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000129 // Circle back.
bsalomon820dd6c2014-11-05 12:09:45 -0800130 a->setDeleteWhenDestroyed(cache, b);
131 b->setDeleteWhenDestroyed(cache, a);
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000132 a->unref();
133 b->unref();
134
135 // Add a third independent resource also with the same key.
bsalomon6d3fe022014-07-25 08:35:45 -0700136 GrGpuResource* r = new TestResource(context->getGpu());
bsalomon820dd6c2014-11-05 12:09:45 -0800137 cache->addResource(key, r);
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000138 r->unref();
139
140 // Invalidate all three, all three should be purged and destroyed.
bsalomon820dd6c2014-11-05 12:09:45 -0800141 REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000142 const GrResourceInvalidatedMessage msg = { key };
143 SkMessageBus<GrResourceInvalidatedMessage>::Post(msg);
bsalomon820dd6c2014-11-05 12:09:45 -0800144 cache->purgeAsNeeded();
145 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000146}
147
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000148static void test_cache_delete_on_destruction(skiatest::Reporter* reporter,
149 GrContext* context) {
150 GrCacheID::Domain domain = GrCacheID::GenerateDomain();
151 GrCacheID::Key keyData;
152 keyData.fData64[0] = 5;
153 keyData.fData64[1] = 0;
154 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();
155
156 GrResourceKey key(GrCacheID(domain, keyData), t, 0);
157
158 {
bsalomon820dd6c2014-11-05 12:09:45 -0800159 context->setResourceCacheLimits(3, 30000);
160 GrResourceCache* cache = context->getResourceCache();
161 cache->purgeAllUnlocked();
162 SkASSERT(0 == cache->getCachedResourceCount() && 0 == cache->getCachedResourceBytes());
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000163
bsalomonc44be0e2014-07-25 07:32:33 -0700164 TestResource* a = new TestResource(context->getGpu());
165 TestResource* b = new TestResource(context->getGpu());
bsalomon820dd6c2014-11-05 12:09:45 -0800166 cache->addResource(key, a);
167 cache->addResource(key, b);
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000168
bsalomon820dd6c2014-11-05 12:09:45 -0800169 a->setDeleteWhenDestroyed(cache, b);
170 b->setDeleteWhenDestroyed(cache, a);
171
172 a->unref();
173 b->unref();
174 REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
175 cache->purgeAllUnlocked();
176 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
177 }
178 {
179 context->setResourceCacheLimits(3, 30000);
180 GrResourceCache* cache = context->getResourceCache();
181 cache->purgeAllUnlocked();
182 SkASSERT(0 == cache->getCachedResourceCount() && 0 == cache->getCachedResourceBytes());
183 TestResource* a = new TestResource(context->getGpu());
184 TestResource* b = new TestResource(context->getGpu());
185 cache->addResource(key, a);
186 cache->addResource(key, b);
187
188 a->setDeleteWhenDestroyed(cache, b);
189 b->setDeleteWhenDestroyed(cache, a);
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000190
191 a->unref();
192 b->unref();
193
bsalomon820dd6c2014-11-05 12:09:45 -0800194 cache->deleteResource(a->getCacheEntry());
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000195
bsalomon820dd6c2014-11-05 12:09:45 -0800196 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000197 }
198}
199
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000200static void test_resource_size_changed(skiatest::Reporter* reporter,
201 GrContext* context) {
202 GrCacheID::Domain domain = GrCacheID::GenerateDomain();
203 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();
204
205 GrCacheID::Key key1Data;
206 key1Data.fData64[0] = 0;
207 key1Data.fData64[1] = 0;
208 GrResourceKey key1(GrCacheID(domain, key1Data), t, 0);
209
210 GrCacheID::Key key2Data;
211 key2Data.fData64[0] = 1;
212 key2Data.fData64[1] = 0;
213 GrResourceKey key2(GrCacheID(domain, key2Data), t, 0);
214
215 // Test changing resources sizes (both increase & decrease).
216 {
bsalomon820dd6c2014-11-05 12:09:45 -0800217 context->setResourceCacheLimits(3, 30000);
218 GrResourceCache* cache = context->getResourceCache();
219 cache->purgeAllUnlocked();
220 SkASSERT(0 == cache->getCachedResourceCount() && 0 == cache->getCachedResourceBytes());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000221
bsalomonc44be0e2014-07-25 07:32:33 -0700222 TestResource* a = new TestResource(context->getGpu());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000223 a->setSize(100); // Test didChangeGpuMemorySize() when not in the cache.
bsalomon820dd6c2014-11-05 12:09:45 -0800224 cache->addResource(key1, a);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000225 a->unref();
226
bsalomonc44be0e2014-07-25 07:32:33 -0700227 TestResource* b = new TestResource(context->getGpu());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000228 b->setSize(100);
bsalomon820dd6c2014-11-05 12:09:45 -0800229 cache->addResource(key2, b);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000230 b->unref();
231
bsalomon820dd6c2014-11-05 12:09:45 -0800232 REPORTER_ASSERT(reporter, 200 == cache->getCachedResourceBytes());
233 REPORTER_ASSERT(reporter, 2 == cache->getCachedResourceCount());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000234
bsalomon820dd6c2014-11-05 12:09:45 -0800235 static_cast<TestResource*>(cache->find(key2))->setSize(200);
236 static_cast<TestResource*>(cache->find(key1))->setSize(50);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000237
bsalomon820dd6c2014-11-05 12:09:45 -0800238 REPORTER_ASSERT(reporter, 250 == cache->getCachedResourceBytes());
239 REPORTER_ASSERT(reporter, 2 == cache->getCachedResourceCount());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000240 }
241
242 // Test increasing a resources size beyond the cache budget.
243 {
bsalomon820dd6c2014-11-05 12:09:45 -0800244 context->setResourceCacheLimits(2, 300);
245 GrResourceCache* cache = context->getResourceCache();
246 cache->purgeAllUnlocked();
247 SkASSERT(0 == cache->getCachedResourceCount() && 0 == cache->getCachedResourceBytes());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000248
bsalomonc44be0e2014-07-25 07:32:33 -0700249 TestResource* a = new TestResource(context->getGpu(), 100);
bsalomon820dd6c2014-11-05 12:09:45 -0800250 cache->addResource(key1, a);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000251 a->unref();
252
bsalomonc44be0e2014-07-25 07:32:33 -0700253 TestResource* b = new TestResource(context->getGpu(), 100);
bsalomon820dd6c2014-11-05 12:09:45 -0800254 cache->addResource(key2, b);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000255 b->unref();
256
bsalomon820dd6c2014-11-05 12:09:45 -0800257 REPORTER_ASSERT(reporter, 200 == cache->getCachedResourceBytes());
258 REPORTER_ASSERT(reporter, 2 == cache->getCachedResourceCount());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000259
bsalomon820dd6c2014-11-05 12:09:45 -0800260 static_cast<TestResource*>(cache->find(key2))->setSize(201);
261 REPORTER_ASSERT(reporter, !cache->hasKey(key1));
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000262
bsalomon820dd6c2014-11-05 12:09:45 -0800263 REPORTER_ASSERT(reporter, 201 == cache->getCachedResourceBytes());
264 REPORTER_ASSERT(reporter, 1 == cache->getCachedResourceCount());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000265 }
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000266}
267
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000268////////////////////////////////////////////////////////////////////////////////
tfarina@chromium.org4ee16bf2014-01-10 22:08:27 +0000269DEF_GPUTEST(ResourceCache, reporter, factory) {
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000270 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
271 GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
272 if (!GrContextFactory::IsRenderingGLContext(glType)) {
273 continue;
274 }
275 GrContext* context = factory->get(glType);
bsalomonf2703d82014-10-28 14:33:06 -0700276 GrSurfaceDesc desc;
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000277 desc.fConfig = kSkia8888_GrPixelConfig;
bsalomonf2703d82014-10-28 14:33:06 -0700278 desc.fFlags = kRenderTarget_GrSurfaceFlag;
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000279 desc.fWidth = gWidth;
280 desc.fHeight = gHeight;
reed69f6f002014-09-18 06:09:44 -0700281 SkImageInfo info = SkImageInfo::MakeN32Premul(gWidth, gHeight);
reed4a8126e2014-09-22 07:29:03 -0700282 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context, info));
reed69f6f002014-09-18 06:09:44 -0700283 test_cache(reporter, context, surface->getCanvas());
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000284 }
bsalomon820dd6c2014-11-05 12:09:45 -0800285
286 // The below tests use a mock context.
287 SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
288 REPORTER_ASSERT(reporter, SkToBool(context));
289 if (NULL == context) {
290 return;
291 }
292
293 test_purge_invalidated(reporter, context);
294 test_cache_delete_on_destruction(reporter, context);
295 test_resource_size_changed(reporter, context);
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000296}
297
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000298#endif