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/DiscardablePixelRef.h" 33 #include "platform/graphics/ScaledImageFragment.h" 34 #include "platform/graphics/skia/SkSizeHash.h" 35 #include "platform/image-decoders/ImageDecoder.h" 36 37 #include "wtf/DoublyLinkedList.h" 38 #include "wtf/HashSet.h" 39 #include "wtf/OwnPtr.h" 40 #include "wtf/PassOwnPtr.h" 41 #include "wtf/ThreadingPrimitives.h" 42 #include "wtf/Vector.h" 43 44 namespace WebCore { 45 46 class ImageFrameGenerator; 47 class SharedBuffer; 48 49 // FUNCTION 50 // 51 // ImageDecodingStore is a class used to manage image cache objects. There are two 52 // types of cache objects stored: 53 // 54 // 1. Image objects 55 // Each image object belongs to one frame decoded and/or resampled from an image 56 // file. The image object can be complete or partial. Complete means the image 57 // is fully decoded and will not mutate in future decoding passes. It can have 58 // multiple concurrent users. A partial image object has only one user. 59 // 60 // 2. Decoder objects 61 // A decoder object contains an image decoder. This allows decoding to resume 62 // from previous states. There can be one user per one decoder object at any 63 // time. 64 // 65 // EXTERNAL OBJECTS 66 // 67 // ScaledImageFragment 68 // A cached image object. Contains the bitmap and information about the bitmap 69 // image. 70 // 71 // ImageDecoder 72 // A decoder object. It is used to decode raw data into bitmap images. 73 // 74 // ImageFrameGenerator 75 // This is a direct user of this cache. Responsible for generating bitmap images 76 // using an ImageDecoder. It contains encoded image data and is used to represent 77 // one image file. It is used to index image and decoder objects in the cache. 78 // 79 // LazyDecodingPixelRef 80 // A read only user of this cache. 81 // 82 // THREAD SAFETY 83 // 84 // All public methods can be used on any thread. 85 86 class PLATFORM_EXPORT ImageDecodingStore { 87 public: create()88 static PassOwnPtr<ImageDecodingStore> create() { return adoptPtr(new ImageDecodingStore); } 89 ~ImageDecodingStore(); 90 91 static ImageDecodingStore* instance(); 92 93 // Why do we need this? 94 // ImageDecodingStore is used in two code paths: 95 // 1. Android uses this to cache both images and decoders. 96 // 2. Skia discardable memory path has its own cache. We still want cache 97 // decoders but not images because Skia will take care of it. 98 // Because of the two use cases we want to just disable image caching. 99 // 100 // FIXME: It is weird to have this behavior. We want to remove image 101 // caching from this class once the transition to Skia discardable memory 102 // is complete. 103 static void setImageCachingEnabled(bool); 104 105 // Access a complete cached image object. A complete cached image object is 106 // indexed by the origin (ImageFrameGenerator), scaled size and frame index 107 // within the image file. 108 // Return true if the cache object is found. 109 // Return false if the cache object cannot be found or it is incomplete. 110 bool lockCache(const ImageFrameGenerator*, const SkISize& scaledSize, size_t index, const ScaledImageFragment**); 111 void unlockCache(const ImageFrameGenerator*, const ScaledImageFragment*); 112 const ScaledImageFragment* insertAndLockCache(const ImageFrameGenerator*, PassOwnPtr<ScaledImageFragment>); 113 114 // Access a cached decoder object. A decoder is indexed by origin (ImageFrameGenerator) 115 // and scaled size. Return true if the cached object is found. 116 bool lockDecoder(const ImageFrameGenerator*, const SkISize& scaledSize, ImageDecoder**); 117 void unlockDecoder(const ImageFrameGenerator*, const ImageDecoder*); 118 void insertDecoder(const ImageFrameGenerator*, PassOwnPtr<ImageDecoder>, bool isDiscardable); 119 void removeDecoder(const ImageFrameGenerator*, const ImageDecoder*); 120 121 // Locks the cache for safety, but does not attempt to lock the object we're checking for. 122 bool isCached(const ImageFrameGenerator*, const SkISize& scaledSize, size_t index); 123 124 // Remove all cache entries indexed by ImageFrameGenerator. 125 void removeCacheIndexedByGenerator(const ImageFrameGenerator*); 126 127 void clear(); 128 void setCacheLimitInBytes(size_t); 129 size_t memoryUsageInBytes(); 130 int cacheEntries(); 131 int imageCacheEntries(); 132 int decoderCacheEntries(); 133 134 private: 135 // Image cache entry is identified by: 136 // 1. Pointer to ImageFrameGenerator. 137 // 2. Size of the image. 138 // 3. LocalFrame index. 139 // 4. LocalFrame generation. Increments on each progressive decode. 140 // 141 // The use of generation ID is to allow multiple versions of an image frame 142 // be stored in the cache. Each generation comes from a progressive decode. 143 // 144 // Decoder entries are identified by (1) and (2) only. 145 typedef std::pair<const ImageFrameGenerator*, SkISize> DecoderCacheKey; 146 typedef std::pair<size_t, size_t> IndexAndGeneration; 147 typedef std::pair<DecoderCacheKey, IndexAndGeneration> ImageCacheKey; 148 149 // Base class for all cache entries. 150 class CacheEntry : public DoublyLinkedListNode<CacheEntry> { 151 friend class WTF::DoublyLinkedListNode<CacheEntry>; 152 public: 153 enum CacheType { 154 TypeImage, 155 TypeDecoder, 156 }; 157 CacheEntry(const ImageFrameGenerator * generator,int useCount,bool isDiscardable)158 CacheEntry(const ImageFrameGenerator* generator, int useCount, bool isDiscardable) 159 : m_generator(generator) 160 , m_useCount(useCount) 161 , m_isDiscardable(isDiscardable) 162 , m_prev(0) 163 , m_next(0) 164 { 165 } 166 ~CacheEntry()167 virtual ~CacheEntry() 168 { 169 ASSERT(!m_useCount); 170 } 171 generator()172 const ImageFrameGenerator* generator() const { return m_generator; } useCount()173 int useCount() const { return m_useCount; } incrementUseCount()174 void incrementUseCount() { ++m_useCount; } decrementUseCount()175 void decrementUseCount() { --m_useCount; ASSERT(m_useCount >= 0); } isDiscardable()176 bool isDiscardable() const { return m_isDiscardable; } 177 178 // FIXME: getSafeSize() returns size in bytes truncated to a 32-bits integer. 179 // Find a way to get the size in 64-bits. 180 virtual size_t memoryUsageInBytes() const = 0; 181 virtual CacheType type() const = 0; 182 183 protected: 184 const ImageFrameGenerator* m_generator; 185 int m_useCount; 186 bool m_isDiscardable; 187 188 private: 189 CacheEntry* m_prev; 190 CacheEntry* m_next; 191 }; 192 193 class ImageCacheEntry FINAL : public CacheEntry { 194 public: createAndUse(const ImageFrameGenerator * generator,PassOwnPtr<ScaledImageFragment> image)195 static PassOwnPtr<ImageCacheEntry> createAndUse(const ImageFrameGenerator* generator, PassOwnPtr<ScaledImageFragment> image) 196 { 197 return adoptPtr(new ImageCacheEntry(generator, 1, image)); 198 } 199 ImageCacheEntry(const ImageFrameGenerator * generator,int count,PassOwnPtr<ScaledImageFragment> image)200 ImageCacheEntry(const ImageFrameGenerator* generator, int count, PassOwnPtr<ScaledImageFragment> image) 201 : CacheEntry(generator, count, DiscardablePixelRef::isDiscardable(image->bitmap().pixelRef())) 202 , m_cachedImage(image) 203 { 204 } 205 206 // FIXME: getSafeSize() returns size in bytes truncated to a 32-bits integer. 207 // Find a way to get the size in 64-bits. memoryUsageInBytes()208 virtual size_t memoryUsageInBytes() const OVERRIDE { return cachedImage()->bitmap().getSafeSize(); } type()209 virtual CacheType type() const OVERRIDE { return TypeImage; } 210 makeCacheKey(const ImageFrameGenerator * generator,const SkISize & size,size_t index,size_t generation)211 static ImageCacheKey makeCacheKey(const ImageFrameGenerator* generator, const SkISize& size, size_t index, size_t generation) 212 { 213 return std::make_pair(std::make_pair(generator, size), std::make_pair(index, generation)); 214 } cacheKey()215 ImageCacheKey cacheKey() const { return makeCacheKey(m_generator, m_cachedImage->scaledSize(), m_cachedImage->index(), m_cachedImage->generation()); } cachedImage()216 const ScaledImageFragment* cachedImage() const { return m_cachedImage.get(); } cachedImage()217 ScaledImageFragment* cachedImage() { return m_cachedImage.get(); } 218 219 private: 220 OwnPtr<ScaledImageFragment> m_cachedImage; 221 }; 222 223 class DecoderCacheEntry FINAL : public CacheEntry { 224 public: create(const ImageFrameGenerator * generator,PassOwnPtr<ImageDecoder> decoder,bool isDiscardable)225 static PassOwnPtr<DecoderCacheEntry> create(const ImageFrameGenerator* generator, PassOwnPtr<ImageDecoder> decoder, bool isDiscardable) 226 { 227 return adoptPtr(new DecoderCacheEntry(generator, 0, decoder, isDiscardable)); 228 } 229 DecoderCacheEntry(const ImageFrameGenerator * generator,int count,PassOwnPtr<ImageDecoder> decoder,bool isDiscardable)230 DecoderCacheEntry(const ImageFrameGenerator* generator, int count, PassOwnPtr<ImageDecoder> decoder, bool isDiscardable) 231 : CacheEntry(generator, count, isDiscardable) 232 , m_cachedDecoder(decoder) 233 , m_size(SkISize::Make(m_cachedDecoder->decodedSize().width(), m_cachedDecoder->decodedSize().height())) 234 { 235 } 236 memoryUsageInBytes()237 virtual size_t memoryUsageInBytes() const OVERRIDE { return m_size.width() * m_size.height() * 4; } type()238 virtual CacheType type() const OVERRIDE { return TypeDecoder; } 239 makeCacheKey(const ImageFrameGenerator * generator,const SkISize & size)240 static DecoderCacheKey makeCacheKey(const ImageFrameGenerator* generator, const SkISize& size) 241 { 242 return std::make_pair(generator, size); 243 } makeCacheKey(const ImageFrameGenerator * generator,const ImageDecoder * decoder)244 static DecoderCacheKey makeCacheKey(const ImageFrameGenerator* generator, const ImageDecoder* decoder) 245 { 246 return std::make_pair(generator, SkISize::Make(decoder->decodedSize().width(), decoder->decodedSize().height())); 247 } cacheKey()248 DecoderCacheKey cacheKey() const { return makeCacheKey(m_generator, m_size); } cachedDecoder()249 ImageDecoder* cachedDecoder() const { return m_cachedDecoder.get(); } 250 251 private: 252 OwnPtr<ImageDecoder> m_cachedDecoder; 253 SkISize m_size; 254 }; 255 256 ImageDecodingStore(); 257 258 void prune(); 259 260 // These helper methods are called while m_mutex is locked. 261 262 // Find and lock a cache entry, and return true on success. 263 // Memory of the cache entry can be discarded, in which case it is saved in 264 // deletionList. 265 bool lockCacheEntryInternal(ImageCacheEntry*, const ScaledImageFragment**, Vector<OwnPtr<CacheEntry> >* deletionList); 266 267 template<class T, class U, class V> void insertCacheInternal(PassOwnPtr<T> cacheEntry, U* cacheMap, V* identifierMap); 268 269 // Helper method to remove a cache entry. Ownership is transferred to 270 // deletionList. Use of Vector<> is handy when removing multiple entries. 271 template<class T, class U, class V> void removeFromCacheInternal(const T* cacheEntry, U* cacheMap, V* identifierMap, Vector<OwnPtr<CacheEntry> >* deletionList); 272 273 // Helper method to remove a cache entry. Uses the templated version base on 274 // the type of cache entry. 275 void removeFromCacheInternal(const CacheEntry*, Vector<OwnPtr<CacheEntry> >* deletionList); 276 277 // Helper method to remove all cache entries associated with a ImageFraneGenerator. 278 // Ownership of cache entries is transferred to deletionList. 279 template<class U, class V> void removeCacheIndexedByGeneratorInternal(U* cacheMap, V* identifierMap, const ImageFrameGenerator*, Vector<OwnPtr<CacheEntry> >* deletionList); 280 281 // Helper method to remove cache entry pointers from the LRU list. 282 void removeFromCacheListInternal(const Vector<OwnPtr<CacheEntry> >& deletionList); 283 284 // A doubly linked list that maintains usage history of cache entries. 285 // This is used for eviction of old entries. 286 // Head of this list is the least recently used cache entry. 287 // Tail of this list is the most recently used cache entry. 288 DoublyLinkedList<CacheEntry> m_orderedCacheList; 289 290 // A lookup table for all image cache objects. Owns all image cache objects. 291 typedef HashMap<ImageCacheKey, OwnPtr<ImageCacheEntry> > ImageCacheMap; 292 ImageCacheMap m_imageCacheMap; 293 294 // A lookup table for all decoder cache objects. Owns all decoder cache objects. 295 typedef HashMap<DecoderCacheKey, OwnPtr<DecoderCacheEntry> > DecoderCacheMap; 296 DecoderCacheMap m_decoderCacheMap; 297 298 // A lookup table to map ImageFrameGenerator to all associated image 299 // cache keys. 300 typedef HashSet<ImageCacheKey> ImageCacheKeySet; 301 typedef HashMap<const ImageFrameGenerator*, ImageCacheKeySet> ImageCacheKeyMap; 302 ImageCacheKeyMap m_imageCacheKeyMap; 303 304 // A lookup table to map ImageFrameGenerator to all associated 305 // decoder cache keys. 306 typedef HashSet<DecoderCacheKey> DecoderCacheKeySet; 307 typedef HashMap<const ImageFrameGenerator*, DecoderCacheKeySet> DecoderCacheKeyMap; 308 DecoderCacheKeyMap m_decoderCacheKeyMap; 309 310 size_t m_heapLimitInBytes; 311 size_t m_heapMemoryUsageInBytes; 312 size_t m_discardableMemoryUsageInBytes; 313 314 // Protect concurrent access to these members: 315 // m_orderedCacheList 316 // m_imageCacheMap, m_decoderCacheMap and all CacheEntrys stored in it 317 // m_imageCacheKeyMap 318 // m_decoderCacheKeyMap 319 // m_heapLimitInBytes 320 // m_heapMemoryUsageInBytes 321 // m_discardableMemoryUsageInBytes 322 // This mutex also protects calls to underlying skBitmap's 323 // lockPixels()/unlockPixels() as they are not threadsafe. 324 Mutex m_mutex; 325 }; 326 327 } // namespace WebCore 328 329 #endif 330