|
1 /* |
|
2 * Copyright 2013 Google Inc. |
|
3 * |
|
4 * Use of this source code is governed by a BSD-style license that can be |
|
5 * found in the LICENSE file. |
|
6 */ |
|
7 |
|
8 #ifndef SkScaledImageCache_DEFINED |
|
9 #define SkScaledImageCache_DEFINED |
|
10 |
|
11 #include "SkBitmap.h" |
|
12 |
|
13 class SkDiscardableMemory; |
|
14 class SkMipMap; |
|
15 |
|
16 /** |
|
17 * Cache object for bitmaps (with possible scale in X Y as part of the key). |
|
18 * |
|
19 * Multiple caches can be instantiated, but each instance is not implicitly |
|
20 * thread-safe, so if a given instance is to be shared across threads, the |
|
21 * caller must manage the access itself (e.g. via a mutex). |
|
22 * |
|
23 * As a convenience, a global instance is also defined, which can be safely |
|
24 * access across threads via the static methods (e.g. FindAndLock, etc.). |
|
25 */ |
|
26 class SkScaledImageCache { |
|
27 public: |
|
28 struct ID; |
|
29 |
|
30 /** |
|
31 * Returns a locked/pinned SkDiscardableMemory instance for the specified |
|
32 * number of bytes, or NULL on failure. |
|
33 */ |
|
34 typedef SkDiscardableMemory* (*DiscardableFactory)(size_t bytes); |
|
35 |
|
36 /* |
|
37 * The following static methods are thread-safe wrappers around a global |
|
38 * instance of this cache. |
|
39 */ |
|
40 |
|
41 static ID* FindAndLock(uint32_t pixelGenerationID, |
|
42 int32_t width, |
|
43 int32_t height, |
|
44 SkBitmap* returnedBitmap); |
|
45 |
|
46 static ID* FindAndLock(const SkBitmap& original, SkScalar scaleX, |
|
47 SkScalar scaleY, SkBitmap* returnedBitmap); |
|
48 static ID* FindAndLockMip(const SkBitmap& original, |
|
49 SkMipMap const** returnedMipMap); |
|
50 |
|
51 |
|
52 static ID* AddAndLock(uint32_t pixelGenerationID, |
|
53 int32_t width, |
|
54 int32_t height, |
|
55 const SkBitmap& bitmap); |
|
56 |
|
57 static ID* AddAndLock(const SkBitmap& original, SkScalar scaleX, |
|
58 SkScalar scaleY, const SkBitmap& bitmap); |
|
59 static ID* AddAndLockMip(const SkBitmap& original, const SkMipMap* mipMap); |
|
60 |
|
61 static void Unlock(ID*); |
|
62 |
|
63 static size_t GetBytesUsed(); |
|
64 static size_t GetByteLimit(); |
|
65 static size_t SetByteLimit(size_t newLimit); |
|
66 |
|
67 static SkBitmap::Allocator* GetAllocator(); |
|
68 |
|
69 /** |
|
70 * Call SkDebugf() with diagnostic information about the state of the cache |
|
71 */ |
|
72 static void Dump(); |
|
73 |
|
74 /////////////////////////////////////////////////////////////////////////// |
|
75 |
|
76 /** |
|
77 * Construct the cache to call DiscardableFactory when it |
|
78 * allocates memory for the pixels. In this mode, the cache has |
|
79 * not explicit budget, and so methods like getBytesUsed() and |
|
80 * getByteLimit() will return 0, and setByteLimit will ignore its argument |
|
81 * and return 0. |
|
82 */ |
|
83 SkScaledImageCache(DiscardableFactory); |
|
84 |
|
85 /** |
|
86 * Construct the cache, allocating memory with malloc, and respect the |
|
87 * byteLimit, purging automatically when a new image is added to the cache |
|
88 * that pushes the total bytesUsed over the limit. Note: The limit can be |
|
89 * changed at runtime with setByteLimit. |
|
90 */ |
|
91 SkScaledImageCache(size_t byteLimit); |
|
92 |
|
93 ~SkScaledImageCache(); |
|
94 |
|
95 /** |
|
96 * Search the cache for a matching bitmap (using generationID, |
|
97 * width, and height as a search key). If found, return it in |
|
98 * returnedBitmap, and return its ID pointer. Use the returned |
|
99 * ptr to unlock the cache when you are done using |
|
100 * returnedBitmap. |
|
101 * |
|
102 * If a match is not found, returnedBitmap will be unmodifed, and |
|
103 * NULL will be returned. |
|
104 * |
|
105 * This is used if there is no scaling or subsetting, for example |
|
106 * by SkLazyPixelRef. |
|
107 */ |
|
108 ID* findAndLock(uint32_t pixelGenerationID, int32_t width, int32_t height, |
|
109 SkBitmap* returnedBitmap); |
|
110 |
|
111 /** |
|
112 * Search the cache for a scaled version of original. If found, |
|
113 * return it in returnedBitmap, and return its ID pointer. Use |
|
114 * the returned ptr to unlock the cache when you are done using |
|
115 * returnedBitmap. |
|
116 * |
|
117 * If a match is not found, returnedBitmap will be unmodifed, and |
|
118 * NULL will be returned. |
|
119 */ |
|
120 ID* findAndLock(const SkBitmap& original, SkScalar scaleX, |
|
121 SkScalar scaleY, SkBitmap* returnedBitmap); |
|
122 ID* findAndLockMip(const SkBitmap& original, |
|
123 SkMipMap const** returnedMipMap); |
|
124 |
|
125 /** |
|
126 * To add a new bitmap (or mipMap) to the cache, call |
|
127 * AddAndLock. Use the returned ptr to unlock the cache when you |
|
128 * are done using scaled. |
|
129 * |
|
130 * Use (generationID, width, and height) or (original, scaleX, |
|
131 * scaleY) or (original) as a search key |
|
132 */ |
|
133 ID* addAndLock(uint32_t pixelGenerationID, int32_t width, int32_t height, |
|
134 const SkBitmap& bitmap); |
|
135 ID* addAndLock(const SkBitmap& original, SkScalar scaleX, |
|
136 SkScalar scaleY, const SkBitmap& bitmap); |
|
137 ID* addAndLockMip(const SkBitmap& original, const SkMipMap* mipMap); |
|
138 |
|
139 /** |
|
140 * Given a non-null ID ptr returned by either findAndLock or addAndLock, |
|
141 * this releases the associated resources to be available to be purged |
|
142 * if needed. After this, the cached bitmap should no longer be |
|
143 * referenced by the caller. |
|
144 */ |
|
145 void unlock(ID*); |
|
146 |
|
147 size_t getBytesUsed() const { return fBytesUsed; } |
|
148 size_t getByteLimit() const { return fByteLimit; } |
|
149 |
|
150 /** |
|
151 * Set the maximum number of bytes available to this cache. If the current |
|
152 * cache exceeds this new value, it will be purged to try to fit within |
|
153 * this new limit. |
|
154 */ |
|
155 size_t setByteLimit(size_t newLimit); |
|
156 |
|
157 SkBitmap::Allocator* allocator() const { return fAllocator; }; |
|
158 |
|
159 /** |
|
160 * Call SkDebugf() with diagnostic information about the state of the cache |
|
161 */ |
|
162 void dump() const; |
|
163 |
|
164 public: |
|
165 struct Rec; |
|
166 struct Key; |
|
167 private: |
|
168 Rec* fHead; |
|
169 Rec* fTail; |
|
170 |
|
171 class Hash; |
|
172 Hash* fHash; |
|
173 |
|
174 DiscardableFactory fDiscardableFactory; |
|
175 // the allocator is NULL or one that matches discardables |
|
176 SkBitmap::Allocator* fAllocator; |
|
177 |
|
178 size_t fBytesUsed; |
|
179 size_t fByteLimit; |
|
180 int fCount; |
|
181 |
|
182 Rec* findAndLock(uint32_t generationID, SkScalar sx, SkScalar sy, |
|
183 const SkIRect& bounds); |
|
184 Rec* findAndLock(const Key& key); |
|
185 ID* addAndLock(Rec* rec); |
|
186 |
|
187 void purgeRec(Rec*); |
|
188 void purgeAsNeeded(); |
|
189 |
|
190 // linklist management |
|
191 void moveToHead(Rec*); |
|
192 void addToHead(Rec*); |
|
193 void detach(Rec*); |
|
194 |
|
195 void init(); // called by constructors |
|
196 |
|
197 #ifdef SK_DEBUG |
|
198 void validate() const; |
|
199 #else |
|
200 void validate() const {} |
|
201 #endif |
|
202 }; |
|
203 #endif |