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