OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 #include "GrAtlas.h" | 8 #include "GrAtlas.h" |
9 #include "GrGpu.h" | 9 #include "GrGpu.h" |
10 #include "GrLayerCache.h" | 10 #include "GrLayerCache.h" |
11 | 11 |
12 /** | |
13 * PictureLayerKey just wraps a saveLayer's id in a picture for GrTHashTable. | |
14 */ | |
15 class GrLayerCache::PictureLayerKey { | |
16 public: | |
17 PictureLayerKey(uint32_t pictureID, int layerID) | |
18 : fPictureID(pictureID) | |
19 , fLayerID(layerID) { | |
20 } | |
21 | |
22 uint32_t pictureID() const { return fPictureID; } | |
23 int layerID() const { return fLayerID; } | |
24 | |
25 uint32_t getHash() const { return (fPictureID << 16) | fLayerID; } | |
26 | |
27 static bool LessThan(const GrCachedLayer& layer, const PictureLayerKey& key)
{ | |
28 if (layer.pictureID() == key.pictureID()) { | |
29 return layer.layerID() < key.layerID(); | |
30 } | |
31 | |
32 return layer.pictureID() < key.pictureID(); | |
33 } | |
34 | |
35 static bool Equals(const GrCachedLayer& layer, const PictureLayerKey& key) { | |
36 return layer.pictureID() == key.pictureID() && layer.layerID() == key.la
yerID(); | |
37 } | |
38 | |
39 private: | |
40 uint32_t fPictureID; | |
41 int fLayerID; | |
42 }; | |
43 | |
44 /** | |
45 * PictureKey just wraps a picture's unique ID for GrTHashTable. It is used to | |
46 * look up a picture's GrPictureInfo (i.e., its GrPlot usage). | |
47 */ | |
48 class GrLayerCache::PictureKey { | |
49 public: | |
50 PictureKey(uint32_t pictureID) : fPictureID(pictureID) { } | |
51 | |
52 uint32_t pictureID() const { return fPictureID; } | |
53 | |
54 uint32_t getHash() const { return fPictureID; } | |
55 | |
56 static bool LessThan(const GrPictureInfo& pictInfo, const PictureKey& key) { | |
57 return pictInfo.fPictureID < key.pictureID(); | |
58 } | |
59 | |
60 static bool Equals(const GrPictureInfo& pictInfo, const PictureKey& key) { | |
61 return pictInfo.fPictureID == key.pictureID(); | |
62 | |
63 } | |
64 | |
65 private: | |
66 uint32_t fPictureID; | |
67 }; | |
68 | |
69 #ifdef SK_DEBUG | 12 #ifdef SK_DEBUG |
70 void GrCachedLayer::validate(const GrTexture* backingTexture) const { | 13 void GrCachedLayer::validate(const GrTexture* backingTexture) const { |
71 SkASSERT(SK_InvalidGenID != fPictureID); | 14 SkASSERT(SK_InvalidGenID != fKey.getPictureID()); |
72 SkASSERT(-1 != fLayerID); | 15 SkASSERT(-1 != fKey.getLayerID()); |
| 16 |
73 | 17 |
74 if (NULL != fTexture) { | 18 if (NULL != fTexture) { |
75 // If the layer is in some texture then it must occupy some rectangle | 19 // If the layer is in some texture then it must occupy some rectangle |
76 SkASSERT(!fRect.isEmpty()); | 20 SkASSERT(!fRect.isEmpty()); |
77 if (!this->isAtlased()) { | 21 if (!this->isAtlased()) { |
78 // If it isn't atlased then the rectangle should start at the origin | 22 // If it isn't atlased then the rectangle should start at the origin |
79 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); | 23 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); |
80 } | 24 } |
81 } else { | 25 } else { |
82 SkASSERT(fRect.isEmpty()); | 26 SkASSERT(fRect.isEmpty()); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 const GrCachedLayer* fLayer; | 59 const GrCachedLayer* fLayer; |
116 }; | 60 }; |
117 #endif | 61 #endif |
118 | 62 |
119 GrLayerCache::GrLayerCache(GrContext* context) | 63 GrLayerCache::GrLayerCache(GrContext* context) |
120 : fContext(context) { | 64 : fContext(context) { |
121 this->initAtlas(); | 65 this->initAtlas(); |
122 } | 66 } |
123 | 67 |
124 GrLayerCache::~GrLayerCache() { | 68 GrLayerCache::~GrLayerCache() { |
125 SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 69 |
126 for (int i = 0; i < fLayerHash.count(); ++i) { | 70 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
127 this->unlock(layerArray[i]); | 71 for (; !iter.done(); ++iter) { |
| 72 GrCachedLayer* layer = &(*iter); |
| 73 this->unlock(layer); |
| 74 SkDELETE(layer); |
128 } | 75 } |
129 | 76 |
130 fLayerHash.deleteAll(); | |
131 | |
132 // The atlas only lets go of its texture when the atlas is deleted. | 77 // The atlas only lets go of its texture when the atlas is deleted. |
133 fAtlas.free(); | 78 fAtlas.free(); |
134 } | 79 } |
135 | 80 |
136 void GrLayerCache::initAtlas() { | 81 void GrLayerCache::initAtlas() { |
137 static const int kAtlasTextureWidth = 1024; | 82 static const int kAtlasTextureWidth = 1024; |
138 static const int kAtlasTextureHeight = 1024; | 83 static const int kAtlasTextureHeight = 1024; |
139 | 84 |
140 SkASSERT(NULL == fAtlas.get()); | 85 SkASSERT(NULL == fAtlas.get()); |
141 | 86 |
142 // The layer cache only gets 1 plot | 87 // The layer cache only gets 1 plot |
143 SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight)
; | 88 SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight)
; |
144 fAtlas.reset(SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kSkia8888_GrPixelConfi
g, | 89 fAtlas.reset(SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kSkia8888_GrPixelConfi
g, |
145 kRenderTarget_GrTextureFlagBit, | 90 kRenderTarget_GrTextureFlagBit, |
146 textureSize, kNumPlotsX, kNumPlotsY, false
))); | 91 textureSize, kNumPlotsX, kNumPlotsY, false
))); |
147 } | 92 } |
148 | 93 |
149 void GrLayerCache::freeAll() { | 94 void GrLayerCache::freeAll() { |
150 SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 95 |
151 for (int i = 0; i < fLayerHash.count(); ++i) { | 96 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
152 this->unlock(layerArray[i]); | 97 for (; !iter.done(); ++iter) { |
| 98 GrCachedLayer* layer = &(*iter); |
| 99 this->unlock(layer); |
| 100 SkDELETE(layer); |
153 } | 101 } |
154 | 102 fLayerHash.rewind(); |
155 fLayerHash.deleteAll(); | |
156 | 103 |
157 // The atlas only lets go of its texture when the atlas is deleted. | 104 // The atlas only lets go of its texture when the atlas is deleted. |
158 fAtlas.free(); | 105 fAtlas.free(); |
159 // GrLayerCache always assumes an atlas exists so recreate it. The atlas | 106 // GrLayerCache always assumes an atlas exists so recreate it. The atlas |
160 // lazily allocates a replacement texture so reallocating a new | 107 // lazily allocates a replacement texture so reallocating a new |
161 // atlas here won't disrupt a GrContext::contextDestroyed or freeGpuResource
s. | 108 // atlas here won't disrupt a GrContext::contextDestroyed or freeGpuResource
s. |
162 // TODO: Make GrLayerCache lazily allocate the atlas manager? | 109 // TODO: Make GrLayerCache lazily allocate the atlas manager? |
163 this->initAtlas(); | 110 this->initAtlas(); |
164 } | 111 } |
165 | 112 |
166 GrCachedLayer* GrLayerCache::createLayer(const SkPicture* picture, int layerID)
{ | 113 GrCachedLayer* GrLayerCache::createLayer(const SkPicture* picture, int layerID)
{ |
167 SkASSERT(picture->uniqueID() != SK_InvalidGenID); | 114 SkASSERT(picture->uniqueID() != SK_InvalidGenID && layerID >= 0); |
168 | 115 |
169 GrCachedLayer* layer = SkNEW_ARGS(GrCachedLayer, (picture->uniqueID(), layer
ID)); | 116 GrCachedLayer* layer = SkNEW_ARGS(GrCachedLayer, (picture->uniqueID(), layer
ID)); |
170 fLayerHash.insert(PictureLayerKey(picture->uniqueID(), layerID), layer); | 117 fLayerHash.add(layer); |
171 return layer; | 118 return layer; |
172 } | 119 } |
173 | 120 |
174 GrCachedLayer* GrLayerCache::findLayer(const SkPicture* picture, int layerID) { | 121 GrCachedLayer* GrLayerCache::findLayer(const SkPicture* picture, int layerID) { |
175 SkASSERT(picture->uniqueID() != SK_InvalidGenID); | 122 SkASSERT(picture->uniqueID() != SK_InvalidGenID && layerID >= 0); |
176 return fLayerHash.find(PictureLayerKey(picture->uniqueID(), layerID)); | 123 return fLayerHash.find(GrCachedLayer::Key(picture->uniqueID(), layerID)); |
177 } | 124 } |
178 | 125 |
179 GrCachedLayer* GrLayerCache::findLayerOrCreate(const SkPicture* picture, int lay
erID) { | 126 GrCachedLayer* GrLayerCache::findLayerOrCreate(const SkPicture* picture, int lay
erID) { |
180 SkASSERT(picture->uniqueID() != SK_InvalidGenID); | 127 SkASSERT(picture->uniqueID() != SK_InvalidGenID && layerID >= 0); |
181 GrCachedLayer* layer = fLayerHash.find(PictureLayerKey(picture->uniqueID(),
layerID)); | 128 GrCachedLayer* layer = fLayerHash.find(GrCachedLayer::Key(picture->uniqueID(
), layerID)); |
182 if (NULL == layer) { | 129 if (NULL == layer) { |
183 layer = this->createLayer(picture, layerID); | 130 layer = this->createLayer(picture, layerID); |
184 } | 131 } |
185 | 132 |
186 return layer; | 133 return layer; |
187 } | 134 } |
188 | 135 |
189 bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) { | 136 bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) { |
190 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) | 137 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) |
191 | 138 |
192 if (NULL != layer->texture()) { | 139 if (NULL != layer->texture()) { |
193 // This layer is already locked | 140 // This layer is already locked |
194 #ifdef SK_DEBUG | 141 #ifdef SK_DEBUG |
195 if (layer->isAtlased()) { | 142 if (layer->isAtlased()) { |
196 // It claims to be atlased | 143 // It claims to be atlased |
197 SkASSERT(layer->rect().width() == desc.fWidth); | 144 SkASSERT(layer->rect().width() == desc.fWidth); |
198 SkASSERT(layer->rect().height() == desc.fHeight); | 145 SkASSERT(layer->rect().height() == desc.fHeight); |
199 } | 146 } |
200 #endif | 147 #endif |
201 return true; | 148 return true; |
202 } | 149 } |
203 | 150 |
204 #if USE_ATLAS | 151 #if USE_ATLAS |
205 { | 152 { |
206 GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(layer->pictureID(
))); | 153 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
207 if (NULL == pictInfo) { | 154 if (NULL == pictInfo) { |
208 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); | 155 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); |
209 fPictureHash.insert(PictureKey(layer->pictureID()), pictInfo); | 156 fPictureHash.add(pictInfo); |
210 } | 157 } |
211 | 158 |
212 SkIPoint16 loc; | 159 SkIPoint16 loc; |
213 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, | 160 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, |
214 desc.fWidth, desc.fHeight, | 161 desc.fWidth, desc.fHeight, |
215 NULL, &loc); | 162 NULL, &loc); |
216 // addToAtlas can allocate the backing texture | 163 // addToAtlas can allocate the backing texture |
217 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); | 164 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); |
218 if (NULL != plot) { | 165 if (NULL != plot) { |
219 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, | 166 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, |
(...skipping 16 matching lines...) Expand all Loading... |
236 void GrLayerCache::unlock(GrCachedLayer* layer) { | 183 void GrLayerCache::unlock(GrCachedLayer* layer) { |
237 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) | 184 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) |
238 | 185 |
239 if (NULL == layer || NULL == layer->texture()) { | 186 if (NULL == layer || NULL == layer->texture()) { |
240 return; | 187 return; |
241 } | 188 } |
242 | 189 |
243 if (layer->isAtlased()) { | 190 if (layer->isAtlased()) { |
244 SkASSERT(layer->texture() == fAtlas->getTexture()); | 191 SkASSERT(layer->texture() == fAtlas->getTexture()); |
245 | 192 |
246 GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(layer->pictureID(
))); | 193 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
247 SkASSERT(NULL != pictInfo); | 194 SkASSERT(NULL != pictInfo); |
248 pictInfo->fPlotUsage.isEmpty(); // just to silence compiler warnings for
the time being | 195 pictInfo->fPlotUsage.isEmpty(); // just to silence compiler warnings for
the time being |
249 | 196 |
250 // TODO: purging from atlas goes here | 197 // TODO: purging from atlas goes here |
251 } else { | 198 } else { |
252 fContext->unlockScratchTexture(layer->texture()); | 199 fContext->unlockScratchTexture(layer->texture()); |
253 layer->setTexture(NULL, GrIRect16::MakeEmpty()); | 200 layer->setTexture(NULL, GrIRect16::MakeEmpty()); |
254 } | 201 } |
255 } | 202 } |
256 | 203 |
257 #ifdef SK_DEBUG | 204 #ifdef SK_DEBUG |
258 void GrLayerCache::validate() const { | 205 void GrLayerCache::validate() const { |
259 const SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 206 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::ConstIter iter(&fLayerHas
h); |
260 for (int i = 0; i < fLayerHash.count(); ++i) { | 207 for (; !iter.done(); ++iter) { |
261 layerArray[i]->validate(fAtlas->getTexture()); | 208 (*iter).validate(fAtlas->getTexture()); |
262 } | 209 } |
263 } | 210 } |
264 | 211 |
265 class GrAutoValidateCache : ::SkNoncopyable { | 212 class GrAutoValidateCache : ::SkNoncopyable { |
266 public: | 213 public: |
267 explicit GrAutoValidateCache(GrLayerCache* cache) | 214 explicit GrAutoValidateCache(GrLayerCache* cache) |
268 : fCache(cache) { | 215 : fCache(cache) { |
269 fCache->validate(); | 216 fCache->validate(); |
270 } | 217 } |
271 ~GrAutoValidateCache() { | 218 ~GrAutoValidateCache() { |
272 fCache->validate(); | 219 fCache->validate(); |
273 } | 220 } |
274 private: | 221 private: |
275 GrLayerCache* fCache; | 222 GrLayerCache* fCache; |
276 }; | 223 }; |
277 #endif | 224 #endif |
278 | 225 |
279 void GrLayerCache::purge(const SkPicture* picture) { | 226 void GrLayerCache::purge(const SkPicture* picture) { |
280 SkDEBUGCODE(GrAutoValidateCache avc(this);) | 227 SkDEBUGCODE(GrAutoValidateCache avc(this);) |
281 | 228 |
282 // This is somewhat of an abuse of GrTHashTable. We need to find all the | 229 // We need to find all the layers associated with 'picture' and remove them. |
283 // layers associated with 'picture' but the usual hash calls only look for | |
284 // exact key matches. This code peeks into the hash table's innards to | |
285 // find all the 'picture'-related layers. | |
286 // TODO: use a different data structure for the layer hash? | |
287 SkTDArray<GrCachedLayer*> toBeRemoved; | 230 SkTDArray<GrCachedLayer*> toBeRemoved; |
288 | 231 |
289 const SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 232 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
290 for (int i = 0; i < fLayerHash.count(); ++i) { | 233 for (; !iter.done(); ++iter) { |
291 if (picture->uniqueID() == layerArray[i]->pictureID()) { | 234 if (picture->uniqueID() == (*iter).pictureID()) { |
292 *toBeRemoved.append() = layerArray[i]; | 235 *toBeRemoved.append() = &(*iter); |
293 } | 236 } |
294 } | 237 } |
295 | 238 |
296 for (int i = 0; i < toBeRemoved.count(); ++i) { | 239 for (int i = 0; i < toBeRemoved.count(); ++i) { |
297 this->unlock(toBeRemoved[i]); | 240 this->unlock(toBeRemoved[i]); |
298 | 241 fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); |
299 PictureLayerKey key(picture->uniqueID(), toBeRemoved[i]->layerID()); | |
300 fLayerHash.remove(key, toBeRemoved[i]); | |
301 SkDELETE(toBeRemoved[i]); | 242 SkDELETE(toBeRemoved[i]); |
302 } | 243 } |
303 | 244 |
304 GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(picture->uniqueID()))
; | 245 GrPictureInfo* pictInfo = fPictureHash.find(picture->uniqueID()); |
305 if (NULL != pictInfo) { | 246 if (NULL != pictInfo) { |
306 fPictureHash.remove(PictureKey(picture->uniqueID()), pictInfo); | 247 fPictureHash.remove(picture->uniqueID()); |
307 SkDELETE(pictInfo); | 248 SkDELETE(pictInfo); |
308 } | 249 } |
309 } | 250 } |
OLD | NEW |