1 /* 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 8 #include "Test.h" 9 #include "TestClassDef.h" 10 #include "SkDiscardableMemory.h" 11 #include "SkScaledImageCache.h" 12 13 static void make_bm(SkBitmap* bm, int w, int h) { 14 bm->setConfig(SkBitmap::kARGB_8888_Config, w, h); 15 bm->allocPixels(); 16 } 17 18 static const int COUNT = 10; 19 static const int DIM = 256; 20 21 static void test_cache(skiatest::Reporter* reporter, SkScaledImageCache& cache, 22 bool testPurge) { 23 SkScaledImageCache::ID* id; 24 25 SkBitmap bm[COUNT]; 26 27 const SkScalar scale = 2; 28 for (int i = 0; i < COUNT; ++i) { 29 make_bm(&bm[i], DIM, DIM); 30 } 31 32 for (int i = 0; i < COUNT; ++i) { 33 SkBitmap tmp; 34 35 SkScaledImageCache::ID* id = cache.findAndLock(bm[i], scale, scale, &tmp); 36 REPORTER_ASSERT(reporter, NULL == id); 37 38 make_bm(&tmp, DIM, DIM); 39 id = cache.addAndLock(bm[i], scale, scale, tmp); 40 REPORTER_ASSERT(reporter, NULL != id); 41 42 SkBitmap tmp2; 43 SkScaledImageCache::ID* id2 = cache.findAndLock(bm[i], scale, scale, 44 &tmp2); 45 REPORTER_ASSERT(reporter, id == id2); 46 REPORTER_ASSERT(reporter, tmp.pixelRef() == tmp2.pixelRef()); 47 REPORTER_ASSERT(reporter, tmp.width() == tmp2.width()); 48 REPORTER_ASSERT(reporter, tmp.height() == tmp2.height()); 49 cache.unlock(id2); 50 51 cache.unlock(id); 52 } 53 54 if (testPurge) { 55 // stress test, should trigger purges 56 float incScale = 2; 57 for (size_t i = 0; i < COUNT * 100; ++i) { 58 incScale += 1; 59 60 SkBitmap tmp; 61 make_bm(&tmp, DIM, DIM); 62 63 SkScaledImageCache::ID* id = cache.addAndLock(bm[0], incScale, 64 incScale, tmp); 65 REPORTER_ASSERT(reporter, NULL != id); 66 cache.unlock(id); 67 } 68 } 69 70 // test the originals after all that purging 71 for (int i = 0; i < COUNT; ++i) { 72 SkBitmap tmp; 73 id = cache.findAndLock(bm[i], scale, scale, &tmp); 74 if (id) { 75 cache.unlock(id); 76 } 77 } 78 79 cache.setByteLimit(0); 80 } 81 82 #include "SkDiscardableMemoryPool.h" 83 84 static SkDiscardableMemoryPool* gPool; 85 static SkDiscardableMemory* pool_factory(size_t bytes) { 86 return gPool->create(bytes); 87 } 88 89 DEF_TEST(ImageCache, reporter) { 90 static const size_t defLimit = DIM * DIM * 4 * COUNT + 1024; // 1K slop 91 92 { 93 SkScaledImageCache cache(defLimit); 94 test_cache(reporter, cache, true); 95 } 96 { 97 SkDiscardableMemoryPool pool(defLimit); 98 gPool = &pool; 99 SkScaledImageCache cache(pool_factory); 100 test_cache(reporter, cache, true); 101 } 102 { 103 SkScaledImageCache cache(SkDiscardableMemory::Create); 104 test_cache(reporter, cache, false); 105 } 106 } 107 108 DEF_TEST(ImageCache_doubleAdd, r) { 109 // Adding the same key twice should be safe. 110 SkScaledImageCache cache(1024); 111 112 SkBitmap original; 113 original.setConfig(SkBitmap::kARGB_8888_Config, 40, 40); 114 original.allocPixels(); 115 116 SkBitmap scaled; 117 scaled.setConfig(SkBitmap::kARGB_8888_Config, 20, 20); 118 scaled.allocPixels(); 119 120 SkScaledImageCache::ID* id1 = cache.addAndLock(original, 0.5f, 0.5f, scaled); 121 SkScaledImageCache::ID* id2 = cache.addAndLock(original, 0.5f, 0.5f, scaled); 122 // We don't really care if id1 == id2 as long as unlocking both works. 123 cache.unlock(id1); 124 cache.unlock(id2); 125 } 126