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