Home | History | Annotate | Download | only in tests
      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& bm1,
     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::kPinned_MemoryStatus);
     64         cache->releaseCache(ID);
     65         REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID) != SkImageCache::kPinned_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, SkData* 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 * 1024)));
    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
    198