| 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 "SkDiscardablePixelRef.h" |
| 13 #include "SkDiscardableMemoryPool.h" |
| 12 #include "SkImageDecoder.h" | 14 #include "SkImageDecoder.h" |
| 13 #include "SkImagePriv.h" | |
| 14 #include "SkLazyPixelRef.h" | |
| 15 #include "SkCachingPixelRef.h" | 15 #include "SkCachingPixelRef.h" |
| 16 #include "SkScaledImageCache.h" | 16 #include "SkScaledImageCache.h" |
| 17 #include "SkStream.h" | 17 #include "SkStream.h" |
| 18 #include "SkUtils.h" |
| 18 | 19 |
| 19 #include "Test.h" | 20 #include "Test.h" |
| 20 #include "TestClassDef.h" | 21 #include "TestClassDef.h" |
| 21 | 22 |
| 22 /** | 23 /** |
| 23 * Fill this bitmap with some color. | 24 * Fill this bitmap with some color. |
| 24 */ | 25 */ |
| 25 static void make_test_image(SkBitmap* bm) { | 26 static void make_test_image(SkBitmap* bm) { |
| 26 static const int W = 50, H = 50; | 27 static const int W = 50, H = 50; |
| 27 static const SkBitmap::Config config = SkBitmap::kARGB_8888_Config; | 28 static const SkBitmap::Config config = SkBitmap::kARGB_8888_Config; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 43 */ | 44 */ |
| 44 static SkData* create_data_from_bitmap(const SkBitmap& bm, | 45 static SkData* create_data_from_bitmap(const SkBitmap& bm, |
| 45 SkImageEncoder::Type type) { | 46 SkImageEncoder::Type type) { |
| 46 SkDynamicMemoryWStream stream; | 47 SkDynamicMemoryWStream stream; |
| 47 if (SkImageEncoder::EncodeStream(&stream, bm, type, 100)) { | 48 if (SkImageEncoder::EncodeStream(&stream, bm, type, 100)) { |
| 48 return stream.copyToData(); | 49 return stream.copyToData(); |
| 49 } | 50 } |
| 50 return NULL; | 51 return NULL; |
| 51 } | 52 } |
| 52 | 53 |
| 53 /** | 54 //////////////////////////////////////////////////////////////////////////////// |
| 54 * A simplified version of SkBitmapFactory | |
| 55 */ | |
| 56 static bool simple_bitmap_factory(SkBitmapFactory::DecodeProc proc, | |
| 57 SkData* data, | |
| 58 SkBitmap* dst) { | |
| 59 SkImageInfo info; | |
| 60 if (!proc(data->data(), data->size(), &info, NULL)) { | |
| 61 return false; | |
| 62 } | |
| 63 dst->setConfig(SkImageInfoToBitmapConfig(info), info.fWidth, | |
| 64 info.fHeight, 0, info.fAlphaType); | |
| 65 SkAutoTUnref<SkLazyPixelRef> ref(SkNEW_ARGS(SkLazyPixelRef, | |
| 66 (data, proc, NULL))); | |
| 67 dst->setPixelRef(ref); | |
| 68 return true; | |
| 69 } | |
| 70 | 55 |
| 71 static void compare_bitmaps(skiatest::Reporter* reporter, | 56 static void compare_bitmaps(skiatest::Reporter* reporter, |
| 72 const SkBitmap& b1, const SkBitmap& b2, | 57 const SkBitmap& b1, const SkBitmap& b2, |
| 73 bool pixelPerfect = true) { | 58 bool pixelPerfect = true) { |
| 74 REPORTER_ASSERT(reporter, b1.empty() == b2.empty()); | 59 REPORTER_ASSERT(reporter, b1.empty() == b2.empty()); |
| 75 REPORTER_ASSERT(reporter, b1.width() == b2.width()); | 60 REPORTER_ASSERT(reporter, b1.width() == b2.width()); |
| 76 REPORTER_ASSERT(reporter, b1.height() == b2.height()); | 61 REPORTER_ASSERT(reporter, b1.height() == b2.height()); |
| 77 REPORTER_ASSERT(reporter, b1.isNull() == b2.isNull()); | 62 REPORTER_ASSERT(reporter, b1.isNull() == b2.isNull()); |
| 78 SkAutoLockPixels autoLockPixels1(b1); | 63 SkAutoLockPixels autoLockPixels1(b1); |
| 79 SkAutoLockPixels autoLockPixels2(b2); | 64 SkAutoLockPixels autoLockPixels2(b2); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 98 for (int y = 0; y < b2.height(); ++y) { | 83 for (int y = 0; y < b2.height(); ++y) { |
| 99 for (int x = 0; x < b2.width(); ++x) { | 84 for (int x = 0; x < b2.width(); ++x) { |
| 100 if (b1.getColor(x, y) != b2.getColor(x, y)) { | 85 if (b1.getColor(x, y) != b2.getColor(x, y)) { |
| 101 ++pixelErrors; | 86 ++pixelErrors; |
| 102 } | 87 } |
| 103 } | 88 } |
| 104 } | 89 } |
| 105 REPORTER_ASSERT(reporter, 0 == pixelErrors); | 90 REPORTER_ASSERT(reporter, 0 == pixelErrors); |
| 106 } | 91 } |
| 107 | 92 |
| 108 | |
| 109 typedef bool (*InstallEncoded)(SkData* encoded, SkBitmap* dst); | 93 typedef bool (*InstallEncoded)(SkData* encoded, SkBitmap* dst); |
| 110 | 94 |
| 111 /** | 95 /** |
| 112 This function tests three differently encoded images against the | 96 This function tests three differently encoded images against the |
| 113 original bitmap */ | 97 original bitmap */ |
| 114 static void test_three_encodings(skiatest::Reporter* reporter, | 98 static void test_three_encodings(skiatest::Reporter* reporter, |
| 115 InstallEncoded install) { | 99 InstallEncoded install) { |
| 116 SkBitmap original; | 100 SkBitmap original; |
| 117 make_test_image(&original); | 101 make_test_image(&original); |
| 118 REPORTER_ASSERT(reporter, !original.empty()); | 102 REPORTER_ASSERT(reporter, !original.empty()); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 REPORTER_ASSERT(reporter, NULL != lazy.getPixels()); | 137 REPORTER_ASSERT(reporter, NULL != lazy.getPixels()); |
| 154 if (NULL == lazy.getPixels()) { | 138 if (NULL == lazy.getPixels()) { |
| 155 continue; | 139 continue; |
| 156 } | 140 } |
| 157 } | 141 } |
| 158 bool comparePixels = (SkImageEncoder::kPNG_Type == type); | 142 bool comparePixels = (SkImageEncoder::kPNG_Type == type); |
| 159 compare_bitmaps(reporter, original, lazy, comparePixels); | 143 compare_bitmaps(reporter, original, lazy, comparePixels); |
| 160 } | 144 } |
| 161 } | 145 } |
| 162 | 146 |
| 163 | |
| 164 //////////////////////////////////////////////////////////////////////////////// | 147 //////////////////////////////////////////////////////////////////////////////// |
| 165 /** | 148 static bool install_skCachingPixelRef(SkData* encoded, SkBitmap* dst) { |
| 166 * This checks to see that a SkLazyPixelRef works as advertised. | 149 return SkCachingPixelRef::Install( |
| 167 */ | 150 SkNEW_ARGS(SkDecodingImageGenerator, (encoded)), dst); |
| 168 static bool install_skLazyPixelRef(SkData* encoded, SkBitmap* dst) { | |
| 169 static const SkBitmapFactory::DecodeProc decoder = | |
| 170 &(SkImageDecoder::DecodeMemoryToTarget); | |
| 171 return simple_bitmap_factory(decoder, encoded, dst); | |
| 172 } | 151 } |
| 173 DEF_TEST(LazyPixelRef, reporter) { | 152 static bool install_skDiscardablePixelRef(SkData* encoded, SkBitmap* dst) { |
| 174 test_three_encodings(reporter, install_skLazyPixelRef); | 153 // Use system-default discardable memory. |
| 154 return SkDecodingImageGenerator::Install(encoded, dst, NULL); |
| 175 } | 155 } |
| 176 | 156 |
| 177 //////////////////////////////////////////////////////////////////////////////// | 157 //////////////////////////////////////////////////////////////////////////////// |
| 178 /** | 158 /** |
| 179 * This checks to see that a SkCachingPixelRef works as advertised. | 159 * This checks to see that a SkCachingPixelRef and a |
| 160 * SkDiscardablePixelRef works as advertised with a |
| 161 * SkDecodingImageGenerator. |
| 180 */ | 162 */ |
| 181 static bool install_skCachingPixelRef(SkData* encoded, SkBitmap* dst) { | 163 DEF_TEST(DecodingImageGenerator, reporter) { |
| 182 return SkCachingPixelRef::Install( | |
| 183 SkNEW_ARGS(SkDecodingImageGenerator, (encoded)), dst); | |
| 184 } | |
| 185 DEF_TEST(CachingPixelRef, reporter) { | |
| 186 test_three_encodings(reporter, install_skCachingPixelRef); | 164 test_three_encodings(reporter, install_skCachingPixelRef); |
| 165 test_three_encodings(reporter, install_skDiscardablePixelRef); |
| 187 } | 166 } |
| 188 | 167 |
| 189 //////////////////////////////////////////////////////////////////////////////// | 168 //////////////////////////////////////////////////////////////////////////////// |
| 169 namespace { |
| 170 class TestImageGenerator : public SkImageGenerator { |
| 171 public: |
| 172 enum TestType { |
| 173 kFailGetInfo_TestType, |
| 174 kFailGetPixels_TestType, |
| 175 kSucceedGetPixels_TestType, |
| 176 kLast_TestType = kSucceedGetPixels_TestType |
| 177 }; |
| 178 static int Width() { return 10; } |
| 179 static int Height() { return 10; } |
| 180 static SkColor Color() { return SK_ColorCYAN; } |
| 181 TestImageGenerator(TestType type, skiatest::Reporter* reporter) |
| 182 : fType(type), fReporter(reporter) { |
| 183 SkASSERT((fType <= kLast_TestType) && (fType >= 0)); |
| 184 } |
| 185 ~TestImageGenerator() { } |
| 186 bool getInfo(SkImageInfo* info) SK_OVERRIDE { |
| 187 REPORTER_ASSERT(fReporter, NULL != info); |
| 188 if ((NULL == info) || (kFailGetInfo_TestType == fType)) { |
| 189 return false; |
| 190 } |
| 191 info->fWidth = TestImageGenerator::Width(); |
| 192 info->fHeight = TestImageGenerator::Height(); |
| 193 info->fColorType = kPMColor_SkColorType; |
| 194 info->fAlphaType = kOpaque_SkAlphaType; |
| 195 return true; |
| 196 } |
| 197 bool getPixels(const SkImageInfo& info, |
| 198 void* pixels, |
| 199 size_t rowBytes) SK_OVERRIDE { |
| 200 REPORTER_ASSERT(fReporter, pixels != NULL); |
| 201 size_t minRowBytes |
| 202 = static_cast<size_t>(info.fWidth * info.bytesPerPixel()); |
| 203 REPORTER_ASSERT(fReporter, rowBytes >= minRowBytes); |
| 204 if ((NULL == pixels) |
| 205 || (fType != kSucceedGetPixels_TestType) |
| 206 || (info.fColorType != kPMColor_SkColorType)) { |
| 207 return false; |
| 208 } |
| 209 char* bytePtr = static_cast<char*>(pixels); |
| 210 for (int y = 0; y < info.fHeight; ++y) { |
| 211 sk_memset32(reinterpret_cast<SkColor*>(bytePtr), |
| 212 TestImageGenerator::Color(), info.fWidth); |
| 213 bytePtr += rowBytes; |
| 214 } |
| 215 return true; |
| 216 } |
| 217 private: |
| 218 const TestType fType; |
| 219 skiatest::Reporter* const fReporter; |
| 220 }; |
| 221 void CheckTestImageGeneratorBitmap(skiatest::Reporter* reporter, |
| 222 const SkBitmap& bm) { |
| 223 REPORTER_ASSERT(reporter, TestImageGenerator::Width() == bm.width()); |
| 224 REPORTER_ASSERT(reporter, TestImageGenerator::Height() == bm.height()); |
| 225 SkAutoLockPixels autoLockPixels(bm); |
| 226 REPORTER_ASSERT(reporter, NULL != bm.getPixels()); |
| 227 if (NULL == bm.getPixels()) { |
| 228 return; |
| 229 } |
| 230 int errors = 0; |
| 231 for (int y = 0; y < bm.height(); ++y) { |
| 232 for (int x = 0; x < bm.width(); ++x) { |
| 233 if (TestImageGenerator::Color() != *bm.getAddr32(x, y)) { |
| 234 ++errors; |
| 235 } |
| 236 } |
| 237 } |
| 238 REPORTER_ASSERT(reporter, 0 == errors); |
| 239 } |
| 240 |
| 241 enum PixelRefType { |
| 242 kSkCaching_PixelRefType, |
| 243 kSkDiscardable_PixelRefType, |
| 244 kLast_PixelRefType = kSkDiscardable_PixelRefType |
| 245 }; |
| 246 void CheckPixelRef(TestImageGenerator::TestType type, |
| 247 skiatest::Reporter* reporter, |
| 248 PixelRefType pixelRefType, |
| 249 SkDiscardableMemory::Factory* factory) { |
| 250 SkASSERT((pixelRefType >= 0) && (pixelRefType <= kLast_PixelRefType)); |
| 251 SkAutoTDelete<SkImageGenerator> gen(SkNEW_ARGS(TestImageGenerator, |
| 252 (type, reporter))); |
| 253 REPORTER_ASSERT(reporter, gen.get() != NULL); |
| 254 SkBitmap lazy; |
| 255 bool success; |
| 256 if (kSkCaching_PixelRefType == pixelRefType) { |
| 257 // Ignore factory; use global SkScaledImageCache. |
| 258 success = SkCachingPixelRef::Install(gen.detach(), &lazy); |
| 259 } else { |
| 260 success = SkDiscardablePixelRef::Install(gen.detach(), &lazy, factory); |
| 261 } |
| 262 REPORTER_ASSERT(reporter, success |
| 263 == (TestImageGenerator::kFailGetInfo_TestType != type)); |
| 264 if (TestImageGenerator::kSucceedGetPixels_TestType == type) { |
| 265 CheckTestImageGeneratorBitmap(reporter, lazy); |
| 266 } else if (TestImageGenerator::kFailGetPixels_TestType == type) { |
| 267 SkAutoLockPixels autoLockPixels(lazy); |
| 268 REPORTER_ASSERT(reporter, NULL == lazy.getPixels()); |
| 269 } |
| 270 } |
| 271 } // namespace |
| 190 /** | 272 /** |
| 191 * This checks to see that a SkDecodingImageGenerator works as advertised. | 273 * This tests the basic functionality of SkDiscardablePixelRef with a |
| 274 * basic SkImageGenerator implementation and several |
| 275 * SkDiscardableMemory::Factory choices. |
| 192 */ | 276 */ |
| 193 DEF_TEST(DecodingImageGenerator, reporter) { | 277 DEF_TEST(DiscardableAndCachingPixelRef, reporter) { |
| 194 test_three_encodings(reporter, SkDecodingImageGenerator::Install); | 278 CheckPixelRef(TestImageGenerator::kFailGetInfo_TestType, |
| 279 reporter, kSkCaching_PixelRefType, NULL); |
| 280 CheckPixelRef(TestImageGenerator::kFailGetPixels_TestType, |
| 281 reporter, kSkCaching_PixelRefType, NULL); |
| 282 CheckPixelRef(TestImageGenerator::kSucceedGetPixels_TestType, |
| 283 reporter, kSkCaching_PixelRefType, NULL); |
| 284 |
| 285 CheckPixelRef(TestImageGenerator::kFailGetInfo_TestType, |
| 286 reporter, kSkDiscardable_PixelRefType, NULL); |
| 287 CheckPixelRef(TestImageGenerator::kFailGetPixels_TestType, |
| 288 reporter, kSkDiscardable_PixelRefType, NULL); |
| 289 CheckPixelRef(TestImageGenerator::kSucceedGetPixels_TestType, |
| 290 reporter, kSkDiscardable_PixelRefType, NULL); |
| 291 |
| 292 SkAutoTUnref<SkDiscardableMemoryPool> pool( |
| 293 SkNEW_ARGS(SkDiscardableMemoryPool, (1, NULL))); |
| 294 REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed()); |
| 295 CheckPixelRef(TestImageGenerator::kFailGetPixels_TestType, |
| 296 reporter, kSkDiscardable_PixelRefType, pool); |
| 297 REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed()); |
| 298 CheckPixelRef(TestImageGenerator::kSucceedGetPixels_TestType, |
| 299 reporter, kSkDiscardable_PixelRefType, pool); |
| 300 REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed()); |
| 301 |
| 302 SkDiscardableMemoryPool* globalPool = SkGetGlobalDiscardableMemoryPool(); |
| 303 CheckPixelRef(TestImageGenerator::kFailGetPixels_TestType, |
| 304 reporter, kSkDiscardable_PixelRefType, globalPool); |
| 305 CheckPixelRef(TestImageGenerator::kSucceedGetPixels_TestType, |
| 306 reporter, kSkDiscardable_PixelRefType, globalPool); |
| 307 |
| 308 // TODO(halcanary): When ashmem-backed SkDiscardableMemory lands, |
| 309 // test that here (on platforms where it is availible). |
| 195 } | 310 } |
| 311 //////////////////////////////////////////////////////////////////////////////// |
| 312 |
| OLD | NEW |