Index: src/gpu/GrLayerCache.cpp |
diff --git a/src/gpu/GrLayerCache.cpp b/src/gpu/GrLayerCache.cpp |
index 9af89a34665664e42499623bab05e46cc60cd156..105ee04e53cd1a26f6ab78238211229bc3916225 100644 |
--- a/src/gpu/GrLayerCache.cpp |
+++ b/src/gpu/GrLayerCache.cpp |
@@ -27,9 +27,11 @@ void GrCachedLayer::validate(const GrTexture* backingTexture) const { |
SkASSERT(fRect.isEmpty()); |
SkASSERT(nullptr == fPlot); |
SkASSERT(!fLocked); // layers without a texture cannot be locked |
+ SkASSERT(!fAtlased); // can't be atlased if it doesn't have a texture |
} |
if (fPlot) { |
+ SkASSERT(fAtlased); |
// If a layer has a plot (i.e., is atlased) then it must point to |
// the backing texture. Additionally, its rect should be non-empty. |
SkASSERT(fTexture && backingTexture == fTexture); |
@@ -119,8 +121,10 @@ void GrLayerCache::freeAll() { |
} |
fLayerHash.rewind(); |
- // The atlas only lets go of its texture when the atlas is deleted. |
- fAtlas.free(); |
+ if (fAtlas) { |
+ fAtlas->resetPlots(); |
+ fAtlas->detachBackingTexture(); |
+ } |
} |
GrCachedLayer* GrLayerCache::createLayer(uint32_t pictureID, |
@@ -167,7 +171,7 @@ GrCachedLayer* GrLayerCache::findLayerOrCreate(uint32_t pictureID, |
bool GrLayerCache::tryToAtlas(GrCachedLayer* layer, |
const GrSurfaceDesc& desc, |
bool* needsRendering) { |
- SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas ? fAtlas->getTexture() : nullptr, layer);) |
+ SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas ? fAtlas->getTextureOrNull() : nullptr, layer);) |
SkASSERT(PlausiblyAtlasable(desc.fWidth, desc.fHeight)); |
SkASSERT(0 == desc.fSampleCnt); |
@@ -217,7 +221,7 @@ bool GrLayerCache::tryToAtlas(GrCachedLayer* layer, |
// The layer was successfully added to the atlas |
const SkIRect bounds = SkIRect::MakeXYWH(loc.fX, loc.fY, |
desc.fWidth, desc.fHeight); |
- layer->setTexture(fAtlas->getTexture(), bounds); |
+ layer->setTexture(fAtlas->getTexture(), bounds, true); |
layer->setPlot(plot); |
layer->setLocked(true); |
this->incPlotLock(layer->plot()->id()); |
@@ -227,7 +231,7 @@ bool GrLayerCache::tryToAtlas(GrCachedLayer* layer, |
// The layer was rejected by the atlas (even though we know it is |
// plausibly atlas-able). See if a plot can be purged and try again. |
- if (!this->purgePlot()) { |
+ if (!this->purgePlots(true)) { |
break; // We weren't able to purge any plots |
} |
} |
@@ -260,14 +264,14 @@ bool GrLayerCache::lock(GrCachedLayer* layer, const GrSurfaceDesc& desc, bool* n |
return false; |
} |
- layer->setTexture(tex, SkIRect::MakeWH(desc.fWidth, desc.fHeight)); |
+ layer->setTexture(tex, SkIRect::MakeWH(desc.fWidth, desc.fHeight), false); |
layer->setLocked(true); |
*needsRendering = true; |
return true; |
} |
void GrLayerCache::unlock(GrCachedLayer* layer) { |
- SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas ? fAtlas->getTexture() : nullptr, layer);) |
+ SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas ? fAtlas->getTextureOrNull() : nullptr, layer);) |
if (nullptr == layer || !layer->locked()) { |
// invalid or not locked |
@@ -299,11 +303,11 @@ void GrLayerCache::unlock(GrCachedLayer* layer) { |
} |
layer->setPlot(nullptr); |
- layer->setTexture(nullptr, SkIRect::MakeEmpty()); |
+ layer->setTexture(nullptr, SkIRect::MakeEmpty(), false); |
#endif |
} else { |
- layer->setTexture(nullptr, SkIRect::MakeEmpty()); |
+ layer->setTexture(nullptr, SkIRect::MakeEmpty(), false); |
} |
layer->setLocked(false); |
@@ -318,7 +322,7 @@ void GrLayerCache::validate() const { |
for (; !iter.done(); ++iter) { |
const GrCachedLayer* layer = &(*iter); |
- layer->validate(fAtlas.get() ? fAtlas->getTexture() : nullptr); |
+ layer->validate(fAtlas.get() ? fAtlas->getTextureOrNull() : nullptr); |
const GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
if (!pictInfo) { |
@@ -389,10 +393,11 @@ void GrLayerCache::purge(uint32_t pictureID) { |
} |
} |
-bool GrLayerCache::purgePlot() { |
+bool GrLayerCache::purgePlots(bool justOne) { |
SkDEBUGCODE(GrAutoValidateCache avc(this);) |
SkASSERT(fAtlas); |
+ bool anyPurged = false; |
GrLayerAtlas::PlotIter iter; |
GrLayerAtlas::Plot* plot; |
for (plot = fAtlas->iterInit(&iter, GrLayerAtlas::kLRUFirst_IterOrder); |
@@ -402,11 +407,14 @@ bool GrLayerCache::purgePlot() { |
continue; |
} |
+ anyPurged = true; |
this->purgePlot(plot); |
- return true; |
+ if (justOne) { |
+ break; |
+ } |
} |
- return false; |
+ return anyPurged; |
} |
void GrLayerCache::purgePlot(GrLayerAtlas::Plot* plot) { |
@@ -455,27 +463,57 @@ void GrLayerCache::purgeAll() { |
return; |
} |
- GrLayerAtlas::PlotIter iter; |
- GrLayerAtlas::Plot* plot; |
- for (plot = fAtlas->iterInit(&iter, GrLayerAtlas::kLRUFirst_IterOrder); |
- plot; |
- plot = iter.prev()) { |
- SkASSERT(0 == fPlotLocks[plot->id()]); |
- |
- this->purgePlot(plot); |
- } |
+ this->purgePlots(false); // clear them all out |
SkASSERT(0 == fPictureHash.count()); |
- SkAutoTUnref<GrDrawContext> drawContext( |
- fContext->drawContext(fAtlas->getTexture()->asRenderTarget())); |
+ if (fAtlas->getTextureOrNull()) { |
+ SkAutoTUnref<GrDrawContext> drawContext( |
+ fContext->drawContext(fAtlas->getTexture()->asRenderTarget())); |
- if (drawContext) { |
- drawContext->discard(); |
+ if (drawContext) { |
+ drawContext->discard(); |
+ } |
} |
} |
#endif |
+void GrLayerCache::begin() { |
+ if (!fAtlas) { |
+ return; |
+ } |
+ |
+ if (!fAtlas->reattachBackingTexture()) { |
+ // We weren't able to re-attach. Clear out all the atlased layers. |
+ this->purgePlots(false); |
+ SkASSERT(0 == fPictureHash.count()); |
+ } |
+#ifdef SK_DEBUG |
+ else { |
+ // we've reattached - everything had better make sense |
+ SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
+ for (; !iter.done(); ++iter) { |
+ GrCachedLayer* layer = &(*iter); |
+ |
+ if (layer->isAtlased()) { |
+ SkASSERT(fAtlas->getTexture() == layer->texture()); |
+ } |
+ } |
+ } |
+#endif |
+} |
+ |
+void GrLayerCache::end() { |
+ if (!fAtlas) { |
+ return; |
+ } |
+ |
+ // Adding this call will clear out all the layers in the atlas |
+ //this->purgePlots(false); |
+ |
+ fAtlas->detachBackingTexture(); |
+} |
+ |
void GrLayerCache::processDeletedPictures() { |
SkTArray<SkPicture::DeletionMessage> deletedPictures; |
fPictDeletionInbox.poll(&deletedPictures); |
@@ -489,7 +527,7 @@ void GrLayerCache::processDeletedPictures() { |
void GrLayerCache::writeLayersToDisk(const SkString& dirName) { |
if (fAtlas) { |
- GrTexture* atlasTexture = fAtlas->getTexture(); |
+ GrTexture* atlasTexture = fAtlas->getTextureOrNull(); |
if (nullptr != atlasTexture) { |
SkString fileName(dirName); |
fileName.append("\\atlas.png"); |