diff options
Diffstat (limited to 'src/gpu/GrLayerCache.cpp')
-rw-r--r-- | src/gpu/GrLayerCache.cpp | 557 |
1 files changed, 0 insertions, 557 deletions
diff --git a/src/gpu/GrLayerCache.cpp b/src/gpu/GrLayerCache.cpp deleted file mode 100644 index b14423aaa2..0000000000 --- a/src/gpu/GrLayerCache.cpp +++ /dev/null @@ -1,557 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "GrLayerAtlas.h" -#include "GrContext.h" -#include "GrDrawContext.h" -#include "GrGpu.h" -#include "GrLayerCache.h" -#include "GrSurfacePriv.h" - -#ifdef SK_DEBUG -void GrCachedLayer::validate(const GrTexture* backingTexture) const { - SkASSERT(SK_InvalidGenID != fKey.pictureID()); - - if (fTexture) { - // If the layer is in some texture then it must occupy some rectangle - SkASSERT(!fRect.isEmpty()); - if (!this->isAtlased()) { - // If it isn't atlased then the rectangle should start at the origin - SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); - } - } else { - 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); - SkASSERT(!fRect.isEmpty()); - } - - if (fLocked) { - // If a layer is locked it must have a texture (though it need not be - // the atlas-backing texture) and occupy some space. - SkASSERT(fTexture); - SkASSERT(!fRect.isEmpty()); - } - - // Unfortunately there is a brief time where a layer can be locked - // but not used, so we can only check the "used implies locked" - // invariant. - if (fUses > 0) { - SkASSERT(fLocked); - } else { - SkASSERT(0 == fUses); - } -} - -class GrAutoValidateLayer : ::SkNoncopyable { -public: - GrAutoValidateLayer(GrTexture* backingTexture, const GrCachedLayer* layer) - : fBackingTexture(backingTexture) - , fLayer(layer) { - if (fLayer) { - fLayer->validate(backingTexture); - } - } - ~GrAutoValidateLayer() { - if (fLayer) { - fLayer->validate(fBackingTexture); - } - } - void setBackingTexture(GrTexture* backingTexture) { - SkASSERT(nullptr == fBackingTexture || fBackingTexture == backingTexture); - fBackingTexture = backingTexture; - } - -private: - const GrTexture* fBackingTexture; - const GrCachedLayer* fLayer; -}; -#endif - -GrLayerCache::GrLayerCache(GrContext* context) - : fContext(context) { - memset(fPlotLocks, 0, sizeof(fPlotLocks)); -} - -GrLayerCache::~GrLayerCache() { - - SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); - for (; !iter.done(); ++iter) { - GrCachedLayer* layer = &(*iter); - SkASSERT(0 == layer->uses()); - this->unlock(layer); - delete layer; - } - - SkASSERT(0 == fPictureHash.count()); - - // The atlas only lets go of its texture when the atlas is deleted. - fAtlas.reset(); -} - -void GrLayerCache::initAtlas() { - SkASSERT(nullptr == fAtlas.get()); - GR_STATIC_ASSERT(kNumPlotsX*kNumPlotsX == GrPictureInfo::kNumPlots); - - SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight); - fAtlas.reset(new GrLayerAtlas(fContext->textureProvider(), kSkia8888_GrPixelConfig, - kRenderTarget_GrSurfaceFlag, textureSize, - kNumPlotsX, kNumPlotsY)); -} - -void GrLayerCache::freeAll() { - - SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); - for (; !iter.done(); ++iter) { - GrCachedLayer* layer = &(*iter); - this->unlock(layer); - delete layer; - } - fLayerHash.rewind(); - - if (fAtlas) { - fAtlas->resetPlots(); - fAtlas->detachBackingTexture(); - } -} - -GrCachedLayer* GrLayerCache::createLayer(uint32_t pictureID, - int start, int stop, - const SkIRect& srcIR, - const SkIRect& dstIR, - const SkMatrix& initialMat, - const int* key, - int keySize, - const SkPaint* paint) { - SkASSERT(pictureID != SK_InvalidGenID && start >= 0 && stop > 0); - - GrCachedLayer* layer = new GrCachedLayer(pictureID, start, stop, srcIR, dstIR, initialMat, key, - keySize, paint); - fLayerHash.add(layer); - return layer; -} - -GrCachedLayer* GrLayerCache::findLayer(uint32_t pictureID, const SkMatrix& initialMat, - const int* key, int keySize) { - SkASSERT(pictureID != SK_InvalidGenID); - return fLayerHash.find(GrCachedLayer::Key(pictureID, initialMat, key, keySize)); -} - -GrCachedLayer* GrLayerCache::findLayerOrCreate(uint32_t pictureID, - int start, int stop, - const SkIRect& srcIR, - const SkIRect& dstIR, - const SkMatrix& initialMat, - const int* key, - int keySize, - const SkPaint* paint) { - SkASSERT(pictureID != SK_InvalidGenID && start >= 0 && stop > 0); - GrCachedLayer* layer = fLayerHash.find(GrCachedLayer::Key(pictureID, initialMat, key, keySize)); - if (nullptr == layer) { - layer = this->createLayer(pictureID, start, stop, - srcIR, dstIR, initialMat, - key, keySize, paint); - } - - return layer; -} - -bool GrLayerCache::tryToAtlas(GrCachedLayer* layer, - const GrSurfaceDesc& desc, - bool* needsRendering) { - SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas ? fAtlas->getTextureOrNull() : nullptr, layer);) - - SkASSERT(PlausiblyAtlasable(desc.fWidth, desc.fHeight)); - SkASSERT(0 == desc.fSampleCnt); - - if (layer->locked()) { - // This layer is already locked - SkASSERT(fAtlas); - SkASSERT(layer->isAtlased()); - SkASSERT(layer->rect().width() == desc.fWidth); - SkASSERT(layer->rect().height() == desc.fHeight); - *needsRendering = false; - return true; - } - - if (layer->isAtlased()) { - SkASSERT(fAtlas); - // Hooray it is still in the atlas - make sure it stays there - layer->setLocked(true); - this->incPlotLock(layer->plot()->id()); - *needsRendering = false; - return true; - } else { - if (!fAtlas) { - this->initAtlas(); - if (!fAtlas) { - return false; - } - } - // Not in the atlas - will it fit? - GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); - if (nullptr == pictInfo) { - pictInfo = new GrPictureInfo(layer->pictureID()); - fPictureHash.add(pictInfo); - } - - SkIPoint16 loc; - for (int i = 0; i < 2; ++i) { // extra pass in case we fail to add but are able to purge - GrLayerAtlas::Plot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, - desc.fWidth, desc.fHeight, - &loc); - // addToAtlas can allocate the backing texture - SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); - if (plot) { -#if !GR_CACHE_HOISTED_LAYERS - pictInfo->incPlotUsage(plot->id()); -#endif - // 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, true); - layer->setPlot(plot); - layer->setLocked(true); - this->incPlotLock(layer->plot()->id()); - *needsRendering = true; - return true; - } - - // 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->purgePlots(true)) { - break; // We weren't able to purge any plots - } - } - - if (pictInfo->fPlotUsage.isEmpty()) { - fPictureHash.remove(pictInfo->fPictureID); - delete pictInfo; - } - } - - return false; -} - -bool GrLayerCache::lock(GrCachedLayer* layer, const GrSurfaceDesc& desc, bool* needsRendering) { - if (layer->locked()) { - // This layer is already locked - *needsRendering = false; - return true; - } - - // TODO: make the test for exact match depend on the image filters themselves - SkAutoTUnref<GrTexture> tex; - if (layer->fFilter) { - tex.reset(fContext->textureProvider()->createTexture(desc, SkBudgeted::kYes)); - } else { - tex.reset(fContext->textureProvider()->createApproxTexture(desc)); - } - - if (!tex) { - return false; - } - - 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->getTextureOrNull() : nullptr, layer);) - - if (nullptr == layer || !layer->locked()) { - // invalid or not locked - return; - } - - if (layer->isAtlased()) { - const int plotID = layer->plot()->id(); - - this->decPlotLock(plotID); - // At this point we could aggressively clear out un-locked plots but - // by delaying we may be able to reuse some of the atlased layers later. -#if !GR_CACHE_HOISTED_LAYERS - // This testing code aggressively removes the atlased layers. This - // can be used to separate the performance contribution of less - // render target pingponging from that due to the re-use of cached layers - GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); - SkASSERT(pictInfo); - - pictInfo->decPlotUsage(plotID); - - if (0 == pictInfo->plotUsage(plotID)) { - pictInfo->fPlotUsage.removePlot(layer->plot()); - - if (pictInfo->fPlotUsage.isEmpty()) { - fPictureHash.remove(pictInfo->fPictureID); - delete pictInfo; - } - } - - layer->setPlot(nullptr); - layer->setTexture(nullptr, SkIRect::MakeEmpty(), false); -#endif - - } else { - layer->setTexture(nullptr, SkIRect::MakeEmpty(), false); - } - - layer->setLocked(false); -} - -#ifdef SK_DEBUG -void GrLayerCache::validate() const { - int plotLocks[kNumPlotsX * kNumPlotsY]; - memset(plotLocks, 0, sizeof(plotLocks)); - - SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::ConstIter iter(&fLayerHash); - for (; !iter.done(); ++iter) { - const GrCachedLayer* layer = &(*iter); - - layer->validate(fAtlas.get() ? fAtlas->getTextureOrNull() : nullptr); - - const GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); - if (!pictInfo) { - // If there is no picture info for this picture then all of its - // layers should be non-atlased. - SkASSERT(!layer->isAtlased()); - } - - if (layer->plot()) { - SkASSERT(pictInfo); - SkASSERT(pictInfo->fPictureID == layer->pictureID()); - - SkASSERT(pictInfo->fPlotUsage.contains(layer->plot())); -#if !GR_CACHE_HOISTED_LAYERS - SkASSERT(pictInfo->plotUsage(layer->plot()->id()) > 0); -#endif - - if (layer->locked()) { - plotLocks[layer->plot()->id()]++; - } - } - } - - for (int i = 0; i < kNumPlotsX*kNumPlotsY; ++i) { - SkASSERT(plotLocks[i] == fPlotLocks[i]); - } -} - -class GrAutoValidateCache : ::SkNoncopyable { -public: - explicit GrAutoValidateCache(GrLayerCache* cache) - : fCache(cache) { - fCache->validate(); - } - ~GrAutoValidateCache() { - fCache->validate(); - } -private: - GrLayerCache* fCache; -}; -#endif - -void GrLayerCache::purge(uint32_t pictureID) { - - SkDEBUGCODE(GrAutoValidateCache avc(this);) - - // We need to find all the layers associated with 'picture' and remove them. - SkTDArray<GrCachedLayer*> toBeRemoved; - - SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); - for (; !iter.done(); ++iter) { - if (pictureID == (*iter).pictureID()) { - *toBeRemoved.append() = &(*iter); - } - } - - for (int i = 0; i < toBeRemoved.count(); ++i) { - SkASSERT(0 == toBeRemoved[i]->uses()); - this->unlock(toBeRemoved[i]); - fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); - delete toBeRemoved[i]; - } - - GrPictureInfo* pictInfo = fPictureHash.find(pictureID); - if (pictInfo) { - fPictureHash.remove(pictureID); - delete pictInfo; - } -} - -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); - plot; - plot = iter.prev()) { - if (fPlotLocks[plot->id()] > 0) { - continue; - } - - anyPurged = true; - this->purgePlot(plot); - if (justOne) { - break; - } - } - - return anyPurged; -} - -void GrLayerCache::purgePlot(GrLayerAtlas::Plot* plot) { - SkASSERT(0 == fPlotLocks[plot->id()]); - - // We need to find all the layers in 'plot' and remove them. - SkTDArray<GrCachedLayer*> toBeRemoved; - - SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); - for (; !iter.done(); ++iter) { - if (plot == (*iter).plot()) { - *toBeRemoved.append() = &(*iter); - } - } - - for (int i = 0; i < toBeRemoved.count(); ++i) { - SkASSERT(0 == toBeRemoved[i]->uses()); - SkASSERT(!toBeRemoved[i]->locked()); - - uint32_t pictureIDToRemove = toBeRemoved[i]->pictureID(); - - // Aggressively remove layers and, if it becomes totally uncached, delete the picture info - fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); - delete toBeRemoved[i]; - - GrPictureInfo* pictInfo = fPictureHash.find(pictureIDToRemove); - if (pictInfo) { -#if !GR_CACHE_HOISTED_LAYERS - SkASSERT(0 == pictInfo->plotUsage(plot->id())); -#endif - pictInfo->fPlotUsage.removePlot(plot); - - if (pictInfo->fPlotUsage.isEmpty()) { - fPictureHash.remove(pictInfo->fPictureID); - delete pictInfo; - } - } - } - - plot->reset(); -} - -#if !GR_CACHE_HOISTED_LAYERS -void GrLayerCache::purgeAll() { - if (!fAtlas) { - return; - } - - this->purgePlots(false); // clear them all out - - SkASSERT(0 == fPictureHash.count()); - - if (fAtlas->getTextureOrNull()) { - sk_sp<GrDrawContext> drawContext( - fContext->drawContext(sk_ref_sp(fAtlas->getTexture()->asRenderTarget()))); - - 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); - - for (int i = 0; i < deletedPictures.count(); i++) { - this->purge(deletedPictures[i].fUniqueID); - } -} - -#ifdef SK_DEBUG -void GrLayerCache::writeLayersToDisk(const SkString& dirName) { - - if (fAtlas) { - GrTexture* atlasTexture = fAtlas->getTextureOrNull(); - if (nullptr != atlasTexture) { - SkString fileName(dirName); - fileName.append("\\atlas.png"); - - atlasTexture->surfacePriv().savePixels(fileName.c_str()); - } - } - - SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); - for (; !iter.done(); ++iter) { - GrCachedLayer* layer = &(*iter); - - if (layer->isAtlased() || !layer->texture()) { - continue; - } - - SkString fileName(dirName); - fileName.appendf("\\%d", layer->fKey.pictureID()); - for (int i = 0; i < layer->fKey.keySize(); ++i) { - fileName.appendf("-%d", layer->fKey.key()[i]); - } - fileName.appendf(".png"); - - layer->texture()->surfacePriv().savePixels(fileName.c_str()); - } -} -#endif |