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" |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 } | 74 } |
75 | 75 |
76 private: | 76 private: |
77 const GrTexture* fBackingTexture; | 77 const GrTexture* fBackingTexture; |
78 const GrCachedLayer* fLayer; | 78 const GrCachedLayer* fLayer; |
79 }; | 79 }; |
80 #endif | 80 #endif |
81 | 81 |
82 GrLayerCache::GrLayerCache(GrContext* context) | 82 GrLayerCache::GrLayerCache(GrContext* context) |
83 : fContext(context) { | 83 : fContext(context) { |
| 84 this->initAtlas(); |
84 memset(fPlotLocks, 0, sizeof(fPlotLocks)); | 85 memset(fPlotLocks, 0, sizeof(fPlotLocks)); |
85 } | 86 } |
86 | 87 |
87 GrLayerCache::~GrLayerCache() { | 88 GrLayerCache::~GrLayerCache() { |
88 | 89 |
89 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); | 90 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
90 for (; !iter.done(); ++iter) { | 91 for (; !iter.done(); ++iter) { |
91 GrCachedLayer* layer = &(*iter); | 92 GrCachedLayer* layer = &(*iter); |
92 SkASSERT(0 == layer->uses()); | 93 SkASSERT(0 == layer->uses()); |
93 this->unlock(layer); | 94 this->unlock(layer); |
(...skipping 18 matching lines...) Expand all Loading... |
112 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); | 113 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
113 for (; !iter.done(); ++iter) { | 114 for (; !iter.done(); ++iter) { |
114 GrCachedLayer* layer = &(*iter); | 115 GrCachedLayer* layer = &(*iter); |
115 this->unlock(layer); | 116 this->unlock(layer); |
116 SkDELETE(layer); | 117 SkDELETE(layer); |
117 } | 118 } |
118 fLayerHash.rewind(); | 119 fLayerHash.rewind(); |
119 | 120 |
120 // The atlas only lets go of its texture when the atlas is deleted. | 121 // The atlas only lets go of its texture when the atlas is deleted. |
121 fAtlas.free(); | 122 fAtlas.free(); |
| 123 // GrLayerCache always assumes an atlas exists so recreate it. The atlas |
| 124 // lazily allocates a replacement texture so reallocating a new |
| 125 // atlas here won't disrupt a GrContext::abandonContext or freeGpuResources. |
| 126 // TODO: Make GrLayerCache lazily allocate the atlas manager? |
| 127 this->initAtlas(); |
122 } | 128 } |
123 | 129 |
124 GrCachedLayer* GrLayerCache::createLayer(uint32_t pictureID, | 130 GrCachedLayer* GrLayerCache::createLayer(uint32_t pictureID, |
125 int start, int stop, | 131 int start, int stop, |
126 const SkIRect& bounds, | 132 const SkIRect& bounds, |
127 const SkMatrix& ctm, | 133 const SkMatrix& ctm, |
128 const SkPaint* paint) { | 134 const SkPaint* paint) { |
129 SkASSERT(pictureID != SK_InvalidGenID && start >= 0 && stop > 0); | 135 SkASSERT(pictureID != SK_InvalidGenID && start >= 0 && stop > 0); |
130 | 136 |
131 GrCachedLayer* layer = SkNEW_ARGS(GrCachedLayer, (pictureID, start, stop, bo
unds, ctm, paint)); | 137 GrCachedLayer* layer = SkNEW_ARGS(GrCachedLayer, (pictureID, start, stop, bo
unds, ctm, paint)); |
(...skipping 25 matching lines...) Expand all Loading... |
157 | 163 |
158 bool GrLayerCache::tryToAtlas(GrCachedLayer* layer, | 164 bool GrLayerCache::tryToAtlas(GrCachedLayer* layer, |
159 const GrTextureDesc& desc, | 165 const GrTextureDesc& desc, |
160 bool* needsRendering) { | 166 bool* needsRendering) { |
161 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) | 167 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) |
162 | 168 |
163 SkASSERT(PlausiblyAtlasable(desc.fWidth, desc.fHeight)); | 169 SkASSERT(PlausiblyAtlasable(desc.fWidth, desc.fHeight)); |
164 | 170 |
165 if (layer->locked()) { | 171 if (layer->locked()) { |
166 // This layer is already locked | 172 // This layer is already locked |
167 SkASSERT(fAtlas); | |
168 SkASSERT(layer->isAtlased()); | 173 SkASSERT(layer->isAtlased()); |
169 SkASSERT(layer->rect().width() == desc.fWidth); | 174 SkASSERT(layer->rect().width() == desc.fWidth); |
170 SkASSERT(layer->rect().height() == desc.fHeight); | 175 SkASSERT(layer->rect().height() == desc.fHeight); |
171 *needsRendering = false; | 176 *needsRendering = false; |
172 return true; | 177 return true; |
173 } | 178 } |
174 | 179 |
175 if (layer->isAtlased()) { | 180 if (layer->isAtlased()) { |
176 SkASSERT(fAtlas); | |
177 // Hooray it is still in the atlas - make sure it stays there | 181 // Hooray it is still in the atlas - make sure it stays there |
178 layer->setLocked(true); | 182 layer->setLocked(true); |
179 this->incPlotLock(layer->plot()->id()); | 183 this->incPlotLock(layer->plot()->id()); |
180 *needsRendering = false; | 184 *needsRendering = false; |
181 return true; | 185 return true; |
182 } else { | 186 } else { |
183 if (!fAtlas) { | |
184 this->initAtlas(); | |
185 if (!fAtlas) { | |
186 return false; | |
187 } | |
188 } | |
189 // Not in the atlas - will it fit? | 187 // Not in the atlas - will it fit? |
190 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 188 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
191 if (NULL == pictInfo) { | 189 if (NULL == pictInfo) { |
192 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); | 190 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); |
193 fPictureHash.add(pictInfo); | 191 fPictureHash.add(pictInfo); |
194 } | 192 } |
195 | 193 |
196 SkIPoint16 loc; | 194 SkIPoint16 loc; |
197 for (int i = 0; i < 2; ++i) { // extra pass in case we fail to add but a
re able to purge | 195 for (int i = 0; i < 2; ++i) { // extra pass in case we fail to add but a
re able to purge |
198 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, | 196 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 // invalid or not locked | 249 // invalid or not locked |
252 return; | 250 return; |
253 } | 251 } |
254 | 252 |
255 if (layer->isAtlased()) { | 253 if (layer->isAtlased()) { |
256 const int plotID = layer->plot()->id(); | 254 const int plotID = layer->plot()->id(); |
257 | 255 |
258 this->decPlotLock(plotID); | 256 this->decPlotLock(plotID); |
259 // At this point we could aggressively clear out un-locked plots but | 257 // At this point we could aggressively clear out un-locked plots but |
260 // by delaying we may be able to reuse some of the atlased layers later. | 258 // by delaying we may be able to reuse some of the atlased layers later. |
261 #if !GR_CACHE_HOISTED_LAYERS | 259 #if DISABLE_CACHING |
262 // This testing code aggressively removes the atlased layers. This | 260 // This testing code aggressively removes the atlased layers. This |
263 // can be used to separate the performance contribution of less | 261 // can be used to separate the performance contribution of less |
264 // render target pingponging from that due to the re-use of cached layer
s | 262 // render target pingponging from that due to the re-use of cached layer
s |
265 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 263 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
266 SkASSERT(pictInfo); | 264 SkASSERT(pictInfo); |
267 | 265 |
268 GrAtlas::RemovePlot(&pictInfo->fPlotUsage, layer->plot()); | 266 GrAtlas::RemovePlot(&pictInfo->fPlotUsage, layer->plot()); |
269 | 267 |
270 layer->setPlot(NULL); | 268 layer->setPlot(NULL); |
271 layer->setTexture(NULL, GrIRect16::MakeEmpty()); | 269 layer->setTexture(NULL, GrIRect16::MakeEmpty()); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 | 348 |
351 GrPictureInfo* pictInfo = fPictureHash.find(pictureID); | 349 GrPictureInfo* pictInfo = fPictureHash.find(pictureID); |
352 if (pictInfo) { | 350 if (pictInfo) { |
353 fPictureHash.remove(pictureID); | 351 fPictureHash.remove(pictureID); |
354 SkDELETE(pictInfo); | 352 SkDELETE(pictInfo); |
355 } | 353 } |
356 } | 354 } |
357 | 355 |
358 bool GrLayerCache::purgePlot() { | 356 bool GrLayerCache::purgePlot() { |
359 SkDEBUGCODE(GrAutoValidateCache avc(this);) | 357 SkDEBUGCODE(GrAutoValidateCache avc(this);) |
360 SkASSERT(fAtlas); | |
361 | 358 |
362 GrAtlas::PlotIter iter; | 359 GrAtlas::PlotIter iter; |
363 GrPlot* plot; | 360 GrPlot* plot; |
364 for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder); | 361 for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder); |
365 plot; | 362 plot; |
366 plot = iter.prev()) { | 363 plot = iter.prev()) { |
367 if (fPlotLocks[plot->id()] > 0) { | 364 if (fPlotLocks[plot->id()] > 0) { |
368 continue; | 365 continue; |
369 } | 366 } |
370 | 367 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 if (pictInfo->fPlotUsage.isEmpty()) { | 402 if (pictInfo->fPlotUsage.isEmpty()) { |
406 fPictureHash.remove(pictInfo->fPictureID); | 403 fPictureHash.remove(pictInfo->fPictureID); |
407 SkDELETE(pictInfo); | 404 SkDELETE(pictInfo); |
408 } | 405 } |
409 } | 406 } |
410 } | 407 } |
411 | 408 |
412 plot->resetRects(); | 409 plot->resetRects(); |
413 } | 410 } |
414 | 411 |
415 #if !GR_CACHE_HOISTED_LAYERS | |
416 void GrLayerCache::purgeAll() { | 412 void GrLayerCache::purgeAll() { |
417 if (!fAtlas) { | |
418 return; | |
419 } | |
420 | |
421 GrAtlas::PlotIter iter; | 413 GrAtlas::PlotIter iter; |
422 GrPlot* plot; | 414 GrPlot* plot; |
423 for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder); | 415 for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder); |
424 plot; | 416 plot; |
425 plot = iter.prev()) { | 417 plot = iter.prev()) { |
426 SkASSERT(0 == fPlotLocks[plot->id()]); | 418 SkASSERT(0 == fPlotLocks[plot->id()]); |
427 | 419 |
428 this->purgePlot(plot); | 420 this->purgePlot(plot); |
429 } | 421 } |
430 | |
431 fContext->discardRenderTarget(fAtlas->getTexture()->asRenderTarget()); | |
432 } | 422 } |
433 #endif | |
434 | 423 |
435 class GrPictureDeletionListener : public SkPicture::DeletionListener { | 424 class GrPictureDeletionListener : public SkPicture::DeletionListener { |
436 virtual void onDeletion(uint32_t pictureID) SK_OVERRIDE{ | 425 virtual void onDeletion(uint32_t pictureID) SK_OVERRIDE{ |
437 const GrPictureDeletedMessage message = { pictureID }; | 426 const GrPictureDeletedMessage message = { pictureID }; |
438 SkMessageBus<GrPictureDeletedMessage>::Post(message); | 427 SkMessageBus<GrPictureDeletedMessage>::Post(message); |
439 } | 428 } |
440 }; | 429 }; |
441 | 430 |
442 void GrLayerCache::trackPicture(const SkPicture* picture) { | 431 void GrLayerCache::trackPicture(const SkPicture* picture) { |
443 if (NULL == fDeletionListener) { | 432 if (NULL == fDeletionListener) { |
444 fDeletionListener.reset(SkNEW(GrPictureDeletionListener)); | 433 fDeletionListener.reset(SkNEW(GrPictureDeletionListener)); |
445 } | 434 } |
446 | 435 |
447 picture->addDeletionListener(fDeletionListener); | 436 picture->addDeletionListener(fDeletionListener); |
448 } | 437 } |
449 | 438 |
450 void GrLayerCache::processDeletedPictures() { | 439 void GrLayerCache::processDeletedPictures() { |
451 SkTDArray<GrPictureDeletedMessage> deletedPictures; | 440 SkTDArray<GrPictureDeletedMessage> deletedPictures; |
452 fPictDeletionInbox.poll(&deletedPictures); | 441 fPictDeletionInbox.poll(&deletedPictures); |
453 | 442 |
454 for (int i = 0; i < deletedPictures.count(); i++) { | 443 for (int i = 0; i < deletedPictures.count(); i++) { |
455 this->purge(deletedPictures[i].pictureID); | 444 this->purge(deletedPictures[i].pictureID); |
456 } | 445 } |
457 } | 446 } |
458 | 447 |
459 #ifdef SK_DEVELOPER | 448 #ifdef SK_DEVELOPER |
460 void GrLayerCache::writeLayersToDisk(const SkString& dirName) { | 449 void GrLayerCache::writeLayersToDisk(const SkString& dirName) { |
461 | 450 |
462 if (fAtlas) { | 451 GrTexture* atlasTexture = fAtlas->getTexture(); |
463 GrTexture* atlasTexture = fAtlas->getTexture(); | 452 if (NULL != atlasTexture) { |
464 if (NULL != atlasTexture) { | 453 SkString fileName(dirName); |
465 SkString fileName(dirName); | 454 fileName.append("\\atlas.png"); |
466 fileName.append("\\atlas.png"); | |
467 | 455 |
468 atlasTexture->surfacePriv().savePixels(fileName.c_str()); | 456 atlasTexture->surfacePriv().savePixels(fileName.c_str()); |
469 } | |
470 } | 457 } |
471 | 458 |
472 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); | 459 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
473 for (; !iter.done(); ++iter) { | 460 for (; !iter.done(); ++iter) { |
474 GrCachedLayer* layer = &(*iter); | 461 GrCachedLayer* layer = &(*iter); |
475 | 462 |
476 if (layer->isAtlased() || !layer->texture()) { | 463 if (layer->isAtlased() || !layer->texture()) { |
477 continue; | 464 continue; |
478 } | 465 } |
479 | 466 |
480 SkString fileName(dirName); | 467 SkString fileName(dirName); |
481 fileName.appendf("\\%d-%d.png", layer->fKey.pictureID(), layer->fKey.sta
rt()); | 468 fileName.appendf("\\%d-%d.png", layer->fKey.pictureID(), layer->fKey.sta
rt()); |
482 | 469 |
483 layer->texture()->surfacePriv().savePixels(fileName.c_str()); | 470 layer->texture()->surfacePriv().savePixels(fileName.c_str()); |
484 } | 471 } |
485 } | 472 } |
486 #endif | 473 #endif |
OLD | NEW |