Home | History | Annotate | Download | only in graphics
      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  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef ImageDecodingStore_h
     27 #define ImageDecodingStore_h
     28 
     29 #include "SkSize.h"
     30 #include "SkTypes.h"
     31 #include "platform/PlatformExport.h"
     32 #include "platform/graphics/skia/SkSizeHash.h"
     33 #include "platform/image-decoders/ImageDecoder.h"
     34 
     35 #include "wtf/DoublyLinkedList.h"
     36 #include "wtf/HashSet.h"
     37 #include "wtf/OwnPtr.h"
     38 #include "wtf/PassOwnPtr.h"
     39 #include "wtf/ThreadingPrimitives.h"
     40 #include "wtf/Vector.h"
     41 
     42 namespace blink {
     43 
     44 class ImageFrameGenerator;
     45 
     46 // FUNCTION
     47 //
     48 // ImageDecodingStore is a class used to manage cached decoder objects.
     49 //
     50 // EXTERNAL OBJECTS
     51 //
     52 // ImageDecoder
     53 //   A decoder object. It is used to decode raw data into bitmap images.
     54 //
     55 // ImageFrameGenerator
     56 //   This is a direct user of this cache. Responsible for generating bitmap images
     57 //   using an ImageDecoder. It contains encoded image data and is used to represent
     58 //   one image file. It is used to index image and decoder objects in the cache.
     59 //
     60 // THREAD SAFETY
     61 //
     62 // All public methods can be used on any thread.
     63 
     64 class PLATFORM_EXPORT ImageDecodingStore {
     65 public:
     66     static PassOwnPtr<ImageDecodingStore> create() { return adoptPtr(new ImageDecodingStore); }
     67     ~ImageDecodingStore();
     68 
     69     static ImageDecodingStore* instance();
     70 
     71     // Access a cached decoder object. A decoder is indexed by origin (ImageFrameGenerator)
     72     // and scaled size. Return true if the cached object is found.
     73     bool lockDecoder(const ImageFrameGenerator*, const SkISize& scaledSize, ImageDecoder**);
     74     void unlockDecoder(const ImageFrameGenerator*, const ImageDecoder*);
     75     void insertDecoder(const ImageFrameGenerator*, PassOwnPtr<ImageDecoder>);
     76     void removeDecoder(const ImageFrameGenerator*, const ImageDecoder*);
     77 
     78     // Remove all cache entries indexed by ImageFrameGenerator.
     79     void removeCacheIndexedByGenerator(const ImageFrameGenerator*);
     80 
     81     void clear();
     82     void setCacheLimitInBytes(size_t);
     83     size_t memoryUsageInBytes();
     84     int cacheEntries();
     85     int decoderCacheEntries();
     86 
     87 private:
     88     // Decoder cache entry is identified by:
     89     // 1. Pointer to ImageFrameGenerator.
     90     // 2. Size of the image.
     91     typedef std::pair<const ImageFrameGenerator*, SkISize> DecoderCacheKey;
     92 
     93     // Base class for all cache entries.
     94     class CacheEntry : public DoublyLinkedListNode<CacheEntry> {
     95         friend class WTF::DoublyLinkedListNode<CacheEntry>;
     96     public:
     97         enum CacheType {
     98             TypeDecoder,
     99         };
    100 
    101         CacheEntry(const ImageFrameGenerator* generator, int useCount)
    102             : m_generator(generator)
    103             , m_useCount(useCount)
    104             , m_prev(0)
    105             , m_next(0)
    106         {
    107         }
    108 
    109         virtual ~CacheEntry()
    110         {
    111             ASSERT(!m_useCount);
    112         }
    113 
    114         const ImageFrameGenerator* generator() const { return m_generator; }
    115         int useCount() const { return m_useCount; }
    116         void incrementUseCount() { ++m_useCount; }
    117         void decrementUseCount() { --m_useCount; ASSERT(m_useCount >= 0); }
    118 
    119         // FIXME: getSafeSize() returns size in bytes truncated to a 32-bits integer.
    120         //        Find a way to get the size in 64-bits.
    121         virtual size_t memoryUsageInBytes() const = 0;
    122         virtual CacheType type() const = 0;
    123 
    124     protected:
    125         const ImageFrameGenerator* m_generator;
    126         int m_useCount;
    127 
    128     private:
    129         CacheEntry* m_prev;
    130         CacheEntry* m_next;
    131     };
    132 
    133     class DecoderCacheEntry FINAL : public CacheEntry {
    134     public:
    135         static PassOwnPtr<DecoderCacheEntry> create(const ImageFrameGenerator* generator, PassOwnPtr<ImageDecoder> decoder)
    136         {
    137             return adoptPtr(new DecoderCacheEntry(generator, 0, decoder));
    138         }
    139 
    140         DecoderCacheEntry(const ImageFrameGenerator* generator, int count, PassOwnPtr<ImageDecoder> decoder)
    141             : CacheEntry(generator, count)
    142             , m_cachedDecoder(decoder)
    143             , m_size(SkISize::Make(m_cachedDecoder->decodedSize().width(), m_cachedDecoder->decodedSize().height()))
    144         {
    145         }
    146 
    147         virtual size_t memoryUsageInBytes() const OVERRIDE { return m_size.width() * m_size.height() * 4; }
    148         virtual CacheType type() const OVERRIDE { return TypeDecoder; }
    149 
    150         static DecoderCacheKey makeCacheKey(const ImageFrameGenerator* generator, const SkISize& size)
    151         {
    152             return std::make_pair(generator, size);
    153         }
    154         static DecoderCacheKey makeCacheKey(const ImageFrameGenerator* generator, const ImageDecoder* decoder)
    155         {
    156             return std::make_pair(generator, SkISize::Make(decoder->decodedSize().width(), decoder->decodedSize().height()));
    157         }
    158         DecoderCacheKey cacheKey() const { return makeCacheKey(m_generator, m_size); }
    159         ImageDecoder* cachedDecoder() const { return m_cachedDecoder.get(); }
    160 
    161     private:
    162         OwnPtr<ImageDecoder> m_cachedDecoder;
    163         SkISize m_size;
    164     };
    165 
    166     ImageDecodingStore();
    167 
    168     void prune();
    169 
    170     // These helper methods are called while m_mutex is locked.
    171     template<class T, class U, class V> void insertCacheInternal(PassOwnPtr<T> cacheEntry, U* cacheMap, V* identifierMap);
    172 
    173     // Helper method to remove a cache entry. Ownership is transferred to
    174     // deletionList. Use of Vector<> is handy when removing multiple entries.
    175     template<class T, class U, class V> void removeFromCacheInternal(const T* cacheEntry, U* cacheMap, V* identifierMap, Vector<OwnPtr<CacheEntry> >* deletionList);
    176 
    177     // Helper method to remove a cache entry. Uses the templated version base on
    178     // the type of cache entry.
    179     void removeFromCacheInternal(const CacheEntry*, Vector<OwnPtr<CacheEntry> >* deletionList);
    180 
    181     // Helper method to remove all cache entries associated with a ImageFraneGenerator.
    182     // Ownership of cache entries is transferred to deletionList.
    183     template<class U, class V> void removeCacheIndexedByGeneratorInternal(U* cacheMap, V* identifierMap, const ImageFrameGenerator*, Vector<OwnPtr<CacheEntry> >* deletionList);
    184 
    185     // Helper method to remove cache entry pointers from the LRU list.
    186     void removeFromCacheListInternal(const Vector<OwnPtr<CacheEntry> >& deletionList);
    187 
    188     // A doubly linked list that maintains usage history of cache entries.
    189     // This is used for eviction of old entries.
    190     // Head of this list is the least recently used cache entry.
    191     // Tail of this list is the most recently used cache entry.
    192     DoublyLinkedList<CacheEntry> m_orderedCacheList;
    193 
    194     // A lookup table for all decoder cache objects. Owns all decoder cache objects.
    195     typedef HashMap<DecoderCacheKey, OwnPtr<DecoderCacheEntry> > DecoderCacheMap;
    196     DecoderCacheMap m_decoderCacheMap;
    197 
    198     // A lookup table to map ImageFrameGenerator to all associated
    199     // decoder cache keys.
    200     typedef HashSet<DecoderCacheKey> DecoderCacheKeySet;
    201     typedef HashMap<const ImageFrameGenerator*, DecoderCacheKeySet> DecoderCacheKeyMap;
    202     DecoderCacheKeyMap m_decoderCacheKeyMap;
    203 
    204     size_t m_heapLimitInBytes;
    205     size_t m_heapMemoryUsageInBytes;
    206 
    207     // Protect concurrent access to these members:
    208     //   m_orderedCacheList
    209     //   m_decoderCacheMap and all CacheEntrys stored in it
    210     //   m_decoderCacheKeyMap
    211     //   m_heapLimitInBytes
    212     //   m_heapMemoryUsageInBytes
    213     // This mutex also protects calls to underlying skBitmap's
    214     // lockPixels()/unlockPixels() as they are not threadsafe.
    215     Mutex m_mutex;
    216 };
    217 
    218 } // namespace blink
    219 
    220 #endif
    221