• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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