Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2013 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 #include "SkBitmap.h"
      9 #include "SkCanvas.h"
     10 #include "SkData.h"
     11 #include "SkDiscardableMemoryPool.h"
     12 #include "SkImage.h"
     13 #include "SkImageEncoder.h"
     14 #include "SkImageGeneratorPriv.h"
     15 #include "SkResourceCache.h"
     16 #include "SkStream.h"
     17 #include "SkUtils.h"
     18 
     19 #include "Test.h"
     20 
     21 /**
     22  * Fill this bitmap with some color.
     23  */
     24 static void make_test_image(SkBitmap* bm) {
     25     const int W = 50, H = 50;
     26     bm->allocN32Pixels(W, H);
     27     bm->eraseColor(SK_ColorBLACK);
     28     SkCanvas canvas(*bm);
     29     SkPaint paint;
     30     paint.setColor(SK_ColorBLUE);
     31     canvas.drawRectCoords(0, 0, SkIntToScalar(W/2),
     32                           SkIntToScalar(H/2), paint);
     33     paint.setColor(SK_ColorWHITE);
     34     canvas.drawRectCoords(SkIntToScalar(W/2), SkIntToScalar(H/2),
     35                           SkIntToScalar(W), SkIntToScalar(H), paint);
     36 }
     37 
     38 /**
     39  * encode this bitmap into some data via SkImageEncoder
     40  */
     41 static SkData* create_data_from_bitmap(const SkBitmap& bm,
     42                                        SkImageEncoder::Type type) {
     43     SkDynamicMemoryWStream stream;
     44     if (SkImageEncoder::EncodeStream(&stream, bm, type, 100)) {
     45         return stream.copyToData();
     46     }
     47     return nullptr;
     48 }
     49 
     50 ////////////////////////////////////////////////////////////////////////////////
     51 
     52 static void compare_bitmaps(skiatest::Reporter* reporter,
     53                             const SkBitmap& b1, const SkBitmap& b2,
     54                             bool pixelPerfect = true) {
     55     REPORTER_ASSERT(reporter, b1.empty() == b2.empty());
     56     REPORTER_ASSERT(reporter, b1.width() == b2.width());
     57     REPORTER_ASSERT(reporter, b1.height() == b2.height());
     58     REPORTER_ASSERT(reporter, b1.isNull() == b2.isNull());
     59     SkAutoLockPixels autoLockPixels1(b1);
     60     SkAutoLockPixels autoLockPixels2(b2);
     61     REPORTER_ASSERT(reporter, b1.isNull() == b2.isNull());
     62     if (b1.isNull() || b1.empty()) {
     63         return;
     64     }
     65     REPORTER_ASSERT(reporter, b1.getPixels());
     66     REPORTER_ASSERT(reporter, b2.getPixels());
     67     if ((!(b1.getPixels())) || (!(b2.getPixels()))) {
     68         return;
     69     }
     70     if ((b1.width() != b2.width()) ||
     71         (b1.height() != b2.height())) {
     72         return;
     73     }
     74     if (!pixelPerfect) {
     75         return;
     76     }
     77 
     78     int pixelErrors = 0;
     79     for (int y = 0; y < b2.height(); ++y) {
     80         for (int x = 0; x < b2.width(); ++x) {
     81             if (b1.getColor(x, y) != b2.getColor(x, y)) {
     82                 ++pixelErrors;
     83             }
     84         }
     85     }
     86     REPORTER_ASSERT(reporter, 0 == pixelErrors);
     87 }
     88 
     89 typedef bool (*InstallEncoded)(SkData* encoded, SkBitmap* dst);
     90 
     91 /**
     92    This function tests three differently encoded images against the
     93    original bitmap */
     94 static void test_three_encodings(skiatest::Reporter* reporter,
     95                                  InstallEncoded install) {
     96     SkBitmap original;
     97     make_test_image(&original);
     98     REPORTER_ASSERT(reporter, !original.empty());
     99     REPORTER_ASSERT(reporter, !original.isNull());
    100     if (original.empty() || original.isNull()) {
    101         return;
    102     }
    103     static const SkImageEncoder::Type types[] = {
    104         SkImageEncoder::kPNG_Type,
    105         SkImageEncoder::kJPEG_Type,
    106         SkImageEncoder::kWEBP_Type
    107     };
    108     for (size_t i = 0; i < SK_ARRAY_COUNT(types); i++) {
    109         SkImageEncoder::Type type = types[i];
    110         SkAutoDataUnref encoded(create_data_from_bitmap(original, type));
    111         REPORTER_ASSERT(reporter, encoded.get() != nullptr);
    112         if (nullptr == encoded.get()) {
    113             continue;
    114         }
    115         SkBitmap lazy;
    116         bool installSuccess = install(encoded.get(), &lazy);
    117         REPORTER_ASSERT(reporter, installSuccess);
    118         if (!installSuccess) {
    119             continue;
    120         }
    121         REPORTER_ASSERT(reporter, nullptr == lazy.getPixels());
    122         {
    123             SkAutoLockPixels autoLockPixels(lazy);  // now pixels are good.
    124             REPORTER_ASSERT(reporter, lazy.getPixels());
    125             if (nullptr == lazy.getPixels()) {
    126                 continue;
    127             }
    128         }
    129         // pixels should be gone!
    130         REPORTER_ASSERT(reporter, nullptr == lazy.getPixels());
    131         {
    132             SkAutoLockPixels autoLockPixels(lazy);  // now pixels are good.
    133             REPORTER_ASSERT(reporter, lazy.getPixels());
    134             if (nullptr == lazy.getPixels()) {
    135                 continue;
    136             }
    137         }
    138         bool comparePixels = (SkImageEncoder::kPNG_Type == type);
    139         compare_bitmaps(reporter, original, lazy, comparePixels);
    140     }
    141 }
    142 
    143 ////////////////////////////////////////////////////////////////////////////////
    144 static bool install_skDiscardablePixelRef(SkData* encoded, SkBitmap* dst) {
    145     // Use system-default discardable memory.
    146     return SkDEPRECATED_InstallDiscardablePixelRef(encoded, dst);
    147 }
    148 
    149 ////////////////////////////////////////////////////////////////////////////////
    150 /**
    151  *  This checks to see that SkDiscardablePixelRef works as advertised with a
    152  *  SkDecodingImageGenerator.
    153  */
    154 DEF_TEST(DecodingImageGenerator, reporter) {
    155     test_three_encodings(reporter, install_skDiscardablePixelRef);
    156 }
    157 
    158 class TestImageGenerator : public SkImageGenerator {
    159 public:
    160     enum TestType {
    161         kFailGetPixels_TestType,
    162         kSucceedGetPixels_TestType,
    163         kLast_TestType = kSucceedGetPixels_TestType
    164     };
    165     static int Width() { return 10; }
    166     static int Height() { return 10; }
    167     // value choosen so that there is no loss when converting to to RGB565 and back
    168     static SkColor Color() { return 0xff10345a; }
    169     static SkPMColor PMColor() { return SkPreMultiplyColor(Color()); }
    170 
    171     TestImageGenerator(TestType type, skiatest::Reporter* reporter,
    172                        SkColorType colorType = kN32_SkColorType)
    173     : INHERITED(GetMyInfo(colorType)), fType(type), fReporter(reporter) {
    174         SkASSERT((fType <= kLast_TestType) && (fType >= 0));
    175     }
    176     virtual ~TestImageGenerator() { }
    177 
    178 protected:
    179     static SkImageInfo GetMyInfo(SkColorType colorType) {
    180         return SkImageInfo::Make(TestImageGenerator::Width(), TestImageGenerator::Height(),
    181                                  colorType, kOpaque_SkAlphaType);
    182     }
    183 
    184     bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
    185                      SkPMColor ctable[], int* ctableCount) override {
    186         REPORTER_ASSERT(fReporter, pixels != nullptr);
    187         REPORTER_ASSERT(fReporter, rowBytes >= info.minRowBytes());
    188         if (fType != kSucceedGetPixels_TestType) {
    189             return false;
    190         }
    191         if (info.colorType() != kN32_SkColorType && info.colorType() != getInfo().colorType()) {
    192             return false;
    193         }
    194         char* bytePtr = static_cast<char*>(pixels);
    195         switch (info.colorType()) {
    196             case kN32_SkColorType:
    197                 for (int y = 0; y < info.height(); ++y) {
    198                     sk_memset32((uint32_t*)bytePtr,
    199                                 TestImageGenerator::PMColor(), info.width());
    200                     bytePtr += rowBytes;
    201                 }
    202                 break;
    203             case kIndex_8_SkColorType:
    204                 *ctableCount = 1;
    205                 ctable[0] = TestImageGenerator::PMColor();
    206                 for (int y = 0; y < info.height(); ++y) {
    207                     memset(bytePtr, 0, info.width());
    208                     bytePtr += rowBytes;
    209                 }
    210                 break;
    211             case kRGB_565_SkColorType:
    212                 for (int y = 0; y < info.height(); ++y) {
    213                     sk_memset16((uint16_t*)bytePtr,
    214                         SkPixel32ToPixel16(TestImageGenerator::PMColor()), info.width());
    215                     bytePtr += rowBytes;
    216                 }
    217                 break;
    218             default:
    219                 return false;
    220         }
    221         return true;
    222     }
    223 
    224 private:
    225     const TestType fType;
    226     skiatest::Reporter* const fReporter;
    227 
    228     typedef SkImageGenerator INHERITED;
    229 };
    230 
    231 static void check_test_image_generator_bitmap(skiatest::Reporter* reporter,
    232                                               const SkBitmap& bm) {
    233     REPORTER_ASSERT(reporter, TestImageGenerator::Width() == bm.width());
    234     REPORTER_ASSERT(reporter, TestImageGenerator::Height() == bm.height());
    235     SkAutoLockPixels autoLockPixels(bm);
    236     REPORTER_ASSERT(reporter, bm.getPixels());
    237     if (nullptr == bm.getPixels()) {
    238         return;
    239     }
    240     int errors = 0;
    241     for (int y = 0; y < bm.height(); ++y) {
    242         for (int x = 0; x < bm.width(); ++x) {
    243             if (TestImageGenerator::Color() != bm.getColor(x, y)) {
    244                 ++errors;
    245             }
    246         }
    247     }
    248     REPORTER_ASSERT(reporter, 0 == errors);
    249 }
    250 
    251 static void check_pixelref(TestImageGenerator::TestType type,
    252                            skiatest::Reporter* reporter,
    253                            SkDiscardableMemory::Factory* factory,
    254                            SkColorType colorType) {
    255     SkAutoTDelete<SkImageGenerator> gen(new TestImageGenerator(type, reporter, colorType));
    256     REPORTER_ASSERT(reporter, gen.get() != nullptr);
    257     SkBitmap lazy;
    258     bool success = SkDEPRECATED_InstallDiscardablePixelRef(gen.detach(), nullptr, &lazy, factory);
    259 
    260     REPORTER_ASSERT(reporter, success);
    261     if (TestImageGenerator::kSucceedGetPixels_TestType == type) {
    262         check_test_image_generator_bitmap(reporter, lazy);
    263     } else if (TestImageGenerator::kFailGetPixels_TestType == type) {
    264         SkAutoLockPixels autoLockPixels(lazy);
    265         REPORTER_ASSERT(reporter, nullptr == lazy.getPixels());
    266     }
    267 }
    268 
    269 /**
    270  *  This tests the basic functionality of SkDiscardablePixelRef with a
    271  *  basic SkImageGenerator implementation and several
    272  *  SkDiscardableMemory::Factory choices.
    273  */
    274 DEF_TEST(DiscardableAndCachingPixelRef, reporter) {
    275     const SkColorType testColorTypes[] = {
    276         kN32_SkColorType,
    277         kIndex_8_SkColorType,
    278         kRGB_565_SkColorType
    279     };
    280     for (const SkColorType testColorType : testColorTypes) {
    281         check_pixelref(TestImageGenerator::kFailGetPixels_TestType, reporter, nullptr,
    282                        testColorType);
    283         check_pixelref(TestImageGenerator::kSucceedGetPixels_TestType, reporter, nullptr,
    284                        testColorType);
    285 
    286         SkAutoTUnref<SkDiscardableMemoryPool> pool(
    287             SkDiscardableMemoryPool::Create(1, nullptr));
    288         REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed());
    289         check_pixelref(TestImageGenerator::kFailGetPixels_TestType, reporter, pool,
    290                        testColorType);
    291         REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed());
    292         check_pixelref(TestImageGenerator::kSucceedGetPixels_TestType, reporter, pool,
    293                        testColorType);
    294         REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed());
    295 
    296         SkDiscardableMemoryPool* globalPool = SkGetGlobalDiscardableMemoryPool();
    297         // Only acts differently from nullptr on a platform that has a
    298         // default discardable memory implementation that differs from the
    299         // global DM pool.
    300         check_pixelref(TestImageGenerator::kFailGetPixels_TestType, reporter, globalPool,
    301                        testColorType);
    302         check_pixelref(TestImageGenerator::kSucceedGetPixels_TestType, reporter, globalPool,
    303                        testColorType);
    304     }
    305 }
    306 
    307 ////////////////////////////////////////////////////////////////////////////////
    308 
    309 DEF_TEST(Image_NewFromGenerator, r) {
    310     const TestImageGenerator::TestType testTypes[] = {
    311         TestImageGenerator::kFailGetPixels_TestType,
    312         TestImageGenerator::kSucceedGetPixels_TestType,
    313     };
    314     const SkColorType testColorTypes[] = {
    315         kN32_SkColorType,
    316         kIndex_8_SkColorType,
    317         kRGB_565_SkColorType
    318     };
    319     for (size_t i = 0; i < SK_ARRAY_COUNT(testTypes); ++i) {
    320         TestImageGenerator::TestType test = testTypes[i];
    321         for (const SkColorType testColorType : testColorTypes) {
    322             SkImageGenerator* gen = new TestImageGenerator(test, r, testColorType);
    323             SkAutoTUnref<SkImage> image(SkImage::NewFromGenerator(gen));
    324             if (nullptr == image.get()) {
    325                 ERRORF(r, "SkImage::NewFromGenerator unexpecedly failed ["
    326                     SK_SIZE_T_SPECIFIER "]", i);
    327                 continue;
    328             }
    329             REPORTER_ASSERT(r, TestImageGenerator::Width() == image->width());
    330             REPORTER_ASSERT(r, TestImageGenerator::Height() == image->height());
    331             REPORTER_ASSERT(r, image->isLazyGenerated());
    332 
    333             SkBitmap bitmap;
    334             bitmap.allocN32Pixels(TestImageGenerator::Width(), TestImageGenerator::Height());
    335             SkCanvas canvas(bitmap);
    336             const SkColor kDefaultColor = 0xffabcdef;
    337             canvas.clear(kDefaultColor);
    338             canvas.drawImage(image, 0, 0, nullptr);
    339             if (TestImageGenerator::kSucceedGetPixels_TestType == test) {
    340                 REPORTER_ASSERT(
    341                     r, TestImageGenerator::Color() == bitmap.getColor(0, 0));
    342             }
    343             else {
    344                 REPORTER_ASSERT(r, kDefaultColor == bitmap.getColor(0, 0));
    345             }
    346         }
    347     }
    348 }
    349