OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #if SK_SUPPORT_GPU | 8 #if SK_SUPPORT_GPU |
9 | 9 |
10 #include "GrContext.h" | 10 #include "GrContext.h" |
11 #include "GrContextFactory.h" | 11 #include "GrContextFactory.h" |
12 #include "GrGpu.h" | 12 #include "GrGpu.h" |
13 #include "GrResourceCache.h" | 13 #include "GrResourceCache.h" |
14 #include "GrResourceCache2.h" | |
15 #include "SkCanvas.h" | 14 #include "SkCanvas.h" |
16 #include "SkSurface.h" | 15 #include "SkSurface.h" |
17 #include "Test.h" | 16 #include "Test.h" |
18 | 17 |
19 static const int gWidth = 640; | 18 static const int gWidth = 640; |
20 static const int gHeight = 480; | 19 static const int gHeight = 480; |
21 | 20 |
22 //////////////////////////////////////////////////////////////////////////////// | 21 //////////////////////////////////////////////////////////////////////////////// |
23 static void test_cache(skiatest::Reporter* reporter, GrContext* context, SkCanva
s* canvas) { | 22 static void test_cache(skiatest::Reporter* reporter, |
| 23 GrContext* context, |
| 24 SkCanvas* canvas) { |
24 const SkIRect size = SkIRect::MakeWH(gWidth, gHeight); | 25 const SkIRect size = SkIRect::MakeWH(gWidth, gHeight); |
25 | 26 |
26 SkBitmap src; | 27 SkBitmap src; |
27 src.allocN32Pixels(size.width(), size.height()); | 28 src.allocN32Pixels(size.width(), size.height()); |
28 src.eraseColor(SK_ColorBLACK); | 29 src.eraseColor(SK_ColorBLACK); |
29 size_t srcSize = src.getSize(); | 30 size_t srcSize = src.getSize(); |
30 | 31 |
31 size_t initialCacheSize; | 32 size_t initialCacheSize; |
32 context->getResourceCacheUsage(NULL, &initialCacheSize); | 33 context->getResourceCacheUsage(NULL, &initialCacheSize); |
33 | 34 |
(...skipping 29 matching lines...) Expand all Loading... |
63 class TestResource : public GrGpuResource { | 64 class TestResource : public GrGpuResource { |
64 static const size_t kDefaultSize = 100; | 65 static const size_t kDefaultSize = 100; |
65 | 66 |
66 public: | 67 public: |
67 SK_DECLARE_INST_COUNT(TestResource); | 68 SK_DECLARE_INST_COUNT(TestResource); |
68 TestResource(GrGpu* gpu, size_t size = kDefaultSize) | 69 TestResource(GrGpu* gpu, size_t size = kDefaultSize) |
69 : INHERITED(gpu, false) | 70 : INHERITED(gpu, false) |
70 , fCache(NULL) | 71 , fCache(NULL) |
71 , fToDelete(NULL) | 72 , fToDelete(NULL) |
72 , fSize(size) { | 73 , fSize(size) { |
73 ++fNumAlive; | 74 ++fAlive; |
74 this->registerWithCache(); | 75 this->registerWithCache(); |
75 } | 76 } |
76 | 77 |
77 ~TestResource() { | 78 ~TestResource() { |
78 --fNumAlive; | 79 --fAlive; |
79 if (fToDelete) { | 80 if (fToDelete) { |
80 // Breaks our little 2-element cycle below. | 81 // Breaks our little 2-element cycle below. |
81 fToDelete->setDeleteWhenDestroyed(NULL, NULL); | 82 fToDelete->setDeleteWhenDestroyed(NULL, NULL); |
82 fCache->deleteResource(fToDelete->getCacheEntry()); | 83 fCache->deleteResource(fToDelete->getCacheEntry()); |
83 } | 84 } |
84 this->release(); | 85 this->release(); |
85 } | 86 } |
86 | 87 |
87 void setSize(size_t size) { | 88 void setSize(size_t size) { |
88 fSize = size; | 89 fSize = size; |
89 this->didChangeGpuMemorySize(); | 90 this->didChangeGpuMemorySize(); |
90 } | 91 } |
91 | 92 |
92 size_t gpuMemorySize() const SK_OVERRIDE { return fSize; } | 93 size_t gpuMemorySize() const SK_OVERRIDE { return fSize; } |
93 | 94 |
94 static int NumAlive() { return fNumAlive; } | 95 static int alive() { return fAlive; } |
95 | 96 |
96 void setDeleteWhenDestroyed(GrResourceCache* cache, TestResource* resource)
{ | 97 void setDeleteWhenDestroyed(GrResourceCache* cache, TestResource* resource)
{ |
97 fCache = cache; | 98 fCache = cache; |
98 fToDelete = resource; | 99 fToDelete = resource; |
99 } | 100 } |
100 | 101 |
101 private: | 102 private: |
102 GrResourceCache* fCache; | 103 GrResourceCache* fCache; |
103 TestResource* fToDelete; | 104 TestResource* fToDelete; |
104 size_t fSize; | 105 size_t fSize; |
105 static int fNumAlive; | 106 static int fAlive; |
106 | 107 |
107 typedef GrGpuResource INHERITED; | 108 typedef GrGpuResource INHERITED; |
108 }; | 109 }; |
109 int TestResource::fNumAlive = 0; | 110 int TestResource::fAlive = 0; |
110 | 111 |
111 static void test_purge_invalidated(skiatest::Reporter* reporter, GrContext* cont
ext) { | 112 static void test_purge_invalidated(skiatest::Reporter* reporter, GrContext* cont
ext) { |
112 GrCacheID::Domain domain = GrCacheID::GenerateDomain(); | 113 GrCacheID::Domain domain = GrCacheID::GenerateDomain(); |
113 GrCacheID::Key keyData; | 114 GrCacheID::Key keyData; |
114 keyData.fData64[0] = 5; | 115 keyData.fData64[0] = 5; |
115 keyData.fData64[1] = 18; | 116 keyData.fData64[1] = 18; |
116 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType(); | 117 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType(); |
117 GrResourceKey key(GrCacheID(domain, keyData), t, 0); | 118 GrResourceKey key(GrCacheID(domain, keyData), t, 0); |
118 | 119 |
119 context->setResourceCacheLimits(5, 30000); | 120 GrResourceCache cache(context->getGpu()->caps(), 5, 30000); |
120 GrResourceCache* cache = context->getResourceCache(); | |
121 cache->purgeAllUnlocked(); | |
122 SkASSERT(0 == cache->getCachedResourceCount() && 0 == cache->getCachedResour
ceBytes()); | |
123 | 121 |
124 // Add two resources with the same key that delete each other from the cache
when destroyed. | 122 // Add two resources with the same key that delete each other from the cache
when destroyed. |
125 TestResource* a = new TestResource(context->getGpu()); | 123 TestResource* a = new TestResource(context->getGpu()); |
126 TestResource* b = new TestResource(context->getGpu()); | 124 TestResource* b = new TestResource(context->getGpu()); |
127 cache->addResource(key, a); | 125 cache.addResource(key, a); |
128 cache->addResource(key, b); | 126 cache.addResource(key, b); |
129 // Circle back. | 127 // Circle back. |
130 a->setDeleteWhenDestroyed(cache, b); | 128 a->setDeleteWhenDestroyed(&cache, b); |
131 b->setDeleteWhenDestroyed(cache, a); | 129 b->setDeleteWhenDestroyed(&cache, a); |
132 a->unref(); | 130 a->unref(); |
133 b->unref(); | 131 b->unref(); |
134 | 132 |
135 // Add a third independent resource also with the same key. | 133 // Add a third independent resource also with the same key. |
136 GrGpuResource* r = new TestResource(context->getGpu()); | 134 GrGpuResource* r = new TestResource(context->getGpu()); |
137 cache->addResource(key, r); | 135 cache.addResource(key, r); |
138 r->unref(); | 136 r->unref(); |
139 | 137 |
140 // Invalidate all three, all three should be purged and destroyed. | 138 // Invalidate all three, all three should be purged and destroyed. |
141 REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive()); | 139 REPORTER_ASSERT(reporter, 3 == TestResource::alive()); |
142 const GrResourceInvalidatedMessage msg = { key }; | 140 const GrResourceInvalidatedMessage msg = { key }; |
143 SkMessageBus<GrResourceInvalidatedMessage>::Post(msg); | 141 SkMessageBus<GrResourceInvalidatedMessage>::Post(msg); |
144 cache->purgeAsNeeded(); | 142 cache.purgeAsNeeded(); |
145 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive()); | 143 REPORTER_ASSERT(reporter, 0 == TestResource::alive()); |
146 } | 144 } |
147 | 145 |
148 static void test_cache_delete_on_destruction(skiatest::Reporter* reporter, | 146 static void test_cache_delete_on_destruction(skiatest::Reporter* reporter, |
149 GrContext* context) { | 147 GrContext* context) { |
150 GrCacheID::Domain domain = GrCacheID::GenerateDomain(); | 148 GrCacheID::Domain domain = GrCacheID::GenerateDomain(); |
151 GrCacheID::Key keyData; | 149 GrCacheID::Key keyData; |
152 keyData.fData64[0] = 5; | 150 keyData.fData64[0] = 5; |
153 keyData.fData64[1] = 0; | 151 keyData.fData64[1] = 0; |
154 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType(); | 152 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType(); |
155 | 153 |
156 GrResourceKey key(GrCacheID(domain, keyData), t, 0); | 154 GrResourceKey key(GrCacheID(domain, keyData), t, 0); |
157 | 155 |
158 { | 156 { |
159 context->setResourceCacheLimits(3, 30000); | 157 { |
160 GrResourceCache* cache = context->getResourceCache(); | 158 GrResourceCache cache(context->getGpu()->caps(), 3, 30000); |
161 cache->purgeAllUnlocked(); | 159 TestResource* a = new TestResource(context->getGpu()); |
162 SkASSERT(0 == cache->getCachedResourceCount() && 0 == cache->getCachedRe
sourceBytes()); | 160 TestResource* b = new TestResource(context->getGpu()); |
| 161 cache.addResource(key, a); |
| 162 cache.addResource(key, b); |
163 | 163 |
| 164 a->setDeleteWhenDestroyed(&cache, b); |
| 165 b->setDeleteWhenDestroyed(&cache, a); |
| 166 |
| 167 a->unref(); |
| 168 b->unref(); |
| 169 REPORTER_ASSERT(reporter, 2 == TestResource::alive()); |
| 170 } |
| 171 REPORTER_ASSERT(reporter, 0 == TestResource::alive()); |
| 172 } |
| 173 { |
| 174 GrResourceCache cache(context->getGpu()->caps(), 3, 30000); |
164 TestResource* a = new TestResource(context->getGpu()); | 175 TestResource* a = new TestResource(context->getGpu()); |
165 TestResource* b = new TestResource(context->getGpu()); | 176 TestResource* b = new TestResource(context->getGpu()); |
166 cache->addResource(key, a); | 177 cache.addResource(key, a); |
167 cache->addResource(key, b); | 178 cache.addResource(key, b); |
168 | 179 |
169 a->setDeleteWhenDestroyed(cache, b); | 180 a->setDeleteWhenDestroyed(&cache, b); |
170 b->setDeleteWhenDestroyed(cache, a); | 181 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->getCachedRe
sourceBytes()); | |
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); | |
190 | 182 |
191 a->unref(); | 183 a->unref(); |
192 b->unref(); | 184 b->unref(); |
193 | 185 |
194 cache->deleteResource(a->getCacheEntry()); | 186 cache.deleteResource(a->getCacheEntry()); |
195 | 187 |
196 REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive()); | 188 REPORTER_ASSERT(reporter, 0 == TestResource::alive()); |
197 } | 189 } |
198 } | 190 } |
199 | 191 |
200 static void test_resource_size_changed(skiatest::Reporter* reporter, | 192 static void test_resource_size_changed(skiatest::Reporter* reporter, |
201 GrContext* context) { | 193 GrContext* context) { |
202 GrCacheID::Domain domain = GrCacheID::GenerateDomain(); | 194 GrCacheID::Domain domain = GrCacheID::GenerateDomain(); |
203 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType(); | 195 GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType(); |
204 | 196 |
205 GrCacheID::Key key1Data; | 197 GrCacheID::Key key1Data; |
206 key1Data.fData64[0] = 0; | 198 key1Data.fData64[0] = 0; |
207 key1Data.fData64[1] = 0; | 199 key1Data.fData64[1] = 0; |
208 GrResourceKey key1(GrCacheID(domain, key1Data), t, 0); | 200 GrResourceKey key1(GrCacheID(domain, key1Data), t, 0); |
209 | 201 |
210 GrCacheID::Key key2Data; | 202 GrCacheID::Key key2Data; |
211 key2Data.fData64[0] = 1; | 203 key2Data.fData64[0] = 1; |
212 key2Data.fData64[1] = 0; | 204 key2Data.fData64[1] = 0; |
213 GrResourceKey key2(GrCacheID(domain, key2Data), t, 0); | 205 GrResourceKey key2(GrCacheID(domain, key2Data), t, 0); |
214 | 206 |
215 // Test changing resources sizes (both increase & decrease). | 207 // Test changing resources sizes (both increase & decrease). |
216 { | 208 { |
217 context->setResourceCacheLimits(3, 30000); | 209 GrResourceCache cache(context->getGpu()->caps(), 2, 300); |
218 GrResourceCache* cache = context->getResourceCache(); | |
219 cache->purgeAllUnlocked(); | |
220 SkASSERT(0 == cache->getCachedResourceCount() && 0 == cache->getCachedRe
sourceBytes()); | |
221 | 210 |
222 TestResource* a = new TestResource(context->getGpu()); | 211 TestResource* a = new TestResource(context->getGpu()); |
223 a->setSize(100); // Test didChangeGpuMemorySize() when not in the cache. | 212 a->setSize(100); // Test didChangeGpuMemorySize() when not in the cache. |
224 cache->addResource(key1, a); | 213 cache.addResource(key1, a); |
225 a->unref(); | 214 a->unref(); |
226 | 215 |
227 TestResource* b = new TestResource(context->getGpu()); | 216 TestResource* b = new TestResource(context->getGpu()); |
228 b->setSize(100); | 217 b->setSize(100); |
229 cache->addResource(key2, b); | 218 cache.addResource(key2, b); |
230 b->unref(); | 219 b->unref(); |
231 | 220 |
232 REPORTER_ASSERT(reporter, 200 == cache->getCachedResourceBytes()); | 221 REPORTER_ASSERT(reporter, 200 == cache.getCachedResourceBytes()); |
233 REPORTER_ASSERT(reporter, 2 == cache->getCachedResourceCount()); | 222 REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount()); |
234 | 223 |
235 static_cast<TestResource*>(cache->find(key2))->setSize(200); | 224 static_cast<TestResource*>(cache.find(key2))->setSize(200); |
236 static_cast<TestResource*>(cache->find(key1))->setSize(50); | 225 static_cast<TestResource*>(cache.find(key1))->setSize(50); |
237 | 226 |
238 REPORTER_ASSERT(reporter, 250 == cache->getCachedResourceBytes()); | 227 REPORTER_ASSERT(reporter, 250 == cache.getCachedResourceBytes()); |
239 REPORTER_ASSERT(reporter, 2 == cache->getCachedResourceCount()); | 228 REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount()); |
240 } | 229 } |
241 | 230 |
242 // Test increasing a resources size beyond the cache budget. | 231 // Test increasing a resources size beyond the cache budget. |
243 { | 232 { |
244 context->setResourceCacheLimits(2, 300); | 233 GrResourceCache cache(context->getGpu()->caps(), 2, 300); |
245 GrResourceCache* cache = context->getResourceCache(); | |
246 cache->purgeAllUnlocked(); | |
247 SkASSERT(0 == cache->getCachedResourceCount() && 0 == cache->getCachedRe
sourceBytes()); | |
248 | 234 |
249 TestResource* a = new TestResource(context->getGpu(), 100); | 235 TestResource* a = new TestResource(context->getGpu(), 100); |
250 cache->addResource(key1, a); | 236 cache.addResource(key1, a); |
251 a->unref(); | 237 a->unref(); |
252 | 238 |
253 TestResource* b = new TestResource(context->getGpu(), 100); | 239 TestResource* b = new TestResource(context->getGpu(), 100); |
254 cache->addResource(key2, b); | 240 cache.addResource(key2, b); |
255 b->unref(); | 241 b->unref(); |
256 | 242 |
257 REPORTER_ASSERT(reporter, 200 == cache->getCachedResourceBytes()); | 243 REPORTER_ASSERT(reporter, 200 == cache.getCachedResourceBytes()); |
258 REPORTER_ASSERT(reporter, 2 == cache->getCachedResourceCount()); | 244 REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount()); |
259 | 245 |
260 static_cast<TestResource*>(cache->find(key2))->setSize(201); | 246 static_cast<TestResource*>(cache.find(key2))->setSize(201); |
261 REPORTER_ASSERT(reporter, !cache->hasKey(key1)); | 247 REPORTER_ASSERT(reporter, NULL == cache.find(key1)); |
262 | 248 |
263 REPORTER_ASSERT(reporter, 201 == cache->getCachedResourceBytes()); | 249 REPORTER_ASSERT(reporter, 201 == cache.getCachedResourceBytes()); |
264 REPORTER_ASSERT(reporter, 1 == cache->getCachedResourceCount()); | 250 REPORTER_ASSERT(reporter, 1 == cache.getCachedResourceCount()); |
265 } | 251 } |
266 } | 252 } |
267 | 253 |
268 //////////////////////////////////////////////////////////////////////////////// | 254 //////////////////////////////////////////////////////////////////////////////// |
269 DEF_GPUTEST(ResourceCache, reporter, factory) { | 255 DEF_GPUTEST(ResourceCache, reporter, factory) { |
270 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { | 256 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { |
271 GrContextFactory::GLContextType glType = static_cast<GrContextFactory::G
LContextType>(type); | 257 GrContextFactory::GLContextType glType = static_cast<GrContextFactory::G
LContextType>(type); |
272 if (!GrContextFactory::IsRenderingGLContext(glType)) { | 258 if (!GrContextFactory::IsRenderingGLContext(glType)) { |
273 continue; | 259 continue; |
274 } | 260 } |
275 GrContext* context = factory->get(glType); | 261 GrContext* context = factory->get(glType); |
| 262 if (NULL == context) { |
| 263 continue; |
| 264 } |
| 265 |
276 GrSurfaceDesc desc; | 266 GrSurfaceDesc desc; |
277 desc.fConfig = kSkia8888_GrPixelConfig; | 267 desc.fConfig = kSkia8888_GrPixelConfig; |
278 desc.fFlags = kRenderTarget_GrSurfaceFlag; | 268 desc.fFlags = kRenderTarget_GrSurfaceFlag; |
279 desc.fWidth = gWidth; | 269 desc.fWidth = gWidth; |
280 desc.fHeight = gHeight; | 270 desc.fHeight = gHeight; |
281 SkImageInfo info = SkImageInfo::MakeN32Premul(gWidth, gHeight); | 271 SkImageInfo info = SkImageInfo::MakeN32Premul(gWidth, gHeight); |
282 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context, info
)); | 272 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context, info
)); |
| 273 |
283 test_cache(reporter, context, surface->getCanvas()); | 274 test_cache(reporter, context, surface->getCanvas()); |
| 275 test_purge_invalidated(reporter, context); |
| 276 test_cache_delete_on_destruction(reporter, context); |
| 277 test_resource_size_changed(reporter, context); |
284 } | 278 } |
285 | |
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); | |
296 } | 279 } |
297 | 280 |
298 #endif | 281 #endif |
OLD | NEW |