blob: c08e75f62c0ec389c02bab67a7b25d4daecbcc6c [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
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000010#include "GrContextFactory.h"
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +000011#include "GrResourceCache.h"
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000012#include "SkGpuDevice.h"
tfarina@chromium.org4ee16bf2014-01-10 22:08:27 +000013#include "Test.h"
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000014
15static const int gWidth = 640;
16static const int gHeight = 480;
17
18////////////////////////////////////////////////////////////////////////////////
skia.committer@gmail.com17f1ae62013-08-09 07:01:22 +000019static void test_cache(skiatest::Reporter* reporter,
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000020 GrContext* context,
21 SkCanvas* canvas) {
22 const SkIRect size = SkIRect::MakeWH(gWidth, gHeight);
23
24 SkBitmap src;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +000025 src.allocN32Pixels(size.width(), size.height());
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000026 src.eraseColor(SK_ColorBLACK);
27 size_t srcSize = src.getSize();
28
commit-bot@chromium.org95c20032014-05-09 14:29:32 +000029 size_t initialCacheSize;
30 context->getResourceCacheUsage(NULL, &initialCacheSize);
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000031
32 int oldMaxNum;
33 size_t oldMaxBytes;
commit-bot@chromium.org95c20032014-05-09 14:29:32 +000034 context->getResourceCacheLimits(&oldMaxNum, &oldMaxBytes);
skia.committer@gmail.com17f1ae62013-08-09 07:01:22 +000035
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000036 // Set the cache limits so we can fit 10 "src" images and the
37 // max number of textures doesn't matter
38 size_t maxCacheSize = initialCacheSize + 10*srcSize;
commit-bot@chromium.org95c20032014-05-09 14:29:32 +000039 context->setResourceCacheLimits(1000, maxCacheSize);
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000040
41 SkBitmap readback;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +000042 readback.allocN32Pixels(size.width(), size.height());
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000043
44 for (int i = 0; i < 100; ++i) {
45 canvas->drawBitmap(src, 0, 0);
46 canvas->readPixels(size, &readback);
47
48 // "modify" the src texture
49 src.notifyPixelsChanged();
50
commit-bot@chromium.org95c20032014-05-09 14:29:32 +000051 size_t curCacheSize;
52 context->getResourceCacheUsage(NULL, &curCacheSize);
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000053
54 // we should never go over the size limit
55 REPORTER_ASSERT(reporter, curCacheSize <= maxCacheSize);
56 }
57
commit-bot@chromium.org95c20032014-05-09 14:29:32 +000058 context->setResourceCacheLimits(oldMaxNum, oldMaxBytes);
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +000059}
60
bsalomon6d3fe022014-07-25 08:35:45 -070061class TestResource : public GrGpuResource {
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +000062 static const size_t kDefaultSize = 100;
63
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +000064public:
65 SK_DECLARE_INST_COUNT(TestResource);
bsalomonc44be0e2014-07-25 07:32:33 -070066 TestResource(GrGpu* gpu, size_t size = kDefaultSize)
67 : INHERITED(gpu, false)
68 , fCache(NULL)
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +000069 , fToDelete(NULL)
70 , fSize(size) {
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +000071 ++fAlive;
bsalomon16961262014-08-26 14:01:07 -070072 this->registerWithCache();
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +000073 }
74
75 ~TestResource() {
76 --fAlive;
77 if (NULL != fToDelete) {
78 // Breaks our little 2-element cycle below.
79 fToDelete->setDeleteWhenDestroyed(NULL, NULL);
80 fCache->deleteResource(fToDelete->getCacheEntry());
81 }
bsalomonc44be0e2014-07-25 07:32:33 -070082 this->release();
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +000083 }
84
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +000085 void setSize(size_t size) {
86 fSize = size;
87 this->didChangeGpuMemorySize();
88 }
89
90 size_t gpuMemorySize() const SK_OVERRIDE { return fSize; }
commit-bot@chromium.org089a7802014-05-02 21:38:22 +000091
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +000092 static int alive() { return fAlive; }
93
94 void setDeleteWhenDestroyed(GrResourceCache* cache, TestResource* resource) {
95 fCache = cache;
96 fToDelete = resource;
97 }
98
99private:
100 GrResourceCache* fCache;
101 TestResource* fToDelete;
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000102 size_t fSize;
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000103 static int fAlive;
104
bsalomon6d3fe022014-07-25 08:35:45 -0700105 typedef GrGpuResource INHERITED;
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000106};
107int TestResource::fAlive = 0;
108
109static void test_purge_invalidated(skiatest::Reporter* reporter, GrContext* context) {
110 GrCacheID::Domain domain = GrCacheID::GenerateDomain();
111 GrCacheID::Key keyData;
112 keyData.fData64[0] = 5;
113 keyData.fData64[1] = 18;
114 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();
115 GrResourceKey key(GrCacheID(domain, keyData), t, 0);
116
117 GrResourceCache cache(5, 30000);
118
119 // Add two resources with the same key that delete each other from the cache when destroyed.
bsalomonc44be0e2014-07-25 07:32:33 -0700120 TestResource* a = new TestResource(context->getGpu());
121 TestResource* b = new TestResource(context->getGpu());
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000122 cache.addResource(key, a);
123 cache.addResource(key, b);
124 // Circle back.
125 a->setDeleteWhenDestroyed(&cache, b);
126 b->setDeleteWhenDestroyed(&cache, a);
127 a->unref();
128 b->unref();
129
130 // Add a third independent resource also with the same key.
bsalomon6d3fe022014-07-25 08:35:45 -0700131 GrGpuResource* r = new TestResource(context->getGpu());
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000132 cache.addResource(key, r);
133 r->unref();
134
135 // Invalidate all three, all three should be purged and destroyed.
136 REPORTER_ASSERT(reporter, 3 == TestResource::alive());
137 const GrResourceInvalidatedMessage msg = { key };
138 SkMessageBus<GrResourceInvalidatedMessage>::Post(msg);
139 cache.purgeAsNeeded();
140 REPORTER_ASSERT(reporter, 0 == TestResource::alive());
141}
142
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000143static void test_cache_delete_on_destruction(skiatest::Reporter* reporter,
144 GrContext* context) {
145 GrCacheID::Domain domain = GrCacheID::GenerateDomain();
146 GrCacheID::Key keyData;
147 keyData.fData64[0] = 5;
148 keyData.fData64[1] = 0;
149 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();
150
151 GrResourceKey key(GrCacheID(domain, keyData), t, 0);
152
153 {
154 {
155 GrResourceCache cache(3, 30000);
bsalomonc44be0e2014-07-25 07:32:33 -0700156 TestResource* a = new TestResource(context->getGpu());
157 TestResource* b = new TestResource(context->getGpu());
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000158 cache.addResource(key, a);
159 cache.addResource(key, b);
160
161 a->setDeleteWhenDestroyed(&cache, b);
162 b->setDeleteWhenDestroyed(&cache, a);
163
164 a->unref();
165 b->unref();
166 REPORTER_ASSERT(reporter, 2 == TestResource::alive());
167 }
168 REPORTER_ASSERT(reporter, 0 == TestResource::alive());
169 }
170 {
171 GrResourceCache cache(3, 30000);
bsalomonc44be0e2014-07-25 07:32:33 -0700172 TestResource* a = new TestResource(context->getGpu());
173 TestResource* b = new TestResource(context->getGpu());
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000174 cache.addResource(key, a);
175 cache.addResource(key, b);
176
177 a->setDeleteWhenDestroyed(&cache, b);
178 b->setDeleteWhenDestroyed(&cache, a);
179
180 a->unref();
181 b->unref();
182
183 cache.deleteResource(a->getCacheEntry());
184
185 REPORTER_ASSERT(reporter, 0 == TestResource::alive());
186 }
187}
188
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000189static void test_resource_size_changed(skiatest::Reporter* reporter,
190 GrContext* context) {
191 GrCacheID::Domain domain = GrCacheID::GenerateDomain();
192 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();
193
194 GrCacheID::Key key1Data;
195 key1Data.fData64[0] = 0;
196 key1Data.fData64[1] = 0;
197 GrResourceKey key1(GrCacheID(domain, key1Data), t, 0);
198
199 GrCacheID::Key key2Data;
200 key2Data.fData64[0] = 1;
201 key2Data.fData64[1] = 0;
202 GrResourceKey key2(GrCacheID(domain, key2Data), t, 0);
203
204 // Test changing resources sizes (both increase & decrease).
205 {
206 GrResourceCache cache(2, 300);
207
bsalomonc44be0e2014-07-25 07:32:33 -0700208 TestResource* a = new TestResource(context->getGpu());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000209 a->setSize(100); // Test didChangeGpuMemorySize() when not in the cache.
210 cache.addResource(key1, a);
211 a->unref();
212
bsalomonc44be0e2014-07-25 07:32:33 -0700213 TestResource* b = new TestResource(context->getGpu());
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000214 b->setSize(100);
215 cache.addResource(key2, b);
216 b->unref();
217
218 REPORTER_ASSERT(reporter, 200 == cache.getCachedResourceBytes());
219 REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount());
220
221 static_cast<TestResource*>(cache.find(key2))->setSize(200);
222 static_cast<TestResource*>(cache.find(key1))->setSize(50);
223
224 REPORTER_ASSERT(reporter, 250 == cache.getCachedResourceBytes());
225 REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount());
226 }
227
228 // Test increasing a resources size beyond the cache budget.
229 {
230 GrResourceCache cache(2, 300);
231
bsalomonc44be0e2014-07-25 07:32:33 -0700232 TestResource* a = new TestResource(context->getGpu(), 100);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000233 cache.addResource(key1, a);
234 a->unref();
235
bsalomonc44be0e2014-07-25 07:32:33 -0700236 TestResource* b = new TestResource(context->getGpu(), 100);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000237 cache.addResource(key2, b);
238 b->unref();
239
240 REPORTER_ASSERT(reporter, 200 == cache.getCachedResourceBytes());
241 REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount());
242
243 static_cast<TestResource*>(cache.find(key2))->setSize(201);
244 REPORTER_ASSERT(reporter, NULL == cache.find(key1));
245
246 REPORTER_ASSERT(reporter, 201 == cache.getCachedResourceBytes());
247 REPORTER_ASSERT(reporter, 1 == cache.getCachedResourceCount());
248 }
249
250 // Test changing the size of an exclusively-held resource.
251 {
252 GrResourceCache cache(2, 300);
253
bsalomonc44be0e2014-07-25 07:32:33 -0700254 TestResource* a = new TestResource(context->getGpu(), 100);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000255 cache.addResource(key1, a);
256 cache.makeExclusive(a->getCacheEntry());
257
bsalomonc44be0e2014-07-25 07:32:33 -0700258 TestResource* b = new TestResource(context->getGpu(), 100);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000259 cache.addResource(key2, b);
260 b->unref();
261
262 REPORTER_ASSERT(reporter, 200 == cache.getCachedResourceBytes());
263 REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount());
264 REPORTER_ASSERT(reporter, NULL == cache.find(key1));
265
266 a->setSize(200);
267
268 REPORTER_ASSERT(reporter, 300 == cache.getCachedResourceBytes());
269 REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount());
270 // Internal resource cache validation will test the detached size (debug mode only).
271
272 cache.makeNonExclusive(a->getCacheEntry());
273 a->unref();
274
275 REPORTER_ASSERT(reporter, 300 == cache.getCachedResourceBytes());
276 REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount());
277 REPORTER_ASSERT(reporter, NULL != cache.find(key1));
278 // Internal resource cache validation will test the detached size (debug mode only).
279 }
280}
281
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000282////////////////////////////////////////////////////////////////////////////////
tfarina@chromium.org4ee16bf2014-01-10 22:08:27 +0000283DEF_GPUTEST(ResourceCache, reporter, factory) {
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000284 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
285 GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
286 if (!GrContextFactory::IsRenderingGLContext(glType)) {
287 continue;
288 }
289 GrContext* context = factory->get(glType);
290 if (NULL == context) {
291 continue;
292 }
293
294 GrTextureDesc desc;
295 desc.fConfig = kSkia8888_GrPixelConfig;
296 desc.fFlags = kRenderTarget_GrTextureFlagBit;
297 desc.fWidth = gWidth;
298 desc.fHeight = gHeight;
299
300 SkAutoTUnref<GrTexture> texture(context->createUncachedTexture(desc, NULL, 0));
bsalomon23b406c2014-08-28 14:06:42 -0700301 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(texture.get()));
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000302 SkCanvas canvas(device.get());
303
304 test_cache(reporter, context, &canvas);
commit-bot@chromium.orgc6658042014-01-15 23:09:01 +0000305 test_purge_invalidated(reporter, context);
commit-bot@chromium.orgbd58feb2014-01-17 17:56:21 +0000306 test_cache_delete_on_destruction(reporter, context);
commit-bot@chromium.org11c6b392014-05-05 19:09:13 +0000307 test_resource_size_changed(reporter, context);
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000308 }
309}
310
commit-bot@chromium.orgc28f5552013-08-08 22:55:21 +0000311#endif