Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(196)

Side by Side Diff: src/core/SkResourceCache.h

Issue 950363002: Notify resource caches when pixelref genID goes stale (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: too much, magic bus Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698