2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef ImageDecodingStore_h
27 #define ImageDecodingStore_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"
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"
46 class ImageFrameGenerator;
51 // ImageDecodingStore is a class used to manage image cache objects. There are two
52 // types of cache objects stored:
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.
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
67 // ScaledImageFragment
68 // A cached image object. Contains the bitmap and information about the bitmap
72 // A decoder object. It is used to decode raw data into bitmap images.
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.
79 // LazyDecodingPixelRef
80 // A read only user of this cache.
84 // All public methods can be used on any thread.
86 class PLATFORM_EXPORT ImageDecodingStore {
88 static PassOwnPtr<ImageDecodingStore> create() { return adoptPtr(new ImageDecodingStore); }
89 ~ImageDecodingStore();
91 static ImageDecodingStore* instance();
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.
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
103 static void setImageCachingEnabled(bool);
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>);
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*);
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);
124 // Remove all cache entries indexed by ImageFrameGenerator.
125 void removeCacheIndexedByGenerator(const ImageFrameGenerator*);
128 void setCacheLimitInBytes(size_t);
129 size_t memoryUsageInBytes();
131 int imageCacheEntries();
132 int decoderCacheEntries();
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.
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.
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;
149 // Base class for all cache entries.
150 class CacheEntry : public DoublyLinkedListNode<CacheEntry> {
151 friend class WTF::DoublyLinkedListNode<CacheEntry>;
158 CacheEntry(const ImageFrameGenerator* generator, int useCount, bool isDiscardable)
159 : m_generator(generator)
160 , m_useCount(useCount)
161 , m_isDiscardable(isDiscardable)
167 virtual ~CacheEntry()
172 const ImageFrameGenerator* generator() const { return m_generator; }
173 int useCount() const { return m_useCount; }
174 void incrementUseCount() { ++m_useCount; }
175 void decrementUseCount() { --m_useCount; ASSERT(m_useCount >= 0); }
176 bool isDiscardable() const { return m_isDiscardable; }
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;
184 const ImageFrameGenerator* m_generator;
186 bool m_isDiscardable;
193 class ImageCacheEntry FINAL : public CacheEntry {
195 static PassOwnPtr<ImageCacheEntry> createAndUse(const ImageFrameGenerator* generator, PassOwnPtr<ScaledImageFragment> image)
197 return adoptPtr(new ImageCacheEntry(generator, 1, image));
200 ImageCacheEntry(const ImageFrameGenerator* generator, int count, PassOwnPtr<ScaledImageFragment> image)
201 : CacheEntry(generator, count, DiscardablePixelRef::isDiscardable(image->bitmap().pixelRef()))
202 , m_cachedImage(image)
206 // FIXME: getSafeSize() returns size in bytes truncated to a 32-bits integer.
207 // Find a way to get the size in 64-bits.
208 virtual size_t memoryUsageInBytes() const OVERRIDE { return cachedImage()->bitmap().getSafeSize(); }
209 virtual CacheType type() const OVERRIDE { return TypeImage; }
211 static ImageCacheKey makeCacheKey(const ImageFrameGenerator* generator, const SkISize& size, size_t index, size_t generation)
213 return std::make_pair(std::make_pair(generator, size), std::make_pair(index, generation));
215 ImageCacheKey cacheKey() const { return makeCacheKey(m_generator, m_cachedImage->scaledSize(), m_cachedImage->index(), m_cachedImage->generation()); }
216 const ScaledImageFragment* cachedImage() const { return m_cachedImage.get(); }
217 ScaledImageFragment* cachedImage() { return m_cachedImage.get(); }
220 OwnPtr<ScaledImageFragment> m_cachedImage;
223 class DecoderCacheEntry FINAL : public CacheEntry {
225 static PassOwnPtr<DecoderCacheEntry> create(const ImageFrameGenerator* generator, PassOwnPtr<ImageDecoder> decoder, bool isDiscardable)
227 return adoptPtr(new DecoderCacheEntry(generator, 0, decoder, 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()))
237 virtual size_t memoryUsageInBytes() const OVERRIDE { return m_size.width() * m_size.height() * 4; }
238 virtual CacheType type() const OVERRIDE { return TypeDecoder; }
240 static DecoderCacheKey makeCacheKey(const ImageFrameGenerator* generator, const SkISize& size)
242 return std::make_pair(generator, size);
244 static DecoderCacheKey makeCacheKey(const ImageFrameGenerator* generator, const ImageDecoder* decoder)
246 return std::make_pair(generator, SkISize::Make(decoder->decodedSize().width(), decoder->decodedSize().height()));
248 DecoderCacheKey cacheKey() const { return makeCacheKey(m_generator, m_size); }
249 ImageDecoder* cachedDecoder() const { return m_cachedDecoder.get(); }
252 OwnPtr<ImageDecoder> m_cachedDecoder;
256 ImageDecodingStore();
260 // These helper methods are called while m_mutex is locked.
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
265 bool lockCacheEntryInternal(ImageCacheEntry*, const ScaledImageFragment**, Vector<OwnPtr<CacheEntry> >* deletionList);
267 template<class T, class U, class V> void insertCacheInternal(PassOwnPtr<T> cacheEntry, U* cacheMap, V* identifierMap);
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);
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);
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);
281 // Helper method to remove cache entry pointers from the LRU list.
282 void removeFromCacheListInternal(const Vector<OwnPtr<CacheEntry> >& deletionList);
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;
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;
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;
298 // A lookup table to map ImageFrameGenerator to all associated image
300 typedef HashSet<ImageCacheKey> ImageCacheKeySet;
301 typedef HashMap<const ImageFrameGenerator*, ImageCacheKeySet> ImageCacheKeyMap;
302 ImageCacheKeyMap m_imageCacheKeyMap;
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;
310 size_t m_heapLimitInBytes;
311 size_t m_heapMemoryUsageInBytes;
312 size_t m_discardableMemoryUsageInBytes;
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.