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 #include "SkBitmap.h" | 8 #include "SkBitmap.h" |
9 #include "SkCanvas.h" | 9 #include "SkCanvas.h" |
10 #include "SkData.h" | 10 #include "SkData.h" |
11 #include "SkDecodingImageGenerator.h" | 11 #include "SkDecodingImageGenerator.h" |
12 #include "SkDiscardableMemoryPool.h" | |
13 #include "SkDiscardablePixelRef.h" | |
12 #include "SkForceLinking.h" | 14 #include "SkForceLinking.h" |
13 #include "SkImageDecoder.h" | 15 #include "SkImageDecoder.h" |
14 #include "SkImagePriv.h" | 16 #include "SkImagePriv.h" |
15 #include "SkLazyCachingPixelRef.h" | 17 #include "SkLazyCachingPixelRef.h" |
16 #include "SkLazyPixelRef.h" | |
17 #include "SkScaledImageCache.h" | 18 #include "SkScaledImageCache.h" |
18 #include "SkStream.h" | 19 #include "SkStream.h" |
20 #include "SkUtils.h" | |
19 | 21 |
20 #include "Test.h" | 22 #include "Test.h" |
21 #include "TestClassDef.h" | 23 #include "TestClassDef.h" |
22 | 24 |
23 __SK_FORCE_IMAGE_DECODER_LINKING; | 25 __SK_FORCE_IMAGE_DECODER_LINKING; |
24 | 26 |
25 /** | 27 /** |
26 * Fill this bitmap with some color. | 28 * Fill this bitmap with some color. |
27 */ | 29 */ |
28 static void make_test_image(SkBitmap* bm) { | 30 static void make_test_image(SkBitmap* bm) { |
(...skipping 17 matching lines...) Expand all Loading... | |
46 */ | 48 */ |
47 static SkData* create_data_from_bitmap(const SkBitmap& bm, | 49 static SkData* create_data_from_bitmap(const SkBitmap& bm, |
48 SkImageEncoder::Type type) { | 50 SkImageEncoder::Type type) { |
49 SkDynamicMemoryWStream stream; | 51 SkDynamicMemoryWStream stream; |
50 if (SkImageEncoder::EncodeStream(&stream, bm, type, 100)) { | 52 if (SkImageEncoder::EncodeStream(&stream, bm, type, 100)) { |
51 return stream.copyToData(); | 53 return stream.copyToData(); |
52 } | 54 } |
53 return NULL; | 55 return NULL; |
54 } | 56 } |
55 | 57 |
56 /** | |
57 * A simplified version of SkBitmapFactory | |
58 */ | |
59 static bool simple_bitmap_factory(SkBitmapFactory::DecodeProc proc, | |
60 SkData* data, | |
61 SkBitmap* dst) { | |
62 SkImageInfo info; | |
63 if (!proc(data->data(), data->size(), &info, NULL)) { | |
64 return false; | |
65 } | |
66 dst->setConfig(SkImageInfoToBitmapConfig(info), info.fWidth, | |
67 info.fHeight, 0, info.fAlphaType); | |
68 SkAutoTUnref<SkLazyPixelRef> ref(SkNEW_ARGS(SkLazyPixelRef, | |
69 (data, proc, NULL))); | |
70 dst->setPixelRef(ref); | |
71 return true; | |
72 } | |
73 | |
74 static void compare_bitmaps(skiatest::Reporter* reporter, | 58 static void compare_bitmaps(skiatest::Reporter* reporter, |
75 const SkBitmap& b1, const SkBitmap& b2, | 59 const SkBitmap& b1, const SkBitmap& b2, |
76 bool pixelPerfect = true) { | 60 bool pixelPerfect = true) { |
77 REPORTER_ASSERT(reporter, b1.empty() == b2.empty()); | 61 REPORTER_ASSERT(reporter, b1.empty() == b2.empty()); |
78 REPORTER_ASSERT(reporter, b1.width() == b2.width()); | 62 REPORTER_ASSERT(reporter, b1.width() == b2.width()); |
79 REPORTER_ASSERT(reporter, b1.height() == b2.height()); | 63 REPORTER_ASSERT(reporter, b1.height() == b2.height()); |
80 REPORTER_ASSERT(reporter, b1.isNull() == b2.isNull()); | 64 REPORTER_ASSERT(reporter, b1.isNull() == b2.isNull()); |
81 SkAutoLockPixels autoLockPixels1(b1); | 65 SkAutoLockPixels autoLockPixels1(b1); |
82 SkAutoLockPixels autoLockPixels2(b2); | 66 SkAutoLockPixels autoLockPixels2(b2); |
83 REPORTER_ASSERT(reporter, b1.isNull() == b2.isNull()); | 67 REPORTER_ASSERT(reporter, b1.isNull() == b2.isNull()); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
135 SkAutoDataUnref encoded(create_data_from_bitmap(original, type)); | 119 SkAutoDataUnref encoded(create_data_from_bitmap(original, type)); |
136 REPORTER_ASSERT(reporter, encoded.get() != NULL); | 120 REPORTER_ASSERT(reporter, encoded.get() != NULL); |
137 if (NULL != encoded.get()) { | 121 if (NULL != encoded.get()) { |
138 bool comparePixels = (SkImageEncoder::kPNG_Type == type); | 122 bool comparePixels = (SkImageEncoder::kPNG_Type == type); |
139 comp(reporter, encoded, original, comparePixels); | 123 comp(reporter, encoded, original, comparePixels); |
140 } | 124 } |
141 } | 125 } |
142 } | 126 } |
143 | 127 |
144 /** | 128 /** |
145 * This checks to see that a SkLazyPixelRef works as advertised. | |
146 */ | |
147 static void compare_with_skLazyPixelRef(skiatest::Reporter* reporter, | |
148 SkData* encoded, | |
149 const SkBitmap& original, | |
150 bool comparePixels) { | |
151 SkBitmap lazy; | |
152 static const SkBitmapFactory::DecodeProc decoder = | |
153 &(SkImageDecoder::DecodeMemoryToTarget); | |
154 bool success = simple_bitmap_factory(decoder, encoded, &lazy); | |
155 REPORTER_ASSERT(reporter, success); | |
156 | |
157 REPORTER_ASSERT(reporter, NULL == lazy.getPixels()); | |
158 { | |
159 SkAutoLockPixels autoLockPixels(lazy); // now pixels are good. | |
160 REPORTER_ASSERT(reporter, NULL != lazy.getPixels()); | |
161 } | |
162 // pixels should be gone! | |
163 REPORTER_ASSERT(reporter, NULL == lazy.getPixels()); | |
164 { | |
165 SkAutoLockPixels autoLockPixels(lazy); // now pixels are good. | |
166 REPORTER_ASSERT(reporter, NULL != lazy.getPixels()); | |
167 } | |
168 compare_bitmaps(reporter, original, lazy, comparePixels); | |
169 } | |
170 DEF_TEST(LazyPixelRef, reporter) { | |
171 test_three_encodings(reporter, compare_with_skLazyPixelRef); | |
172 } | |
173 | |
174 | |
175 | |
176 /** | |
177 * This checks to see that a SkLazyCachedPixelRef works as advertised. | 129 * This checks to see that a SkLazyCachedPixelRef works as advertised. |
178 */ | 130 */ |
179 | 131 |
180 static void compare_with_skLazyCachedPixelRef(skiatest::Reporter* reporter, | 132 static void compare_with_skLazyCachedPixelRef(skiatest::Reporter* reporter, |
181 SkData* encoded, | 133 SkData* encoded, |
182 const SkBitmap& original, | 134 const SkBitmap& original, |
183 bool comparePixels) { | 135 bool comparePixels) { |
184 SkBitmap lazy; | 136 SkBitmap lazy; |
185 static const SkBitmapFactory::DecodeProc decoder = | 137 static const SkLazyCachingPixelRef::DecodeProc decoder = |
186 &(SkImageDecoder::DecodeMemoryToTarget); | 138 &(SkImageDecoder::DecodeMemoryToTarget); |
187 bool success = SkLazyCachingPixelRef::Install(decoder, encoded, &lazy); | 139 bool success = SkLazyCachingPixelRef::Install(decoder, encoded, &lazy); |
188 REPORTER_ASSERT(reporter, success); | 140 REPORTER_ASSERT(reporter, success); |
189 | 141 |
190 REPORTER_ASSERT(reporter, NULL == lazy.getPixels()); | 142 REPORTER_ASSERT(reporter, NULL == lazy.getPixels()); |
191 { | 143 { |
192 SkAutoLockPixels autoLockPixels(lazy); // now pixels are good. | 144 SkAutoLockPixels autoLockPixels(lazy); // now pixels are good. |
193 REPORTER_ASSERT(reporter, NULL != lazy.getPixels()); | 145 REPORTER_ASSERT(reporter, NULL != lazy.getPixels()); |
194 } | 146 } |
195 // pixels should be gone! | 147 // pixels should be gone! |
196 REPORTER_ASSERT(reporter, NULL == lazy.getPixels()); | 148 REPORTER_ASSERT(reporter, NULL == lazy.getPixels()); |
197 { | 149 { |
198 SkAutoLockPixels autoLockPixels(lazy); // now pixels are good. | 150 SkAutoLockPixels autoLockPixels(lazy); // now pixels are good. |
199 REPORTER_ASSERT(reporter, NULL != lazy.getPixels()); | 151 REPORTER_ASSERT(reporter, NULL != lazy.getPixels()); |
200 } | 152 } |
201 compare_bitmaps(reporter, original, lazy, comparePixels); | 153 compare_bitmaps(reporter, original, lazy, comparePixels); |
202 } | 154 } |
203 DEF_TEST(LazyCachedPixelRef, reporter) { | 155 DEF_TEST(LazyCachedPixelRef, reporter) { |
204 test_three_encodings(reporter, compare_with_skLazyCachedPixelRef); | 156 test_three_encodings(reporter, compare_with_skLazyCachedPixelRef); |
205 } | 157 } |
206 | 158 |
207 class TestPixelRef : public SkCachingPixelRef { | 159 class TestPixelRef : public SkCachingPixelRef { |
208 public: | 160 public: |
209 TestPixelRef(int x) : fX(x) { } | 161 explicit TestPixelRef(int x) : fX(x) { } |
210 virtual ~TestPixelRef() { } | 162 virtual ~TestPixelRef() { } |
211 static bool Install(SkBitmap* destination, int x) { | 163 static bool Install(SkBitmap* destination, int x) { |
212 SkAutoTUnref<TestPixelRef> ref(SkNEW_ARGS(TestPixelRef, (x))); | 164 SkAutoTUnref<TestPixelRef> ref(SkNEW_ARGS(TestPixelRef, (x))); |
213 return ref->configure(destination) && destination->setPixelRef(ref); | 165 return ref->configure(destination) && destination->setPixelRef(ref); |
214 } | 166 } |
215 SK_DECLARE_UNFLATTENABLE_OBJECT() | 167 SK_DECLARE_UNFLATTENABLE_OBJECT() |
168 | |
216 protected: | 169 protected: |
217 virtual bool onDecodeInfo(SkImageInfo* info) SK_OVERRIDE { | 170 virtual bool onDecodeInfo(SkImageInfo* info) SK_OVERRIDE { |
218 if (fX == 0) { | 171 if (fX == 0) { |
219 return false; | 172 return false; |
220 } | 173 } |
221 SkASSERT(info); | 174 SkASSERT(info); |
222 info->fWidth = 10; | 175 info->fWidth = 10; |
223 info->fHeight = 10; | 176 info->fHeight = 10; |
224 info->fColorType = kRGBA_8888_SkColorType; | 177 info->fColorType = kPMColor_SkColorType; |
225 info->fAlphaType = kOpaque_SkAlphaType; | 178 info->fAlphaType = kOpaque_SkAlphaType; |
226 return true; | 179 return true; |
227 } | 180 } |
228 virtual bool onDecodePixels(const SkImageInfo& info, | 181 virtual bool onDecodePixels(const SkImageInfo& info, |
229 void* pixels, | 182 void* pixels, |
230 size_t rowBytes) SK_OVERRIDE { | 183 size_t rowBytes) SK_OVERRIDE { |
231 return false; | 184 return false; |
232 } | 185 } |
186 | |
233 private: | 187 private: |
234 int fX; // controls where the failure happens | 188 int fX; // controls where the failure happens |
235 typedef SkCachingPixelRef INHERITED; | 189 typedef SkCachingPixelRef INHERITED; |
236 }; | 190 }; |
237 | 191 |
238 DEF_TEST(CachingPixelRef, reporter) { | 192 DEF_TEST(CachingPixelRef, reporter) { |
239 SkBitmap lazy; | 193 SkBitmap lazy; |
240 // test the error handling | 194 // test the error handling |
241 REPORTER_ASSERT(reporter, !TestPixelRef::Install(&lazy, 0)); | 195 REPORTER_ASSERT(reporter, !TestPixelRef::Install(&lazy, 0)); |
242 // onDecodeInfo should succeed, allowing installation | 196 // onDecodeInfo should succeed, allowing installation |
243 REPORTER_ASSERT(reporter, TestPixelRef::Install(&lazy, 1)); | 197 REPORTER_ASSERT(reporter, TestPixelRef::Install(&lazy, 1)); |
244 SkAutoLockPixels autoLockPixels(lazy); // now pixels are good. | 198 SkAutoLockPixels autoLockPixels(lazy); // now pixels are good. |
245 // onDecodePixels should fail, so getting pixels will fail. | 199 // onDecodePixels should fail, so getting pixels will fail. |
246 REPORTER_ASSERT(reporter, NULL == lazy.getPixels()); | 200 REPORTER_ASSERT(reporter, NULL == lazy.getPixels()); |
247 } | 201 } |
248 | 202 |
249 static void compare_with_SkDecodingImageGenerator(skiatest::Reporter* reporter, | 203 static void compare_with_SkDecodingImageGenerator(skiatest::Reporter* reporter, |
250 SkData* encoded, | 204 SkData* encoded, |
251 const SkBitmap& original, | 205 const SkBitmap& original, |
252 bool comparePixels) { | 206 bool comparePixels) { |
207 SkAutoTUnref<SkDiscardableMemoryPool> dMFactory( | |
208 SkNEW_ARGS(SkDiscardableMemoryPool, (1))); | |
209 // Set the pool's budget abnormally low to force re-decoding | |
253 | 210 |
254 SkBitmap lazy; | 211 SkBitmap lazy; |
255 bool success = SkDecodingImageGenerator::Install(encoded, &lazy); | 212 bool success = SkDecodingImageGenerator::Install(encoded, &lazy, dMFactory); |
256 REPORTER_ASSERT(reporter, success); | 213 REPORTER_ASSERT(reporter, success); |
257 if (!success) { | 214 if (!success) { |
258 return; | 215 return; |
259 } | 216 } |
260 | 217 |
261 REPORTER_ASSERT(reporter, NULL == lazy.getPixels()); | 218 REPORTER_ASSERT(reporter, NULL == lazy.getPixels()); |
262 { | 219 { |
263 SkAutoLockPixels autoLockPixels(lazy); // now pixels are good. | 220 SkAutoLockPixels autoLockPixels(lazy); // now pixels are good. |
264 REPORTER_ASSERT(reporter, NULL != lazy.getPixels()); | 221 REPORTER_ASSERT(reporter, NULL != lazy.getPixels()); |
265 if (NULL == lazy.getPixels()) { | 222 if (NULL == lazy.getPixels()) { |
266 return; | 223 return; |
267 } | 224 } |
268 } | 225 } |
269 // pixels should be gone! | 226 // pixels should be gone! |
270 REPORTER_ASSERT(reporter, NULL == lazy.getPixels()); | 227 REPORTER_ASSERT(reporter, NULL == lazy.getPixels()); |
271 { | 228 { |
272 SkAutoLockPixels autoLockPixels(lazy); // now pixels are good. | 229 SkAutoLockPixels autoLockPixels(lazy); // now pixels are good. |
273 REPORTER_ASSERT(reporter, NULL != lazy.getPixels()); | 230 REPORTER_ASSERT(reporter, NULL != lazy.getPixels()); |
274 } | 231 } |
275 compare_bitmaps(reporter, original, lazy, comparePixels); | 232 compare_bitmaps(reporter, original, lazy, comparePixels); |
276 } | 233 } |
277 DEF_TEST(DecodingImageGenerator, reporter) { | 234 DEF_TEST(DecodingImageGenerator, reporter) { |
278 test_three_encodings(reporter, compare_with_SkDecodingImageGenerator); | 235 test_three_encodings(reporter, compare_with_SkDecodingImageGenerator); |
279 } | 236 } |
237 | |
238 //////////////////////////////////////////////////////////////////////////////// | |
239 namespace { | |
240 /** | |
241 * if x == 0, will fail at getPixels() | |
scroggo
2013/12/04 19:09:25
This seems like a good candidate for an enum.
Als
hal.canary
2013/12/04 19:39:40
Done.
| |
242 * if x <= 1, will fail at getInfo() | |
243 * if x >= 2, will fill the given pixels with SK_ColorCYAN. | |
244 */ | |
245 class TestImageGenerator : public SkImageGenerator { | |
246 public: | |
247 static int Width() { return 10; } | |
248 static int Height() { return 10; } | |
249 static SkColor Color() { return SK_ColorCYAN; } | |
250 TestImageGenerator(int x, skiatest::Reporter* reporter) | |
251 : fX(x), fReporter(reporter) { } | |
252 ~TestImageGenerator() { } | |
253 bool getInfo(SkImageInfo* info) SK_OVERRIDE { | |
254 REPORTER_ASSERT(fReporter, NULL != info); | |
255 if ((info == NULL) || (fX == 0)) { | |
256 return false; | |
257 } | |
258 info->fWidth = TestImageGenerator::Width(); | |
259 info->fHeight = TestImageGenerator::Height(); | |
260 info->fColorType = kPMColor_SkColorType; | |
261 info->fAlphaType = kOpaque_SkAlphaType; | |
262 return true; | |
263 } | |
264 bool getPixels(const SkImageInfo& info, | |
265 void* pixels, | |
266 size_t rowBytes) SK_OVERRIDE { | |
267 REPORTER_ASSERT(fReporter, pixels != NULL); | |
268 REPORTER_ASSERT(fReporter, | |
269 rowBytes >= (info.fWidth * info.bytesPerPixel())); | |
270 if ((pixels == NULL) | |
scroggo
2013/12/04 19:09:25
For your == checks (here and above), NULL or 0 sho
hal.canary
2013/12/04 19:39:40
Done.
| |
271 || (fX < 2) | |
272 || (info.fColorType != kPMColor_SkColorType)) { | |
273 return false; | |
274 } | |
275 char* bytePtr = static_cast<char*>(pixels); | |
276 for (int y = 0; y < info.fHeight; ++y) { | |
277 sk_memset32(reinterpret_cast<SkPMColor*>(bytePtr), | |
278 TestImageGenerator::Color(), info.fWidth); | |
279 bytePtr += rowBytes; | |
280 } | |
281 return true; | |
282 } | |
283 private: | |
284 int fX; | |
285 skiatest::Reporter* fReporter; | |
286 }; | |
287 void CheckTestImageGeneratorBitmap(skiatest::Reporter* reporter, | |
288 const SkBitmap& bm) { | |
289 REPORTER_ASSERT(reporter, TestImageGenerator::Width() == bm.width()); | |
290 REPORTER_ASSERT(reporter, TestImageGenerator::Height() == bm.height()); | |
291 SkAutoLockPixels autoLockPixels(bm); | |
292 REPORTER_ASSERT(reporter, NULL != bm.getPixels()); | |
293 if (NULL == bm.getPixels()) { | |
294 return; | |
295 } | |
296 int errors = 0; | |
297 for (int y = 0; y < bm.height(); ++y) { | |
298 for (int x = 0; x < bm.width(); ++x) { | |
299 if (TestImageGenerator::Color() != bm.getColor(x, y)) { | |
300 ++errors; | |
301 } | |
302 } | |
303 } | |
304 REPORTER_ASSERT(reporter, 0 == errors); | |
305 } | |
306 void CheckDiscardablePixelRef(int x, skiatest::Reporter* reporter, | |
307 SkDiscardableMemory::Factory* factory) { | |
308 SkAutoTDelete<SkImageGenerator> gen(SkNEW_ARGS(TestImageGenerator, | |
309 (x, reporter))); | |
310 REPORTER_ASSERT(reporter, gen.get() != NULL); | |
311 SkBitmap lazy; | |
312 bool success = SkDiscardablePixelRef::Install(gen.detach(), | |
313 &lazy, factory); | |
314 REPORTER_ASSERT(reporter, success == (0 != x)); // since x==2 | |
scroggo
2013/12/04 19:09:25
Does this comment go with the next line? I think t
hal.canary
2013/12/04 19:39:40
Done.
| |
315 if (x > 1) { | |
316 CheckTestImageGeneratorBitmap(reporter, lazy); | |
317 } | |
318 } | |
319 } // namespace | |
320 /** | |
321 * This tests the basic functionality of SkDiscardablePixelRef with a | |
322 * basic SkImageGenerator implementation and several | |
323 * SkDiscardableMemory::Factory choices. | |
324 */ | |
325 DEF_TEST(DiscardablePixelRef, reporter) { | |
326 CheckDiscardablePixelRef(0, reporter, NULL); | |
327 CheckDiscardablePixelRef(1, reporter, NULL); | |
328 CheckDiscardablePixelRef(2, reporter, NULL); | |
329 | |
330 SkAutoTUnref<SkDiscardableMemoryPool> pool( | |
331 SkNEW_ARGS(SkDiscardableMemoryPool, (1, NULL))); | |
332 REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed()); | |
333 CheckDiscardablePixelRef(1, reporter, pool); | |
334 REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed()); | |
335 CheckDiscardablePixelRef(2, reporter, pool); | |
336 REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed()); | |
337 | |
338 SkDiscardableMemoryPool* globalPool = SkGetGlobalDiscardableMemoryPool(); | |
339 CheckDiscardablePixelRef(1, reporter, globalPool); | |
340 CheckDiscardablePixelRef(2, reporter, globalPool); | |
341 | |
342 // TODO(halcanary): When ashmem-backed SkDiscardableMemory lands, | |
343 // test that here (on platforms where it is availible). | |
344 } | |
345 //////////////////////////////////////////////////////////////////////////////// | |
346 | |
OLD | NEW |