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 DECLARE_SKMESSAGEBUS_MESSAGE(GrPictureDeletedMessage); | 12 DECLARE_SKMESSAGEBUS_MESSAGE(GrPictureDeletedMessage); |
13 | 13 |
14 #ifdef SK_DEBUG | 14 #ifdef SK_DEBUG |
15 void GrCachedLayer::validate(const GrTexture* backingTexture) const { | 15 void GrCachedLayer::validate(const GrTexture* backingTexture) const { |
16 SkASSERT(SK_InvalidGenID != fKey.pictureID()); | 16 SkASSERT(SK_InvalidGenID != fKey.pictureID()); |
17 SkASSERT(fKey.start() >= 0); | 17 SkASSERT(fKey.start() >= 0); |
18 | 18 |
19 | |
20 if (fTexture) { | 19 if (fTexture) { |
21 // If the layer is in some texture then it must occupy some rectangle | 20 // If the layer is in some texture then it must occupy some rectangle |
22 SkASSERT(!fRect.isEmpty()); | 21 SkASSERT(!fRect.isEmpty()); |
23 if (!this->isAtlased()) { | 22 if (!this->isAtlased()) { |
24 // If it isn't atlased then the rectangle should start at the origin | 23 // If it isn't atlased then the rectangle should start at the origin |
25 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); | 24 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); |
26 } | 25 } |
27 } else { | 26 } else { |
28 SkASSERT(fRect.isEmpty()); | 27 SkASSERT(fRect.isEmpty()); |
29 SkASSERT(NULL == fPlot); | 28 SkASSERT(NULL == fPlot); |
30 SkASSERT(!fLocked); // layers without a texture cannot be locked | 29 SkASSERT(!fLocked); // layers without a texture cannot be locked |
31 } | 30 } |
32 | 31 |
33 if (fPlot) { | 32 if (fPlot) { |
34 // If a layer has a plot (i.e., is atlased) then it must point to | 33 // If a layer has a plot (i.e., is atlased) then it must point to |
35 // the backing texture. Additionally, its rect should be non-empty. | 34 // the backing texture. Additionally, its rect should be non-empty. |
36 SkASSERT(fTexture && backingTexture == fTexture); | 35 SkASSERT(fTexture && backingTexture == fTexture); |
37 SkASSERT(!fRect.isEmpty()); | 36 SkASSERT(!fRect.isEmpty()); |
38 } | 37 } |
39 | 38 |
40 if (fLocked) { | 39 if (fLocked) { |
41 // If a layer is locked it must have a texture (though it need not be | 40 // If a layer is locked it must have a texture (though it need not be |
42 // the atlas-backing texture) and occupy some space. | 41 // the atlas-backing texture) and occupy some space. |
43 SkASSERT(fTexture); | 42 SkASSERT(fTexture); |
44 SkASSERT(!fRect.isEmpty()); | 43 SkASSERT(!fRect.isEmpty()); |
45 } | 44 } |
| 45 |
| 46 // Unfortunately there is a brief time where a layer can be locked |
| 47 // but not used, so we can only check the "used implies locked" |
| 48 // invariant. |
| 49 if (fUses > 0) { |
| 50 SkASSERT(fLocked); |
| 51 } else { |
| 52 SkASSERT(0 == fUses); |
| 53 } |
46 } | 54 } |
47 | 55 |
48 class GrAutoValidateLayer : ::SkNoncopyable { | 56 class GrAutoValidateLayer : ::SkNoncopyable { |
49 public: | 57 public: |
50 GrAutoValidateLayer(GrTexture* backingTexture, const GrCachedLayer* layer) | 58 GrAutoValidateLayer(GrTexture* backingTexture, const GrCachedLayer* layer) |
51 : fBackingTexture(backingTexture) | 59 : fBackingTexture(backingTexture) |
52 , fLayer(layer) { | 60 , fLayer(layer) { |
53 if (fLayer) { | 61 if (fLayer) { |
54 fLayer->validate(backingTexture); | 62 fLayer->validate(backingTexture); |
55 } | 63 } |
(...skipping 18 matching lines...) Expand all Loading... |
74 : fContext(context) { | 82 : fContext(context) { |
75 this->initAtlas(); | 83 this->initAtlas(); |
76 memset(fPlotLocks, 0, sizeof(fPlotLocks)); | 84 memset(fPlotLocks, 0, sizeof(fPlotLocks)); |
77 } | 85 } |
78 | 86 |
79 GrLayerCache::~GrLayerCache() { | 87 GrLayerCache::~GrLayerCache() { |
80 | 88 |
81 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); | 89 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
82 for (; !iter.done(); ++iter) { | 90 for (; !iter.done(); ++iter) { |
83 GrCachedLayer* layer = &(*iter); | 91 GrCachedLayer* layer = &(*iter); |
| 92 SkASSERT(0 == layer->uses()); |
84 this->unlock(layer); | 93 this->unlock(layer); |
85 SkDELETE(layer); | 94 SkDELETE(layer); |
86 } | 95 } |
87 | 96 |
88 // The atlas only lets go of its texture when the atlas is deleted. | 97 // The atlas only lets go of its texture when the atlas is deleted. |
89 fAtlas.free(); | 98 fAtlas.free(); |
90 } | 99 } |
91 | 100 |
92 void GrLayerCache::initAtlas() { | 101 void GrLayerCache::initAtlas() { |
93 SkASSERT(NULL == fAtlas.get()); | 102 SkASSERT(NULL == fAtlas.get()); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 SkASSERT(layer->rect().height() == desc.fHeight); | 170 SkASSERT(layer->rect().height() == desc.fHeight); |
162 } | 171 } |
163 #endif | 172 #endif |
164 return false; | 173 return false; |
165 } | 174 } |
166 | 175 |
167 if (layer->isAtlased()) { | 176 if (layer->isAtlased()) { |
168 // Hooray it is still in the atlas - make sure it stays there | 177 // Hooray it is still in the atlas - make sure it stays there |
169 SkASSERT(!dontAtlas); | 178 SkASSERT(!dontAtlas); |
170 layer->setLocked(true); | 179 layer->setLocked(true); |
171 fPlotLocks[layer->plot()->id()]++; | 180 this->incPlotLock(layer->plot()->id()); |
172 return false; | 181 return false; |
173 } else if (!dontAtlas && PlausiblyAtlasable(desc.fWidth, desc.fHeight)) { | 182 } else if (!dontAtlas && PlausiblyAtlasable(desc.fWidth, desc.fHeight)) { |
174 // Not in the atlas - will it fit? | 183 // Not in the atlas - will it fit? |
175 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 184 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
176 if (NULL == pictInfo) { | 185 if (NULL == pictInfo) { |
177 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); | 186 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); |
178 fPictureHash.add(pictInfo); | 187 fPictureHash.add(pictInfo); |
179 } | 188 } |
180 | 189 |
181 SkIPoint16 loc; | 190 SkIPoint16 loc; |
182 for (int i = 0; i < 2; ++i) { // extra pass in case we fail to add but a
re able to purge | 191 for (int i = 0; i < 2; ++i) { // extra pass in case we fail to add but a
re able to purge |
183 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, | 192 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, |
184 desc.fWidth, desc.fHeight, | 193 desc.fWidth, desc.fHeight, |
185 NULL, &loc); | 194 NULL, &loc); |
186 // addToAtlas can allocate the backing texture | 195 // addToAtlas can allocate the backing texture |
187 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); | 196 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); |
188 if (plot) { | 197 if (plot) { |
189 // The layer was successfully added to the atlas | 198 // The layer was successfully added to the atlas |
190 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, | 199 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, |
191 SkToS16(desc.fWidth), | 200 SkToS16(desc.fWidth), |
192 SkToS16(desc.fHeight)); | 201 SkToS16(desc.fHeight)); |
193 layer->setTexture(fAtlas->getTexture(), bounds); | 202 layer->setTexture(fAtlas->getTexture(), bounds); |
194 layer->setPlot(plot); | 203 layer->setPlot(plot); |
195 layer->setLocked(true); | 204 layer->setLocked(true); |
196 fPlotLocks[layer->plot()->id()]++; | 205 this->incPlotLock(layer->plot()->id()); |
197 return true; | 206 return true; |
198 } | 207 } |
199 | 208 |
200 // The layer was rejected by the atlas (even though we know it is | 209 // The layer was rejected by the atlas (even though we know it is |
201 // plausibly atlas-able). See if a plot can be purged and try again. | 210 // plausibly atlas-able). See if a plot can be purged and try again. |
202 if (!this->purgePlot()) { | 211 if (!this->purgePlot()) { |
203 break; // We weren't able to purge any plots | 212 break; // We weren't able to purge any plots |
204 } | 213 } |
205 } | 214 } |
206 } | 215 } |
(...skipping 13 matching lines...) Expand all Loading... |
220 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) | 229 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) |
221 | 230 |
222 if (NULL == layer || !layer->locked()) { | 231 if (NULL == layer || !layer->locked()) { |
223 // invalid or not locked | 232 // invalid or not locked |
224 return; | 233 return; |
225 } | 234 } |
226 | 235 |
227 if (layer->isAtlased()) { | 236 if (layer->isAtlased()) { |
228 const int plotID = layer->plot()->id(); | 237 const int plotID = layer->plot()->id(); |
229 | 238 |
230 SkASSERT(fPlotLocks[plotID] > 0); | 239 this->decPlotLock(plotID); |
231 fPlotLocks[plotID]--; | |
232 // At this point we could aggressively clear out un-locked plots but | 240 // At this point we could aggressively clear out un-locked plots but |
233 // by delaying we may be able to reuse some of the atlased layers later. | 241 // by delaying we may be able to reuse some of the atlased layers later. |
234 #if DISABLE_CACHING | 242 #if DISABLE_CACHING |
235 // This testing code aggressively removes the atlased layers. This | 243 // This testing code aggressively removes the atlased layers. This |
236 // can be used to separate the performance contribution of less | 244 // can be used to separate the performance contribution of less |
237 // render target pingponging from that due to the re-use of cached layer
s | 245 // render target pingponging from that due to the re-use of cached layer
s |
238 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 246 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
239 SkASSERT(pictInfo); | 247 SkASSERT(pictInfo); |
240 | 248 |
241 GrAtlas::RemovePlot(&pictInfo->fPlotUsage, layer->plot()); | 249 GrAtlas::RemovePlot(&pictInfo->fPlotUsage, layer->plot()); |
(...skipping 21 matching lines...) Expand all Loading... |
263 layer->validate(fAtlas->getTexture()); | 271 layer->validate(fAtlas->getTexture()); |
264 | 272 |
265 const GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 273 const GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
266 if (pictInfo) { | 274 if (pictInfo) { |
267 // In aggressive cleanup mode a picture info should only exist if | 275 // In aggressive cleanup mode a picture info should only exist if |
268 // it has some atlased layers | 276 // it has some atlased layers |
269 #if !DISABLE_CACHING | 277 #if !DISABLE_CACHING |
270 SkASSERT(!pictInfo->fPlotUsage.isEmpty()); | 278 SkASSERT(!pictInfo->fPlotUsage.isEmpty()); |
271 #endif | 279 #endif |
272 } else { | 280 } else { |
273 // If there is no picture info for this layer then all of its | 281 // If there is no picture info for this picture then all of its |
274 // layers should be non-atlased. | 282 // layers should be non-atlased. |
275 SkASSERT(!layer->isAtlased()); | 283 SkASSERT(!layer->isAtlased()); |
276 } | 284 } |
277 | 285 |
278 if (layer->plot()) { | 286 if (layer->plot()) { |
279 SkASSERT(pictInfo); | 287 SkASSERT(pictInfo); |
280 SkASSERT(pictInfo->fPictureID == layer->pictureID()); | 288 SkASSERT(pictInfo->fPictureID == layer->pictureID()); |
281 | 289 |
282 SkASSERT(pictInfo->fPlotUsage.contains(layer->plot())); | 290 SkASSERT(pictInfo->fPlotUsage.contains(layer->plot())); |
283 | 291 |
(...skipping 30 matching lines...) Expand all Loading... |
314 SkTDArray<GrCachedLayer*> toBeRemoved; | 322 SkTDArray<GrCachedLayer*> toBeRemoved; |
315 | 323 |
316 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); | 324 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
317 for (; !iter.done(); ++iter) { | 325 for (; !iter.done(); ++iter) { |
318 if (pictureID == (*iter).pictureID()) { | 326 if (pictureID == (*iter).pictureID()) { |
319 *toBeRemoved.append() = &(*iter); | 327 *toBeRemoved.append() = &(*iter); |
320 } | 328 } |
321 } | 329 } |
322 | 330 |
323 for (int i = 0; i < toBeRemoved.count(); ++i) { | 331 for (int i = 0; i < toBeRemoved.count(); ++i) { |
| 332 SkASSERT(0 == toBeRemoved[i]->uses()); |
324 this->unlock(toBeRemoved[i]); | 333 this->unlock(toBeRemoved[i]); |
325 fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); | 334 fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); |
326 SkDELETE(toBeRemoved[i]); | 335 SkDELETE(toBeRemoved[i]); |
327 } | 336 } |
328 | 337 |
329 GrPictureInfo* pictInfo = fPictureHash.find(pictureID); | 338 GrPictureInfo* pictInfo = fPictureHash.find(pictureID); |
330 if (pictInfo) { | 339 if (pictInfo) { |
331 fPictureHash.remove(pictureID); | 340 fPictureHash.remove(pictureID); |
332 SkDELETE(pictInfo); | 341 SkDELETE(pictInfo); |
333 } | 342 } |
(...skipping 25 matching lines...) Expand all Loading... |
359 SkTDArray<GrCachedLayer*> toBeRemoved; | 368 SkTDArray<GrCachedLayer*> toBeRemoved; |
360 | 369 |
361 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); | 370 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
362 for (; !iter.done(); ++iter) { | 371 for (; !iter.done(); ++iter) { |
363 if (plot == (*iter).plot()) { | 372 if (plot == (*iter).plot()) { |
364 *toBeRemoved.append() = &(*iter); | 373 *toBeRemoved.append() = &(*iter); |
365 } | 374 } |
366 } | 375 } |
367 | 376 |
368 for (int i = 0; i < toBeRemoved.count(); ++i) { | 377 for (int i = 0; i < toBeRemoved.count(); ++i) { |
| 378 SkASSERT(0 == toBeRemoved[i]->uses()); |
369 SkASSERT(!toBeRemoved[i]->locked()); | 379 SkASSERT(!toBeRemoved[i]->locked()); |
370 | 380 |
371 uint32_t pictureIDToRemove = toBeRemoved[i]->pictureID(); | 381 uint32_t pictureIDToRemove = toBeRemoved[i]->pictureID(); |
372 | 382 |
373 // Aggressively remove layers and, if it becomes totally uncached, delet
e the picture info | 383 // Aggressively remove layers and, if it becomes totally uncached, delet
e the picture info |
374 fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); | 384 fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); |
375 SkDELETE(toBeRemoved[i]); | 385 SkDELETE(toBeRemoved[i]); |
376 | 386 |
377 GrPictureInfo* pictInfo = fPictureHash.find(pictureIDToRemove); | 387 GrPictureInfo* pictInfo = fPictureHash.find(pictureIDToRemove); |
378 if (pictInfo) { | 388 if (pictInfo) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 | 427 |
418 void GrLayerCache::processDeletedPictures() { | 428 void GrLayerCache::processDeletedPictures() { |
419 SkTDArray<GrPictureDeletedMessage> deletedPictures; | 429 SkTDArray<GrPictureDeletedMessage> deletedPictures; |
420 fPictDeletionInbox.poll(&deletedPictures); | 430 fPictDeletionInbox.poll(&deletedPictures); |
421 | 431 |
422 for (int i = 0; i < deletedPictures.count(); i++) { | 432 for (int i = 0; i < deletedPictures.count(); i++) { |
423 this->purge(deletedPictures[i].pictureID); | 433 this->purge(deletedPictures[i].pictureID); |
424 } | 434 } |
425 } | 435 } |
426 | 436 |
OLD | NEW |