Home | History | Annotate | Download | only in chromium
      1 /*
      2  * Copyright (C) 2012 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 
     28 #include "core/platform/graphics/chromium/ImageDecodingStore.h"
     29 
     30 #include "core/platform/SharedBuffer.h"
     31 #include "core/platform/graphics/chromium/ImageFrameGenerator.h"
     32 #include "core/platform/graphics/chromium/test/MockDiscardablePixelRef.h"
     33 #include "core/platform/graphics/chromium/test/MockImageDecoder.h"
     34 #include <gtest/gtest.h>
     35 
     36 using namespace WebCore;
     37 
     38 namespace {
     39 
     40 class ImageDecodingStoreTest : public ::testing::Test, public MockImageDecoderClient {
     41 public:
     42     virtual void SetUp()
     43     {
     44         ImageDecodingStore::initializeOnce();
     45         m_data = SharedBuffer::create();
     46         m_generator = ImageFrameGenerator::create(SkISize::Make(100, 100), m_data, true);
     47         m_decodersDestroyed = 0;
     48     }
     49 
     50     virtual void TearDown()
     51     {
     52         ImageDecodingStore::shutdown();
     53     }
     54 
     55     virtual void decoderBeingDestroyed()
     56     {
     57         ++m_decodersDestroyed;
     58     }
     59 
     60     virtual void frameBufferRequested()
     61     {
     62         // Decoder is never used by ImageDecodingStore.
     63         ASSERT_TRUE(false);
     64     }
     65 
     66     virtual ImageFrame::FrameStatus frameStatus()
     67     {
     68         return ImageFrame::FramePartial;
     69     }
     70 
     71     virtual size_t frameCount() { return 1; }
     72     virtual int repetitionCount() const { return cAnimationNone; }
     73     virtual float frameDuration() const { return 0; }
     74 
     75 protected:
     76     PassOwnPtr<ScaledImageFragment> createCompleteImage(const SkISize& size, bool discardable = false, size_t index = 0)
     77     {
     78         SkBitmap bitmap;
     79         bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
     80         if (!discardable)
     81             bitmap.allocPixels();
     82         else
     83             bitmap.setPixelRef(new MockDiscardablePixelRef())->unref();
     84         return ScaledImageFragment::createComplete(size, index, bitmap);
     85     }
     86 
     87     PassOwnPtr<ScaledImageFragment> createIncompleteImage(const SkISize& size, bool discardable = false, size_t generation = 0)
     88     {
     89         SkBitmap bitmap;
     90         bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
     91         if (!discardable)
     92             bitmap.allocPixels();
     93         else
     94             bitmap.setPixelRef(new MockDiscardablePixelRef())->unref();
     95         return ScaledImageFragment::createPartial(size, 0, generation, bitmap);
     96     }
     97 
     98     void insertCache(const SkISize& size)
     99     {
    100         const ScaledImageFragment* image = ImageDecodingStore::instance()->insertAndLockCache(
    101             m_generator.get(), createCompleteImage(size));
    102         unlockCache(image);
    103     }
    104 
    105     const ScaledImageFragment* lockCache(const SkISize& size, size_t index = 0)
    106     {
    107         const ScaledImageFragment* cachedImage = 0;
    108         if (ImageDecodingStore::instance()->lockCache(m_generator.get(), size, index, &cachedImage))
    109             return cachedImage;
    110         return 0;
    111     }
    112 
    113     void unlockCache(const ScaledImageFragment* cachedImage)
    114     {
    115         ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
    116     }
    117 
    118     void evictOneCache()
    119     {
    120         size_t memoryUsageInBytes = ImageDecodingStore::instance()->memoryUsageInBytes();
    121         if (memoryUsageInBytes)
    122             ImageDecodingStore::instance()->setCacheLimitInBytes(memoryUsageInBytes - 1);
    123         else
    124             ImageDecodingStore::instance()->setCacheLimitInBytes(0);
    125     }
    126 
    127     bool isCacheAlive(const SkISize& size)
    128     {
    129         const ScaledImageFragment* cachedImage = lockCache(size);
    130         if (!cachedImage)
    131             return false;
    132         ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
    133         return true;
    134     }
    135 
    136     RefPtr<SharedBuffer> m_data;
    137     RefPtr<ImageFrameGenerator> m_generator;
    138     int m_decodersDestroyed;
    139 };
    140 
    141 TEST_F(ImageDecodingStoreTest, evictOneCache)
    142 {
    143     insertCache(SkISize::Make(1, 1));
    144     insertCache(SkISize::Make(2, 2));
    145     insertCache(SkISize::Make(3, 3));
    146     EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries());
    147 
    148     evictOneCache();
    149     EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
    150 
    151     evictOneCache();
    152     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
    153 }
    154 
    155 TEST_F(ImageDecodingStoreTest, pruneOrderIsLeastRecentlyUsed)
    156 {
    157     insertCache(SkISize::Make(1, 1));
    158     insertCache(SkISize::Make(2, 2));
    159     insertCache(SkISize::Make(3, 3));
    160     insertCache(SkISize::Make(4, 4));
    161     insertCache(SkISize::Make(5, 5));
    162     EXPECT_EQ(5u, ImageDecodingStore::instance()->cacheEntries());
    163 
    164     // Use cache in the order 3, 2, 4, 1, 5.
    165     EXPECT_TRUE(isCacheAlive(SkISize::Make(3, 3)));
    166     EXPECT_TRUE(isCacheAlive(SkISize::Make(2, 2)));
    167     EXPECT_TRUE(isCacheAlive(SkISize::Make(4, 4)));
    168     EXPECT_TRUE(isCacheAlive(SkISize::Make(1, 1)));
    169     EXPECT_TRUE(isCacheAlive(SkISize::Make(5, 5)));
    170 
    171     // Evict 3.
    172     evictOneCache();
    173     EXPECT_FALSE(isCacheAlive(SkISize::Make(3, 3)));
    174     EXPECT_EQ(4u, ImageDecodingStore::instance()->cacheEntries());
    175 
    176     // Evict 2.
    177     evictOneCache();
    178     EXPECT_FALSE(isCacheAlive(SkISize::Make(2, 2)));
    179     EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries());
    180 
    181     // Evict 4.
    182     evictOneCache();
    183     EXPECT_FALSE(isCacheAlive(SkISize::Make(4, 4)));
    184     EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
    185 
    186     // Evict 1.
    187     evictOneCache();
    188     EXPECT_FALSE(isCacheAlive(SkISize::Make(1, 1)));
    189     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
    190 
    191     // Evict 5.
    192     evictOneCache();
    193     EXPECT_FALSE(isCacheAlive(SkISize::Make(5, 5)));
    194     EXPECT_EQ(0u, ImageDecodingStore::instance()->cacheEntries());
    195 }
    196 
    197 TEST_F(ImageDecodingStoreTest, pruneCausedByInsertion)
    198 {
    199     ImageDecodingStore::instance()->setCacheLimitInBytes(100);
    200 
    201     // Insert 100 entries.
    202     // Cache entries stored should increase and eventually decrease to 1.
    203     insertCache(SkISize::Make(1, 1));
    204     insertCache(SkISize::Make(2, 2));
    205     insertCache(SkISize::Make(3, 3));
    206     EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries());
    207 
    208     for (int i = 4; i <= 100; ++i)
    209         insertCache(SkISize::Make(i, i));
    210 
    211     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
    212     for (int i = 1; i <= 99; ++i)
    213         EXPECT_FALSE(isCacheAlive(SkISize::Make(i, i)));
    214     EXPECT_TRUE(isCacheAlive(SkISize::Make(100, 100)));
    215 }
    216 
    217 TEST_F(ImageDecodingStoreTest, cacheInUseNotEvicted)
    218 {
    219     insertCache(SkISize::Make(1, 1));
    220     insertCache(SkISize::Make(2, 2));
    221     insertCache(SkISize::Make(3, 3));
    222     EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries());
    223 
    224     const ScaledImageFragment* cachedImage = lockCache(SkISize::Make(1, 1));
    225     ASSERT_TRUE(cachedImage);
    226 
    227     // Cache 2 is evicted because cache 1 is in use.
    228     evictOneCache();
    229     EXPECT_TRUE(isCacheAlive(SkISize::Make(1, 1)));
    230     EXPECT_FALSE(isCacheAlive(SkISize::Make(2, 2)));
    231     EXPECT_TRUE(isCacheAlive(SkISize::Make(3, 3)));
    232 
    233     EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
    234     unlockCache(cachedImage);
    235 }
    236 
    237 TEST_F(ImageDecodingStoreTest, destroyImageFrameGenerator)
    238 {
    239     insertCache(SkISize::Make(1, 1));
    240     insertCache(SkISize::Make(2, 2));
    241     insertCache(SkISize::Make(3, 3));
    242     OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this);
    243     decoder->setSize(1, 1);
    244     ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release(), false);
    245     EXPECT_EQ(4u, ImageDecodingStore::instance()->cacheEntries());
    246 
    247     m_generator.clear();
    248     EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries());
    249 }
    250 
    251 TEST_F(ImageDecodingStoreTest, insertDecoder)
    252 {
    253     const SkISize size = SkISize::Make(1, 1);
    254     OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this);
    255     decoder->setSize(1, 1);
    256     const ImageDecoder* refDecoder = decoder.get();
    257     ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release(), false);
    258     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
    259     EXPECT_EQ(4u, ImageDecodingStore::instance()->memoryUsageInBytes());
    260 
    261     ImageDecoder* testDecoder;
    262     EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), size, &testDecoder));
    263     EXPECT_TRUE(testDecoder);
    264     EXPECT_EQ(refDecoder, testDecoder);
    265     ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), testDecoder);
    266     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
    267 }
    268 
    269 TEST_F(ImageDecodingStoreTest, evictDecoder)
    270 {
    271     OwnPtr<ImageDecoder> decoder1 = MockImageDecoder::create(this);
    272     OwnPtr<ImageDecoder> decoder2 = MockImageDecoder::create(this);
    273     OwnPtr<ImageDecoder> decoder3 = MockImageDecoder::create(this);
    274     decoder1->setSize(1, 1);
    275     decoder2->setSize(2, 2);
    276     decoder3->setSize(3, 3);
    277     ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder1.release(), false);
    278     ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder2.release(), false);
    279     ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder3.release(), false);
    280     EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries());
    281     EXPECT_EQ(56u, ImageDecodingStore::instance()->memoryUsageInBytes());
    282 
    283     evictOneCache();
    284     EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
    285     EXPECT_EQ(52u, ImageDecodingStore::instance()->memoryUsageInBytes());
    286 
    287     evictOneCache();
    288     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
    289     EXPECT_EQ(36u, ImageDecodingStore::instance()->memoryUsageInBytes());
    290 
    291     evictOneCache();
    292     EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries());
    293     EXPECT_FALSE(ImageDecodingStore::instance()->memoryUsageInBytes());
    294 }
    295 
    296 TEST_F(ImageDecodingStoreTest, decoderInUseNotEvicted)
    297 {
    298     OwnPtr<ImageDecoder> decoder1 = MockImageDecoder::create(this);
    299     OwnPtr<ImageDecoder> decoder2 = MockImageDecoder::create(this);
    300     OwnPtr<ImageDecoder> decoder3 = MockImageDecoder::create(this);
    301     decoder1->setSize(1, 1);
    302     decoder2->setSize(2, 2);
    303     decoder3->setSize(3, 3);
    304     ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder1.release(), false);
    305     ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder2.release(), false);
    306     ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder3.release(), false);
    307     EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries());
    308 
    309     ImageDecoder* testDecoder;
    310     EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), SkISize::Make(2, 2), &testDecoder));
    311 
    312     evictOneCache();
    313     evictOneCache();
    314     evictOneCache();
    315     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
    316     EXPECT_EQ(16u, ImageDecodingStore::instance()->memoryUsageInBytes());
    317 
    318     ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), testDecoder);
    319     evictOneCache();
    320     EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries());
    321     EXPECT_FALSE(ImageDecodingStore::instance()->memoryUsageInBytes());
    322 }
    323 
    324 TEST_F(ImageDecodingStoreTest, removeDecoder)
    325 {
    326     const SkISize size = SkISize::Make(1, 1);
    327     OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this);
    328     decoder->setSize(1, 1);
    329     const ImageDecoder* refDecoder = decoder.get();
    330     ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release(), false);
    331     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
    332     EXPECT_EQ(4u, ImageDecodingStore::instance()->memoryUsageInBytes());
    333 
    334     ImageDecoder* testDecoder;
    335     EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), size, &testDecoder));
    336     EXPECT_TRUE(testDecoder);
    337     EXPECT_EQ(refDecoder, testDecoder);
    338     ImageDecodingStore::instance()->removeDecoder(m_generator.get(), testDecoder);
    339     EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries());
    340 
    341     EXPECT_FALSE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), size, &testDecoder));
    342 }
    343 
    344 TEST_F(ImageDecodingStoreTest, multipleIndex)
    345 {
    346     const SkISize size = SkISize::Make(1, 1);
    347     const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache(
    348         m_generator.get(), createCompleteImage(size, false, 0));
    349     unlockCache(refImage);
    350     const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache(
    351         m_generator.get(), createCompleteImage(size, false, 1));
    352     unlockCache(testImage);
    353     EXPECT_NE(refImage, testImage);
    354     EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
    355 
    356     EXPECT_TRUE(ImageDecodingStore::instance()->lockCache(m_generator.get(), size, 1, &refImage));
    357     EXPECT_EQ(refImage, testImage);
    358     unlockCache(refImage);
    359 }
    360 
    361 TEST_F(ImageDecodingStoreTest, finalAndPartialImage)
    362 {
    363     const SkISize size = SkISize::Make(1, 1);
    364     const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache(
    365         m_generator.get(), createCompleteImage(size, false, 0));
    366     unlockCache(refImage);
    367     const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache(
    368         m_generator.get(), createIncompleteImage(size, false, 1));
    369     unlockCache(testImage);
    370     EXPECT_NE(refImage, testImage);
    371     EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
    372 
    373     EXPECT_TRUE(ImageDecodingStore::instance()->lockCache(m_generator.get(), size, 0, &refImage));
    374     EXPECT_NE(refImage, testImage);
    375     unlockCache(refImage);
    376 }
    377 
    378 TEST_F(ImageDecodingStoreTest, insertNoGenerationCollision)
    379 {
    380     const SkISize size = SkISize::Make(1, 1);
    381     const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache(
    382         m_generator.get(), createIncompleteImage(size, false, 1));
    383     unlockCache(refImage);
    384     const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache(
    385         m_generator.get(), createIncompleteImage(size, false, 2));
    386     unlockCache(testImage);
    387     EXPECT_NE(refImage, testImage);
    388     EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
    389 }
    390 
    391 TEST_F(ImageDecodingStoreTest, insertGenerationCollision)
    392 {
    393     const SkISize size = SkISize::Make(1, 1);
    394     const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache(
    395         m_generator.get(), createIncompleteImage(size, false, 1));
    396     unlockCache(refImage);
    397     const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache(
    398         m_generator.get(), createIncompleteImage(size, false, 1));
    399     unlockCache(testImage);
    400     EXPECT_EQ(refImage, testImage);
    401     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
    402 }
    403 
    404 TEST_F(ImageDecodingStoreTest, insertGenerationCollisionAfterMemoryDiscarded)
    405 {
    406     const SkISize size = SkISize::Make(1, 1);
    407     const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache(
    408         m_generator.get(), createIncompleteImage(size, true, 1));
    409     unlockCache(refImage);
    410     MockDiscardablePixelRef* pixelRef = static_cast<MockDiscardablePixelRef*>(refImage->bitmap().pixelRef());
    411     pixelRef->discard();
    412     const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache(
    413         m_generator.get(), createIncompleteImage(size, false, 1));
    414     unlockCache(testImage);
    415     EXPECT_NE(refImage, testImage);
    416     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
    417 }
    418 
    419 TEST_F(ImageDecodingStoreTest, lockCacheFailedAfterMemoryDiscarded)
    420 {
    421     const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache(
    422         m_generator.get(), createCompleteImage(SkISize::Make(1, 1), true));
    423     unlockCache(cachedImage);
    424     MockDiscardablePixelRef* pixelRef = static_cast<MockDiscardablePixelRef*>(cachedImage->bitmap().pixelRef());
    425     pixelRef->discard();
    426     EXPECT_EQ(0, lockCache(SkISize::Make(1, 1)));
    427     EXPECT_EQ(0u, ImageDecodingStore::instance()->cacheEntries());
    428 }
    429 
    430 TEST_F(ImageDecodingStoreTest, clear)
    431 {
    432     insertCache(SkISize::Make(1, 1));
    433     insertCache(SkISize::Make(2, 2));
    434     EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
    435 
    436     OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this);
    437     decoder->setSize(1, 1);
    438     ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release(), false);
    439     EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries());
    440 
    441     ImageDecodingStore::instance()->clear();
    442     EXPECT_EQ(0u, ImageDecodingStore::instance()->cacheEntries());
    443 }
    444 
    445 TEST_F(ImageDecodingStoreTest, clearInUse)
    446 {
    447     insertCache(SkISize::Make(1, 1));
    448     insertCache(SkISize::Make(2, 2));
    449     EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
    450 
    451     const ScaledImageFragment* cachedImage = lockCache(SkISize::Make(1, 1));
    452     ASSERT_TRUE(cachedImage);
    453     ImageDecodingStore::instance()->clear();
    454     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
    455 
    456     unlockCache(cachedImage);
    457     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
    458 }
    459 
    460 } // namespace
    461