OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 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 #ifdef SK_DEBUG | 8 #ifdef SK_DEBUG |
9 | 9 |
10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
11 #include "SkBitmapFactory.h" | 11 #include "SkBitmapFactory.h" |
12 #include "SkCanvas.h" | 12 #include "SkCanvas.h" |
13 #include "SkColor.h" | 13 #include "SkColor.h" |
14 #include "SkData.h" | 14 #include "SkData.h" |
15 #include "SkImageDecoder.h" | 15 #include "SkImageDecoder.h" |
16 #include "SkImageEncoder.h" | 16 #include "SkImageEncoder.h" |
17 #include "SkLazyPixelRef.h" | 17 #include "SkLazyPixelRef.h" |
18 #include "SkLruImageCache.h" | 18 #include "SkLruImageCache.h" |
19 #include "SkPaint.h" | 19 #include "SkPaint.h" |
| 20 #include "SkPurgeableImageCache.h" |
20 #include "SkStream.h" | 21 #include "SkStream.h" |
21 #include "SkTemplates.h" | 22 #include "SkTemplates.h" |
22 #include "Test.h" | 23 #include "Test.h" |
23 | 24 |
24 #ifdef SK_BUILD_FOR_ANDROID | |
25 #include "SkAshmemImageCache.h" | |
26 #endif | |
27 | |
28 static SkBitmap* create_bitmap() { | 25 static SkBitmap* create_bitmap() { |
29 SkBitmap* bm = SkNEW(SkBitmap); | 26 SkBitmap* bm = SkNEW(SkBitmap); |
30 const int W = 100, H = 100; | 27 // Use a large bitmap. |
| 28 const int W = 1000, H = 1000; |
31 bm->setConfig(SkBitmap::kARGB_8888_Config, W, H); | 29 bm->setConfig(SkBitmap::kARGB_8888_Config, W, H); |
32 bm->allocPixels(); | 30 bm->allocPixels(); |
33 bm->eraseColor(SK_ColorBLACK); | 31 bm->eraseColor(SK_ColorBLACK); |
34 SkCanvas canvas(*bm); | 32 SkCanvas canvas(*bm); |
35 SkPaint paint; | 33 SkPaint paint; |
36 paint.setColor(SK_ColorBLUE); | 34 paint.setColor(SK_ColorBLUE); |
37 canvas.drawRectCoords(0, 0, SkIntToScalar(W/2), SkIntToScalar(H/2), paint); | 35 canvas.drawRectCoords(0, 0, SkIntToScalar(W/2), SkIntToScalar(H/2), paint); |
38 return bm; | 36 return bm; |
39 } | 37 } |
40 | 38 |
41 static SkData* create_data_from_bitmap(const SkBitmap& bm) { | 39 static SkData* create_data_from_bitmap(const SkBitmap& bm) { |
42 SkDynamicMemoryWStream stream; | 40 SkDynamicMemoryWStream stream; |
43 if (SkImageEncoder::EncodeStream(&stream, bm, SkImageEncoder::kPNG_Type, 100
)) { | 41 if (SkImageEncoder::EncodeStream(&stream, bm, SkImageEncoder::kPNG_Type, 100
)) { |
44 return stream.copyToData(); | 42 return stream.copyToData(); |
45 } | 43 } |
46 return NULL; | 44 return NULL; |
47 } | 45 } |
48 | 46 |
49 static void assert_bounds_equal(skiatest::Reporter* reporter, const SkBitmap& bm
1, | 47 static void assert_bounds_equal(skiatest::Reporter* reporter, const SkBitmap& bm
1, |
50 const SkBitmap& bm2) { | 48 const SkBitmap& bm2) { |
51 REPORTER_ASSERT(reporter, bm1.width() == bm2.width()); | 49 REPORTER_ASSERT(reporter, bm1.width() == bm2.width()); |
52 REPORTER_ASSERT(reporter, bm1.height() == bm2.height()); | 50 REPORTER_ASSERT(reporter, bm1.height() == bm2.height()); |
53 } | 51 } |
54 | 52 |
55 static void test_cache(skiatest::Reporter* reporter, SkImageCache* cache, SkData
* encodedData, | 53 static void test_cache(skiatest::Reporter* reporter, SkImageCache* cache) { |
| 54 // Test the cache directly: |
| 55 cache->purgeAllUnpinnedCaches(); |
| 56 intptr_t ID = SkImageCache::UNINITIALIZED_ID; |
| 57 const size_t size = 1000; |
| 58 char buffer[size]; |
| 59 sk_bzero((void*) buffer, size); |
| 60 void* memory = cache->allocAndPinCache(size, &ID); |
| 61 if (memory != NULL) { |
| 62 memcpy(memory, (void*)buffer, size); |
| 63 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID) == SkImageCache::kP
inned_MemoryStatus); |
| 64 cache->releaseCache(ID); |
| 65 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID) != SkImageCache::kP
inned_MemoryStatus); |
| 66 SkImageCache::DataStatus dataStatus; |
| 67 memory = cache->pinCache(ID, &dataStatus); |
| 68 if (memory != NULL) { |
| 69 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID) |
| 70 == SkImageCache::kPinned_MemoryStatus); |
| 71 if (SkImageCache::kRetained_DataStatus == dataStatus) { |
| 72 REPORTER_ASSERT(reporter, !memcmp(memory, (void*) buffer, size))
; |
| 73 } |
| 74 cache->releaseCache(ID); |
| 75 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID) |
| 76 != SkImageCache::kPinned_MemoryStatus); |
| 77 cache->purgeAllUnpinnedCaches(); |
| 78 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID) |
| 79 != SkImageCache::kPinned_MemoryStatus); |
| 80 memory = cache->pinCache(ID, &dataStatus); |
| 81 if (memory != NULL) { |
| 82 // Since the cache was thrown away, and ID was not pinned, it sh
ould have |
| 83 // been purged. |
| 84 REPORTER_ASSERT(reporter, SkImageCache::kUninitialized_DataStatu
s == dataStatus); |
| 85 cache->releaseCache(ID); |
| 86 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID) |
| 87 != SkImageCache::kPinned_MemoryStatus)
; |
| 88 cache->throwAwayCache(ID); |
| 89 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID) |
| 90 == SkImageCache::kFreed_MemoryStatus); |
| 91 } else { |
| 92 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID) |
| 93 == SkImageCache::kFreed_MemoryStatus); |
| 94 } |
| 95 } |
| 96 } |
| 97 } |
| 98 |
| 99 static void test_factory(skiatest::Reporter* reporter, SkImageCache* cache, SkDa
ta* encodedData, |
56 const SkBitmap& origBitmap) { | 100 const SkBitmap& origBitmap) { |
57 SkBitmapFactory factory(&SkImageDecoder::DecodeMemoryToTarget); | 101 SkBitmapFactory factory(&SkImageDecoder::DecodeMemoryToTarget); |
58 factory.setImageCache(cache); | 102 factory.setImageCache(cache); |
59 SkAutoTDelete<SkBitmap> bitmapFromFactory(SkNEW(SkBitmap)); | 103 SkAutoTDelete<SkBitmap> bitmapFromFactory(SkNEW(SkBitmap)); |
60 bool success = factory.installPixelRef(encodedData, bitmapFromFactory.get())
; | 104 bool success = factory.installPixelRef(encodedData, bitmapFromFactory.get())
; |
61 // This assumes that if the encoder worked, the decoder should also work, so
the above call | 105 // This assumes that if the encoder worked, the decoder should also work, so
the above call |
62 // should not fail. | 106 // should not fail. |
63 REPORTER_ASSERT(reporter, success); | 107 REPORTER_ASSERT(reporter, success); |
64 assert_bounds_equal(reporter, origBitmap, *bitmapFromFactory.get()); | 108 assert_bounds_equal(reporter, origBitmap, *bitmapFromFactory.get()); |
65 | 109 |
66 SkPixelRef* pixelRef = bitmapFromFactory->pixelRef(); | 110 SkPixelRef* pixelRef = bitmapFromFactory->pixelRef(); |
67 REPORTER_ASSERT(reporter, pixelRef != NULL); | 111 REPORTER_ASSERT(reporter, pixelRef != NULL); |
68 if (NULL == cache) { | 112 if (NULL == cache) { |
69 // This assumes that installPixelRef called lockPixels. | 113 // This assumes that installPixelRef called lockPixels. |
70 REPORTER_ASSERT(reporter, bitmapFromFactory->readyToDraw()); | 114 REPORTER_ASSERT(reporter, bitmapFromFactory->readyToDraw()); |
71 } else { | 115 } else { |
72 // Lazy decoding | 116 // Lazy decoding |
73 REPORTER_ASSERT(reporter, !bitmapFromFactory->readyToDraw()); | 117 REPORTER_ASSERT(reporter, !bitmapFromFactory->readyToDraw()); |
74 SkLazyPixelRef* lazyRef = static_cast<SkLazyPixelRef*>(pixelRef); | 118 SkLazyPixelRef* lazyRef = static_cast<SkLazyPixelRef*>(pixelRef); |
75 int32_t cacheID = lazyRef->getCacheId(); | 119 intptr_t cacheID = lazyRef->getCacheId(); |
76 REPORTER_ASSERT(reporter, cache->getCacheStatus(cacheID) | 120 REPORTER_ASSERT(reporter, cache->getMemoryStatus(cacheID) |
77 != SkImageCache::kPinned_CacheStatus); | 121 != SkImageCache::kPinned_MemoryStatus); |
78 { | 122 { |
79 SkAutoLockPixels alp(*bitmapFromFactory.get()); | 123 SkAutoLockPixels alp(*bitmapFromFactory.get()); |
80 REPORTER_ASSERT(reporter, bitmapFromFactory->readyToDraw()); | 124 REPORTER_ASSERT(reporter, bitmapFromFactory->readyToDraw()); |
81 cacheID = lazyRef->getCacheId(); | 125 cacheID = lazyRef->getCacheId(); |
82 REPORTER_ASSERT(reporter, cache->getCacheStatus(cacheID) | 126 REPORTER_ASSERT(reporter, cache->getMemoryStatus(cacheID) |
83 == SkImageCache::kPinned_CacheStatus); | 127 == SkImageCache::kPinned_MemoryStatus); |
84 } | 128 } |
85 REPORTER_ASSERT(reporter, !bitmapFromFactory->readyToDraw()); | 129 REPORTER_ASSERT(reporter, !bitmapFromFactory->readyToDraw()); |
86 REPORTER_ASSERT(reporter, cache->getCacheStatus(cacheID) | 130 REPORTER_ASSERT(reporter, cache->getMemoryStatus(cacheID) |
87 != SkImageCache::kPinned_CacheStatus); | 131 != SkImageCache::kPinned_MemoryStatus); |
88 bitmapFromFactory.free(); | 132 bitmapFromFactory.free(); |
89 REPORTER_ASSERT(reporter, cache->getCacheStatus(cacheID) | 133 REPORTER_ASSERT(reporter, cache->getMemoryStatus(cacheID) |
90 == SkImageCache::kThrownAway_CacheStatus); | 134 == SkImageCache::kFreed_MemoryStatus); |
91 } | 135 } |
92 } | 136 } |
93 | 137 |
| 138 class ImageCacheHolder : public SkNoncopyable { |
| 139 |
| 140 public: |
| 141 ~ImageCacheHolder() { |
| 142 fCaches.safeUnrefAll(); |
| 143 } |
| 144 |
| 145 void addImageCache(SkImageCache* cache) { |
| 146 SkSafeRef(cache); |
| 147 *fCaches.append() = cache; |
| 148 } |
| 149 |
| 150 int count() const { return fCaches.count(); } |
| 151 |
| 152 SkImageCache* getAt(int i) { |
| 153 if (i < 0 || i > fCaches.count()) { |
| 154 return NULL; |
| 155 } |
| 156 return fCaches.getAt(i); |
| 157 } |
| 158 |
| 159 private: |
| 160 SkTDArray<SkImageCache*> fCaches; |
| 161 }; |
| 162 |
94 static void TestBitmapFactory(skiatest::Reporter* reporter) { | 163 static void TestBitmapFactory(skiatest::Reporter* reporter) { |
95 SkAutoTDelete<SkBitmap> bitmap(create_bitmap()); | 164 SkAutoTDelete<SkBitmap> bitmap(create_bitmap()); |
96 SkASSERT(bitmap.get() != NULL); | 165 SkASSERT(bitmap.get() != NULL); |
97 | 166 |
98 SkAutoDataUnref encodedBitmap(create_data_from_bitmap(*bitmap.get())); | 167 SkAutoDataUnref encodedBitmap(create_data_from_bitmap(*bitmap.get())); |
99 if (encodedBitmap.get() == NULL) { | 168 bool encodeSucceeded = encodedBitmap.get() != NULL; |
100 // Encoding failed. | 169 SkASSERT(encodeSucceeded); |
101 return; | 170 |
| 171 ImageCacheHolder cacheHolder; |
| 172 |
| 173 SkAutoTUnref<SkLruImageCache> lruCache(SkNEW_ARGS(SkLruImageCache, (1024 * 1
024))); |
| 174 cacheHolder.addImageCache(lruCache); |
| 175 |
| 176 cacheHolder.addImageCache(NULL); |
| 177 |
| 178 SkImageCache* purgeableCache = SkPurgeableImageCache::GetPurgeableImageCache
(); |
| 179 if (purgeableCache != NULL) { |
| 180 cacheHolder.addImageCache(purgeableCache); |
| 181 purgeableCache->unref(); |
102 } | 182 } |
103 | 183 |
104 SkAutoTUnref<SkLruImageCache> lruCache(SkNEW_ARGS(SkLruImageCache, (1024 * 1
024))); | 184 for (int i = 0; i < cacheHolder.count(); i++) { |
105 test_cache(reporter, lruCache, encodedBitmap, *bitmap.get()); | 185 SkImageCache* cache = cacheHolder.getAt(i); |
106 test_cache(reporter, NULL, encodedBitmap, *bitmap.get()); | 186 if (cache != NULL) { |
107 #ifdef SK_BUILD_FOR_ANDROID | 187 test_cache(reporter, cache); |
108 test_cache(reporter, SkAshmemImageCache::GetAshmemImageCache(), encodedBitma
p, *bitmap.get()); | 188 } |
109 #endif | 189 if (encodeSucceeded) { |
| 190 test_factory(reporter, cache, encodedBitmap, *bitmap.get()); |
| 191 } |
| 192 } |
110 } | 193 } |
111 | 194 |
112 #include "TestClassDef.h" | 195 #include "TestClassDef.h" |
113 DEFINE_TESTCLASS("BitmapFactory", TestBitmapFactoryClass, TestBitmapFactory) | 196 DEFINE_TESTCLASS("BitmapFactory", TestBitmapFactoryClass, TestBitmapFactory) |
114 | 197 |
115 #endif // SK_DEBUG | 198 #endif // SK_DEBUG |
OLD | NEW |