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