OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef SkResourceCache_DEFINED | 8 #ifndef SkResourceCache_DEFINED |
9 #define SkResourceCache_DEFINED | 9 #define SkResourceCache_DEFINED |
10 | 10 |
11 #include "SkBitmap.h" | 11 #include "SkBitmap.h" |
12 #include "SkMessageBus.h" | |
13 #include "SkTDArray.h" | |
12 | 14 |
13 class SkCachedData; | 15 class SkCachedData; |
14 class SkDiscardableMemory; | 16 class SkDiscardableMemory; |
15 class SkMipMap; | 17 class SkMipMap; |
16 | 18 |
17 /** | 19 /** |
18 * Cache object for bitmaps (with possible scale in X Y as part of the key). | 20 * Cache object for bitmaps (with possible scale in X Y as part of the key). |
19 * | 21 * |
20 * Multiple caches can be instantiated, but each instance is not implicitly | 22 * Multiple caches can be instantiated, but each instance is not implicitly |
21 * thread-safe, so if a given instance is to be shared across threads, the | 23 * thread-safe, so if a given instance is to be shared across threads, the |
22 * caller must manage the access itself (e.g. via a mutex). | 24 * caller must manage the access itself (e.g. via a mutex). |
23 * | 25 * |
24 * As a convenience, a global instance is also defined, which can be safely | 26 * As a convenience, a global instance is also defined, which can be safely |
25 * access across threads via the static methods (e.g. FindAndLock, etc.). | 27 * access across threads via the static methods (e.g. FindAndLock, etc.). |
26 */ | 28 */ |
27 class SkResourceCache { | 29 class SkResourceCache { |
28 public: | 30 public: |
29 struct Key { | 31 struct Key { |
30 // Call this to access your private contents. Must not use the address a fter calling init() | 32 // Call this to access your private contents. Must not use the address a fter calling init() |
31 void* writableContents() { return this + 1; } | 33 void* writableContents() { return this + 1; } |
32 | 34 |
33 // must call this after your private data has been written. | 35 // must call this after your private data has been written. |
34 // nameSpace must be unique per Key subclass. | 36 // nameSpace must be unique per Key subclass. |
37 // sharedID == 0 means ignore this field : does not support group purgin g. | |
35 // length must be a multiple of 4 | 38 // length must be a multiple of 4 |
36 void init(void* nameSpace, size_t length); | 39 void init(void* nameSpace, uint64_t sharedID, size_t length); |
40 | |
41 void* getNamespace() const { return fNamespace; } | |
42 uint64_t getSharedID() const { return ((uint64_t)fSharedID_hi << 32) | f SharedID_lo; } | |
37 | 43 |
38 // This is only valid after having called init(). | 44 // This is only valid after having called init(). |
39 uint32_t hash() const { return fHash; } | 45 uint32_t hash() const { return fHash; } |
40 | 46 |
41 bool operator==(const Key& other) const { | 47 bool operator==(const Key& other) const { |
42 const uint32_t* a = this->as32(); | 48 const uint32_t* a = this->as32(); |
43 const uint32_t* b = other.as32(); | 49 const uint32_t* b = other.as32(); |
44 for (int i = 0; i < fCount32; ++i) { // (This checks fCount == othe r.fCount first.) | 50 for (int i = 0; i < fCount32; ++i) { // (This checks fCount == othe r.fCount first.) |
45 if (a[i] != b[i]) { | 51 if (a[i] != b[i]) { |
46 return false; | 52 return false; |
47 } | 53 } |
48 } | 54 } |
49 return true; | 55 return true; |
50 } | 56 } |
51 | 57 |
52 private: | 58 private: |
53 int32_t fCount32; // local + user contents count32 | 59 int32_t fCount32; // local + user contents count32 |
54 uint32_t fHash; | 60 uint32_t fHash; |
61 // split uint64_t into hi and lo so we don't force ourselves to pad on 3 2bit machines. | |
62 uint32_t fSharedID_lo; | |
63 uint32_t fSharedID_hi; | |
55 void* fNamespace; // A unique namespace tag. This is hashed. | 64 void* fNamespace; // A unique namespace tag. This is hashed. |
56 /* uint32_t fContents32[] */ | 65 /* uint32_t fContents32[] */ |
57 | 66 |
58 const uint32_t* as32() const { return (const uint32_t*)this; } | 67 const uint32_t* as32() const { return (const uint32_t*)this; } |
59 }; | 68 }; |
60 | 69 |
61 struct Rec { | 70 struct Rec { |
62 typedef SkResourceCache::Key Key; | 71 typedef SkResourceCache::Key Key; |
63 | 72 |
64 Rec() {} | 73 Rec() {} |
65 virtual ~Rec() {} | 74 virtual ~Rec() {} |
66 | 75 |
67 uint32_t getHash() const { return this->getKey().hash(); } | 76 uint32_t getHash() const { return this->getKey().hash(); } |
68 | 77 |
69 virtual const Key& getKey() const = 0; | 78 virtual const Key& getKey() const = 0; |
70 virtual size_t bytesUsed() const = 0; | 79 virtual size_t bytesUsed() const = 0; |
71 | 80 |
72 // for SkTDynamicHash::Traits | 81 // for SkTDynamicHash::Traits |
73 static uint32_t Hash(const Key& key) { return key.hash(); } | 82 static uint32_t Hash(const Key& key) { return key.hash(); } |
74 static const Key& GetKey(const Rec& rec) { return rec.getKey(); } | 83 static const Key& GetKey(const Rec& rec) { return rec.getKey(); } |
75 | 84 |
76 private: | 85 private: |
77 Rec* fNext; | 86 Rec* fNext; |
78 Rec* fPrev; | 87 Rec* fPrev; |
79 | 88 |
80 friend class SkResourceCache; | 89 friend class SkResourceCache; |
81 }; | 90 }; |
82 | 91 |
92 // Used with SkMessageBus | |
93 struct PurgeSharedIDMessage { | |
94 PurgeSharedIDMessage(uint64_t sharedID) : fSharedID(sharedID) {} | |
95 | |
96 uint64_t fSharedID; | |
97 }; | |
98 | |
83 typedef const Rec* ID; | 99 typedef const Rec* ID; |
84 | 100 |
85 /** | 101 /** |
86 * Callback function for find(). If called, the cache will have found a mat ch for the | 102 * Callback function for find(). If called, the cache will have found a mat ch for the |
87 * specified Key, and will pass in the corresponding Rec, along with a call er-specified | 103 * specified Key, and will pass in the corresponding Rec, along with a call er-specified |
88 * context. The function can read the data in Rec, and copy whatever it lik es into context | 104 * context. The function can read the data in Rec, and copy whatever it lik es into context |
89 * (casting context to whatever it really is). | 105 * (casting context to whatever it really is). |
90 * | 106 * |
91 * The return value determines what the cache will do with the Rec. If the function returns | 107 * The return value determines what the cache will do with the Rec. If the function returns |
92 * true, then the Rec is considered "valid". If false is returned, the Rec will be considered | 108 * true, then the Rec is considered "valid". If false is returned, the Rec will be considered |
93 * "stale" and will be purged from the cache. | 109 * "stale" and will be purged from the cache. |
94 */ | 110 */ |
95 typedef bool (*VisitorProc)(const Rec&, void* context); | 111 typedef bool (*FindVisitor)(const Rec&, void* context); |
96 | 112 |
97 /** | 113 /** |
98 * Returns a locked/pinned SkDiscardableMemory instance for the specified | 114 * Returns a locked/pinned SkDiscardableMemory instance for the specified |
99 * number of bytes, or NULL on failure. | 115 * number of bytes, or NULL on failure. |
100 */ | 116 */ |
101 typedef SkDiscardableMemory* (*DiscardableFactory)(size_t bytes); | 117 typedef SkDiscardableMemory* (*DiscardableFactory)(size_t bytes); |
102 | 118 |
103 /* | 119 /* |
104 * The following static methods are thread-safe wrappers around a global | 120 * The following static methods are thread-safe wrappers around a global |
105 * instance of this cache. | 121 * instance of this cache. |
106 */ | 122 */ |
107 | 123 |
108 /** | 124 /** |
109 * Returns true if the visitor was called on a matching Key, and the visito r returned true. | 125 * Returns true if the visitor was called on a matching Key, and the visito r returned true. |
110 * | 126 * |
111 * Find() will search the cache for the specified Key. If no match is found , return false and | 127 * Find() will search the cache for the specified Key. If no match is found , return false and |
112 * do not call the VisitorProc. If a match is found, return whatever the vi sitor returns. | 128 * do not call the VisitorProc. If a match is found, return whatever the vi sitor returns. |
f(malita)
2015/02/24 20:31:37
Doc needs name update.
reed2
2015/02/24 20:56:28
Hmmm, I think it is still accurate. If a find-visi
f(malita)
2015/02/24 20:59:38
I meant just the param name: s/VisitorProc/FindVis
reed2
2015/02/24 21:30:08
Doh. Done.
| |
113 * Its return value is interpreted to mean: | 129 * Its return value is interpreted to mean: |
114 * true : Rec is valid | 130 * true : Rec is valid |
115 * false : Rec is "stale" -- the cache will purge it. | 131 * false : Rec is "stale" -- the cache will purge it. |
116 */ | 132 */ |
117 static bool Find(const Key& key, VisitorProc, void* context); | 133 static bool Find(const Key& key, FindVisitor, void* context); |
118 static void Add(Rec*); | 134 static void Add(Rec*); |
119 | 135 |
120 static size_t GetTotalBytesUsed(); | 136 static size_t GetTotalBytesUsed(); |
121 static size_t GetTotalByteLimit(); | 137 static size_t GetTotalByteLimit(); |
122 static size_t SetTotalByteLimit(size_t newLimit); | 138 static size_t SetTotalByteLimit(size_t newLimit); |
123 | 139 |
124 static size_t SetSingleAllocationByteLimit(size_t); | 140 static size_t SetSingleAllocationByteLimit(size_t); |
125 static size_t GetSingleAllocationByteLimit(); | 141 static size_t GetSingleAllocationByteLimit(); |
126 static size_t GetEffectiveSingleAllocationByteLimit(); | 142 static size_t GetEffectiveSingleAllocationByteLimit(); |
127 | 143 |
128 static void PurgeAll(); | 144 static void PurgeAll(); |
129 | 145 |
130 /** | 146 /** |
131 * Returns the DiscardableFactory used by the global cache, or NULL. | 147 * Returns the DiscardableFactory used by the global cache, or NULL. |
132 */ | 148 */ |
133 static DiscardableFactory GetDiscardableFactory(); | 149 static DiscardableFactory GetDiscardableFactory(); |
134 | 150 |
135 /** | 151 /** |
136 * Use this allocator for bitmaps, so they can use ashmem when available. | 152 * Use this allocator for bitmaps, so they can use ashmem when available. |
137 * Returns NULL if the ResourceCache has not been initialized with a Discard ableFactory. | 153 * Returns NULL if the ResourceCache has not been initialized with a Discard ableFactory. |
138 */ | 154 */ |
139 static SkBitmap::Allocator* GetAllocator(); | 155 static SkBitmap::Allocator* GetAllocator(); |
140 | 156 |
141 static SkCachedData* NewCachedData(size_t bytes); | 157 static SkCachedData* NewCachedData(size_t bytes); |
142 | 158 |
159 static void PostPurgeSharedID(uint64_t sharedID); | |
160 | |
143 /** | 161 /** |
144 * Call SkDebugf() with diagnostic information about the state of the cache | 162 * Call SkDebugf() with diagnostic information about the state of the cache |
145 */ | 163 */ |
146 static void Dump(); | 164 static void Dump(); |
147 | 165 |
148 /////////////////////////////////////////////////////////////////////////// | 166 /////////////////////////////////////////////////////////////////////////// |
149 | 167 |
150 /** | 168 /** |
151 * Construct the cache to call DiscardableFactory when it | 169 * Construct the cache to call DiscardableFactory when it |
152 * allocates memory for the pixels. In this mode, the cache has | 170 * allocates memory for the pixels. In this mode, the cache has |
(...skipping 14 matching lines...) Expand all Loading... | |
167 | 185 |
168 /** | 186 /** |
169 * Returns true if the visitor was called on a matching Key, and the visito r returned true. | 187 * Returns true if the visitor was called on a matching Key, and the visito r returned true. |
170 * | 188 * |
171 * find() will search the cache for the specified Key. If no match is found , return false and | 189 * find() will search the cache for the specified Key. If no match is found , return false and |
172 * do not call the VisitorProc. If a match is found, return whatever the vi sitor returns. | 190 * do not call the VisitorProc. If a match is found, return whatever the vi sitor returns. |
173 * Its return value is interpreted to mean: | 191 * Its return value is interpreted to mean: |
174 * true : Rec is valid | 192 * true : Rec is valid |
175 * false : Rec is "stale" -- the cache will purge it. | 193 * false : Rec is "stale" -- the cache will purge it. |
176 */ | 194 */ |
177 bool find(const Key&, VisitorProc, void* context); | 195 bool find(const Key&, FindVisitor, void* context); |
178 void add(Rec*); | 196 void add(Rec*); |
179 | 197 |
180 size_t getTotalBytesUsed() const { return fTotalBytesUsed; } | 198 size_t getTotalBytesUsed() const { return fTotalBytesUsed; } |
181 size_t getTotalByteLimit() const { return fTotalByteLimit; } | 199 size_t getTotalByteLimit() const { return fTotalByteLimit; } |
182 | 200 |
183 /** | 201 /** |
184 * This is respected by SkBitmapProcState::possiblyScaleImage. | 202 * This is respected by SkBitmapProcState::possiblyScaleImage. |
185 * 0 is no maximum at all; this is the default. | 203 * 0 is no maximum at all; this is the default. |
186 * setSingleAllocationByteLimit() returns the previous value. | 204 * setSingleAllocationByteLimit() returns the previous value. |
187 */ | 205 */ |
188 size_t setSingleAllocationByteLimit(size_t maximumAllocationSize); | 206 size_t setSingleAllocationByteLimit(size_t maximumAllocationSize); |
189 size_t getSingleAllocationByteLimit() const; | 207 size_t getSingleAllocationByteLimit() const; |
190 // returns the logical single allocation size (pinning against the budget wh en the cache | 208 // returns the logical single allocation size (pinning against the budget wh en the cache |
191 // is not backed by discardable memory. | 209 // is not backed by discardable memory. |
192 size_t getEffectiveSingleAllocationByteLimit() const; | 210 size_t getEffectiveSingleAllocationByteLimit() const; |
193 | 211 |
194 /** | 212 /** |
195 * Set the maximum number of bytes available to this cache. If the current | 213 * Set the maximum number of bytes available to this cache. If the current |
196 * cache exceeds this new value, it will be purged to try to fit within | 214 * cache exceeds this new value, it will be purged to try to fit within |
197 * this new limit. | 215 * this new limit. |
198 */ | 216 */ |
199 size_t setTotalByteLimit(size_t newLimit); | 217 size_t setTotalByteLimit(size_t newLimit); |
200 | 218 |
219 void purgeSharedID(uint64_t sharedID); | |
220 | |
201 void purgeAll() { | 221 void purgeAll() { |
202 this->purgeAsNeeded(true); | 222 this->purgeAsNeeded(true); |
203 } | 223 } |
204 | 224 |
205 DiscardableFactory discardableFactory() const { return fDiscardableFactory; } | 225 DiscardableFactory discardableFactory() const { return fDiscardableFactory; } |
206 SkBitmap::Allocator* allocator() const { return fAllocator; }; | 226 SkBitmap::Allocator* allocator() const { return fAllocator; }; |
207 | 227 |
208 SkCachedData* newCachedData(size_t bytes); | 228 SkCachedData* newCachedData(size_t bytes); |
209 | 229 |
210 /** | 230 /** |
(...skipping 10 matching lines...) Expand all Loading... | |
221 | 241 |
222 DiscardableFactory fDiscardableFactory; | 242 DiscardableFactory fDiscardableFactory; |
223 // the allocator is NULL or one that matches discardables | 243 // the allocator is NULL or one that matches discardables |
224 SkBitmap::Allocator* fAllocator; | 244 SkBitmap::Allocator* fAllocator; |
225 | 245 |
226 size_t fTotalBytesUsed; | 246 size_t fTotalBytesUsed; |
227 size_t fTotalByteLimit; | 247 size_t fTotalByteLimit; |
228 size_t fSingleAllocationByteLimit; | 248 size_t fSingleAllocationByteLimit; |
229 int fCount; | 249 int fCount; |
230 | 250 |
251 SkMessageBus<PurgeSharedIDMessage>::Inbox fPurgeSharedIDInbox; | |
252 | |
253 void checkMessages(); | |
231 void purgeAsNeeded(bool forcePurge = false); | 254 void purgeAsNeeded(bool forcePurge = false); |
232 | 255 |
233 // linklist management | 256 // linklist management |
234 void moveToHead(Rec*); | 257 void moveToHead(Rec*); |
235 void addToHead(Rec*); | 258 void addToHead(Rec*); |
236 void detach(Rec*); | 259 void detach(Rec*); |
237 void remove(Rec*); | 260 void remove(Rec*); |
238 | 261 |
239 void init(); // called by constructors | 262 void init(); // called by constructors |
240 | 263 |
241 #ifdef SK_DEBUG | 264 #ifdef SK_DEBUG |
242 void validate() const; | 265 void validate() const; |
243 #else | 266 #else |
244 void validate() const {} | 267 void validate() const {} |
245 #endif | 268 #endif |
246 }; | 269 }; |
247 #endif | 270 #endif |
OLD | NEW |