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: create()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 CacheEntry(const ImageFrameGenerator * generator,int useCount)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 ~CacheEntry()109 virtual ~CacheEntry() 110 { 111 ASSERT(!m_useCount); 112 } 113 generator()114 const ImageFrameGenerator* generator() const { return m_generator; } useCount()115 int useCount() const { return m_useCount; } incrementUseCount()116 void incrementUseCount() { ++m_useCount; } decrementUseCount()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: create(const ImageFrameGenerator * generator,PassOwnPtr<ImageDecoder> decoder)135 static PassOwnPtr<DecoderCacheEntry> create(const ImageFrameGenerator* generator, PassOwnPtr<ImageDecoder> decoder) 136 { 137 return adoptPtr(new DecoderCacheEntry(generator, 0, decoder)); 138 } 139 DecoderCacheEntry(const ImageFrameGenerator * generator,int count,PassOwnPtr<ImageDecoder> decoder)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 memoryUsageInBytes()147 virtual size_t memoryUsageInBytes() const OVERRIDE { return m_size.width() * m_size.height() * 4; } type()148 virtual CacheType type() const OVERRIDE { return TypeDecoder; } 149 makeCacheKey(const ImageFrameGenerator * generator,const SkISize & size)150 static DecoderCacheKey makeCacheKey(const ImageFrameGenerator* generator, const SkISize& size) 151 { 152 return std::make_pair(generator, size); 153 } makeCacheKey(const ImageFrameGenerator * generator,const ImageDecoder * decoder)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 } cacheKey()158 DecoderCacheKey cacheKey() const { return makeCacheKey(m_generator, m_size); } cachedDecoder()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