OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2012 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 #ifdef SK_DEBUG | |
9 | |
10 #include "SkBitmap.h" | |
11 #include "SkBitmapFactory.h" | |
12 #include "SkCanvas.h" | |
13 #include "SkColor.h" | |
14 #include "SkData.h" | |
15 #include "SkImageDecoder.h" | |
16 #include "SkImageEncoder.h" | |
17 #include "SkLazyPixelRef.h" | |
18 #include "SkLruImageCache.h" | |
19 #include "SkPaint.h" | |
20 #include "SkPurgeableImageCache.h" | |
21 #include "SkStream.h" | |
22 #include "SkTemplates.h" | |
23 #include "Test.h" | |
24 | |
25 static SkBitmap* create_bitmap() { | |
26 SkBitmap* bm = SkNEW(SkBitmap); | |
27 // Use a large bitmap. | |
28 const int W = 1000, H = 1000; | |
29 bm->setConfig(SkBitmap::kARGB_8888_Config, W, H); | |
30 bm->allocPixels(); | |
31 bm->eraseColor(SK_ColorBLACK); | |
32 SkCanvas canvas(*bm); | |
33 SkPaint paint; | |
34 paint.setColor(SK_ColorBLUE); | |
35 canvas.drawRectCoords(0, 0, SkIntToScalar(W/2), SkIntToScalar(H/2), paint); | |
36 return bm; | |
37 } | |
38 | |
39 static SkData* create_data_from_bitmap(const SkBitmap& bm) { | |
40 SkDynamicMemoryWStream stream; | |
41 if (SkImageEncoder::EncodeStream(&stream, bm, SkImageEncoder::kPNG_Type, 100
)) { | |
42 return stream.copyToData(); | |
43 } | |
44 return NULL; | |
45 } | |
46 | |
47 static void assert_bounds_equal(skiatest::Reporter* reporter, const SkBitmap& bm
1, | |
48 const SkBitmap& bm2) { | |
49 REPORTER_ASSERT(reporter, bm1.width() == bm2.width()); | |
50 REPORTER_ASSERT(reporter, bm1.height() == bm2.height()); | |
51 } | |
52 | |
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 // The memory block may or may not have survived the purging (at
the | |
83 // memory manager's whim) so we cannot check dataStatus here. | |
84 cache->releaseCache(ID); | |
85 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID) | |
86 != SkImageCache::kPinned_MemoryStatus)
; | |
87 cache->throwAwayCache(ID); | |
88 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID) | |
89 == SkImageCache::kFreed_MemoryStatus); | |
90 } else { | |
91 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID) | |
92 == SkImageCache::kFreed_MemoryStatus); | |
93 } | |
94 } | |
95 } | |
96 } | |
97 | |
98 static void test_factory(skiatest::Reporter* reporter, SkImageCache* cache, SkDa
ta* encodedData, | |
99 const SkBitmap& origBitmap) { | |
100 SkBitmapFactory factory(&SkImageDecoder::DecodeMemoryToTarget); | |
101 factory.setImageCache(cache); | |
102 SkAutoTDelete<SkBitmap> bitmapFromFactory(SkNEW(SkBitmap)); | |
103 bool success = factory.installPixelRef(encodedData, bitmapFromFactory.get())
; | |
104 // This assumes that if the encoder worked, the decoder should also work, so
the above call | |
105 // should not fail. | |
106 REPORTER_ASSERT(reporter, success); | |
107 assert_bounds_equal(reporter, origBitmap, *bitmapFromFactory.get()); | |
108 | |
109 SkPixelRef* pixelRef = bitmapFromFactory->pixelRef(); | |
110 REPORTER_ASSERT(reporter, pixelRef != NULL); | |
111 if (NULL == cache) { | |
112 // This assumes that installPixelRef called lockPixels. | |
113 REPORTER_ASSERT(reporter, bitmapFromFactory->readyToDraw()); | |
114 } else { | |
115 // Lazy decoding | |
116 REPORTER_ASSERT(reporter, !bitmapFromFactory->readyToDraw()); | |
117 SkLazyPixelRef* lazyRef = static_cast<SkLazyPixelRef*>(pixelRef); | |
118 intptr_t cacheID = lazyRef->getCacheId(); | |
119 REPORTER_ASSERT(reporter, cache->getMemoryStatus(cacheID) | |
120 != SkImageCache::kPinned_MemoryStatus); | |
121 { | |
122 SkAutoLockPixels alp(*bitmapFromFactory.get()); | |
123 REPORTER_ASSERT(reporter, bitmapFromFactory->readyToDraw()); | |
124 cacheID = lazyRef->getCacheId(); | |
125 REPORTER_ASSERT(reporter, cache->getMemoryStatus(cacheID) | |
126 == SkImageCache::kPinned_MemoryStatus); | |
127 } | |
128 REPORTER_ASSERT(reporter, !bitmapFromFactory->readyToDraw()); | |
129 REPORTER_ASSERT(reporter, cache->getMemoryStatus(cacheID) | |
130 != SkImageCache::kPinned_MemoryStatus); | |
131 bitmapFromFactory.free(); | |
132 REPORTER_ASSERT(reporter, cache->getMemoryStatus(cacheID) | |
133 == SkImageCache::kFreed_MemoryStatus); | |
134 } | |
135 } | |
136 | |
137 class ImageCacheHolder : public SkNoncopyable { | |
138 | |
139 public: | |
140 ~ImageCacheHolder() { | |
141 fCaches.safeUnrefAll(); | |
142 } | |
143 | |
144 void addImageCache(SkImageCache* cache) { | |
145 SkSafeRef(cache); | |
146 *fCaches.append() = cache; | |
147 } | |
148 | |
149 int count() const { return fCaches.count(); } | |
150 | |
151 SkImageCache* getAt(int i) { | |
152 if (i < 0 || i > fCaches.count()) { | |
153 return NULL; | |
154 } | |
155 return fCaches.getAt(i); | |
156 } | |
157 | |
158 private: | |
159 SkTDArray<SkImageCache*> fCaches; | |
160 }; | |
161 | |
162 static void TestBitmapFactory(skiatest::Reporter* reporter) { | |
163 SkAutoTDelete<SkBitmap> bitmap(create_bitmap()); | |
164 SkASSERT(bitmap.get() != NULL); | |
165 | |
166 SkAutoDataUnref encodedBitmap(create_data_from_bitmap(*bitmap.get())); | |
167 bool encodeSucceeded = encodedBitmap.get() != NULL; | |
168 SkASSERT(encodeSucceeded); | |
169 | |
170 ImageCacheHolder cacheHolder; | |
171 | |
172 SkAutoTUnref<SkLruImageCache> lruCache(SkNEW_ARGS(SkLruImageCache, (1024 * 1
024))); | |
173 cacheHolder.addImageCache(lruCache); | |
174 | |
175 cacheHolder.addImageCache(NULL); | |
176 | |
177 SkImageCache* purgeableCache = SkPurgeableImageCache::Create(); | |
178 if (purgeableCache != NULL) { | |
179 cacheHolder.addImageCache(purgeableCache); | |
180 purgeableCache->unref(); | |
181 } | |
182 | |
183 for (int i = 0; i < cacheHolder.count(); i++) { | |
184 SkImageCache* cache = cacheHolder.getAt(i); | |
185 if (cache != NULL) { | |
186 test_cache(reporter, cache); | |
187 } | |
188 if (encodeSucceeded) { | |
189 test_factory(reporter, cache, encodedBitmap, *bitmap.get()); | |
190 } | |
191 } | |
192 } | |
193 | |
194 #include "TestClassDef.h" | |
195 DEFINE_TESTCLASS("BitmapFactory", TestBitmapFactoryClass, TestBitmapFactory) | |
196 | |
197 #endif // SK_DEBUG | |
OLD | NEW |