Discard atlas after every MultiPictureDraw::draw

This is intended to prevent ghosting on tiled architectures.

This CL also defers creation of the atlas (and its texture) until it is actually needed.

Review URL: https://codereview.chromium.org/678403002
This commit is contained in:
robertphillips 2014-10-29 08:05:21 -07:00 committed by Commit bot
parent 5abfa688b7
commit 6d5b545574
5 changed files with 48 additions and 18 deletions

View File

@ -146,6 +146,9 @@ void SkMultiPictureDraw::draw() {
if (NULL != context) {
GrLayerHoister::UnlockLayers(context, atlasedNeedRendering);
GrLayerHoister::UnlockLayers(context, atlasedRecycled);
#if !GR_CACHE_HOISTED_LAYERS
GrLayerHoister::PurgeCache(context);
#endif
}
#endif

View File

@ -81,7 +81,6 @@ private:
GrLayerCache::GrLayerCache(GrContext* context)
: fContext(context) {
this->initAtlas();
memset(fPlotLocks, 0, sizeof(fPlotLocks));
}
@ -120,11 +119,6 @@ void GrLayerCache::freeAll() {
// The atlas only lets go of its texture when the atlas is deleted.
fAtlas.free();
// GrLayerCache always assumes an atlas exists so recreate it. The atlas
// lazily allocates a replacement texture so reallocating a new
// atlas here won't disrupt a GrContext::abandonContext or freeGpuResources.
// TODO: Make GrLayerCache lazily allocate the atlas manager?
this->initAtlas();
}
GrCachedLayer* GrLayerCache::createLayer(uint32_t pictureID,
@ -170,6 +164,7 @@ bool GrLayerCache::tryToAtlas(GrCachedLayer* layer,
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);
@ -178,12 +173,19 @@ bool GrLayerCache::tryToAtlas(GrCachedLayer* layer,
}
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 (NULL == pictInfo) {
@ -256,7 +258,7 @@ void GrLayerCache::unlock(GrCachedLayer* layer) {
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 DISABLE_CACHING
#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
@ -355,6 +357,7 @@ void GrLayerCache::purge(uint32_t pictureID) {
bool GrLayerCache::purgePlot() {
SkDEBUGCODE(GrAutoValidateCache avc(this);)
SkASSERT(fAtlas);
GrAtlas::PlotIter iter;
GrPlot* plot;
@ -409,7 +412,12 @@ void GrLayerCache::purgePlot(GrPlot* plot) {
plot->resetRects();
}
#if !GR_CACHE_HOISTED_LAYERS
void GrLayerCache::purgeAll() {
if (!fAtlas) {
return;
}
GrAtlas::PlotIter iter;
GrPlot* plot;
for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder);
@ -419,7 +427,10 @@ void GrLayerCache::purgeAll() {
this->purgePlot(plot);
}
fContext->discardRenderTarget(fAtlas->getTexture()->asRenderTarget());
}
#endif
class GrPictureDeletionListener : public SkPicture::DeletionListener {
virtual void onDeletion(uint32_t pictureID) SK_OVERRIDE{
@ -448,12 +459,14 @@ void GrLayerCache::processDeletedPictures() {
#ifdef SK_DEVELOPER
void GrLayerCache::writeLayersToDisk(const SkString& dirName) {
GrTexture* atlasTexture = fAtlas->getTexture();
if (NULL != atlasTexture) {
SkString fileName(dirName);
fileName.append("\\atlas.png");
if (fAtlas) {
GrTexture* atlasTexture = fAtlas->getTexture();
if (NULL != atlasTexture) {
SkString fileName(dirName);
fileName.append("\\atlas.png");
atlasTexture->surfacePriv().savePixels(fileName.c_str());
atlasTexture->surfacePriv().savePixels(fileName.c_str());
}
}
SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash);

View File

@ -18,6 +18,9 @@
class SkPicture;
// Set to 0 to disable caching of hoisted layers
#define GR_CACHE_HOISTED_LAYERS 0
// The layer cache listens for these messages to purge picture-related resources.
struct GrPictureDeletedMessage {
uint32_t pictureID;
@ -249,6 +252,10 @@ public:
return width <= kPlotWidth && height <= kPlotHeight;
}
#if !GR_CACHE_HOISTED_LAYERS
void purgeAll();
#endif
private:
static const int kAtlasTextureWidth = 1024;
static const int kAtlasTextureHeight = 1024;
@ -291,8 +298,6 @@ private:
const SkIRect& bounds, const SkMatrix& ctm,
const SkPaint* paint);
void purgeAll();
// Remove all the layers (and unlock any resources) associated with 'pictureID'
void purge(uint32_t pictureID);

View File

@ -314,13 +314,16 @@ void GrLayerHoister::UnlockLayers(GrContext* context,
layerCache->removeUse(layers[i].fLayer);
}
#if DISABLE_CACHING
SkDEBUGCODE(layerCache->validate();)
}
void GrLayerHoister::PurgeCache(GrContext* context) {
#if !GR_CACHE_HOISTED_LAYERS
GrLayerCache* layerCache = context->getLayerCache();
// This code completely clears out the atlas. It is required when
// caching is disabled so the atlas doesn't fill up and force more
// free floating layers
layerCache->purgeAll();
#endif
SkDEBUGCODE(layerCache->validate();)
}

View File

@ -87,6 +87,12 @@ public:
@param layers Unneeded layers in the atlas
*/
static void UnlockLayers(GrContext* context, const SkTDArray<GrHoistedLayer>& layers);
/** Forceably remove all cached layers and release the atlas. Useful for debugging and timing.
This is only functional when GR_CACHE_HOISTED_LAYERS is set to 1 in GrLayerCache.h
@param context Owner of the layer cache (and thus the layers)
*/
static void PurgeCache(GrContext* context);
};
#endif