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:
parent
5abfa688b7
commit
6d5b545574
@ -146,6 +146,9 @@ void SkMultiPictureDraw::draw() {
|
|||||||
if (NULL != context) {
|
if (NULL != context) {
|
||||||
GrLayerHoister::UnlockLayers(context, atlasedNeedRendering);
|
GrLayerHoister::UnlockLayers(context, atlasedNeedRendering);
|
||||||
GrLayerHoister::UnlockLayers(context, atlasedRecycled);
|
GrLayerHoister::UnlockLayers(context, atlasedRecycled);
|
||||||
|
#if !GR_CACHE_HOISTED_LAYERS
|
||||||
|
GrLayerHoister::PurgeCache(context);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -81,7 +81,6 @@ private:
|
|||||||
|
|
||||||
GrLayerCache::GrLayerCache(GrContext* context)
|
GrLayerCache::GrLayerCache(GrContext* context)
|
||||||
: fContext(context) {
|
: fContext(context) {
|
||||||
this->initAtlas();
|
|
||||||
memset(fPlotLocks, 0, sizeof(fPlotLocks));
|
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.
|
// The atlas only lets go of its texture when the atlas is deleted.
|
||||||
fAtlas.free();
|
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,
|
GrCachedLayer* GrLayerCache::createLayer(uint32_t pictureID,
|
||||||
@ -170,6 +164,7 @@ bool GrLayerCache::tryToAtlas(GrCachedLayer* layer,
|
|||||||
|
|
||||||
if (layer->locked()) {
|
if (layer->locked()) {
|
||||||
// This layer is already locked
|
// This layer is already locked
|
||||||
|
SkASSERT(fAtlas);
|
||||||
SkASSERT(layer->isAtlased());
|
SkASSERT(layer->isAtlased());
|
||||||
SkASSERT(layer->rect().width() == desc.fWidth);
|
SkASSERT(layer->rect().width() == desc.fWidth);
|
||||||
SkASSERT(layer->rect().height() == desc.fHeight);
|
SkASSERT(layer->rect().height() == desc.fHeight);
|
||||||
@ -178,12 +173,19 @@ bool GrLayerCache::tryToAtlas(GrCachedLayer* layer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (layer->isAtlased()) {
|
if (layer->isAtlased()) {
|
||||||
|
SkASSERT(fAtlas);
|
||||||
// Hooray it is still in the atlas - make sure it stays there
|
// Hooray it is still in the atlas - make sure it stays there
|
||||||
layer->setLocked(true);
|
layer->setLocked(true);
|
||||||
this->incPlotLock(layer->plot()->id());
|
this->incPlotLock(layer->plot()->id());
|
||||||
*needsRendering = false;
|
*needsRendering = false;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
if (!fAtlas) {
|
||||||
|
this->initAtlas();
|
||||||
|
if (!fAtlas) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Not in the atlas - will it fit?
|
// Not in the atlas - will it fit?
|
||||||
GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID());
|
GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID());
|
||||||
if (NULL == pictInfo) {
|
if (NULL == pictInfo) {
|
||||||
@ -256,7 +258,7 @@ void GrLayerCache::unlock(GrCachedLayer* layer) {
|
|||||||
this->decPlotLock(plotID);
|
this->decPlotLock(plotID);
|
||||||
// At this point we could aggressively clear out un-locked plots but
|
// 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.
|
// 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
|
// This testing code aggressively removes the atlased layers. This
|
||||||
// can be used to separate the performance contribution of less
|
// can be used to separate the performance contribution of less
|
||||||
// render target pingponging from that due to the re-use of cached layers
|
// 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() {
|
bool GrLayerCache::purgePlot() {
|
||||||
SkDEBUGCODE(GrAutoValidateCache avc(this);)
|
SkDEBUGCODE(GrAutoValidateCache avc(this);)
|
||||||
|
SkASSERT(fAtlas);
|
||||||
|
|
||||||
GrAtlas::PlotIter iter;
|
GrAtlas::PlotIter iter;
|
||||||
GrPlot* plot;
|
GrPlot* plot;
|
||||||
@ -409,7 +412,12 @@ void GrLayerCache::purgePlot(GrPlot* plot) {
|
|||||||
plot->resetRects();
|
plot->resetRects();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !GR_CACHE_HOISTED_LAYERS
|
||||||
void GrLayerCache::purgeAll() {
|
void GrLayerCache::purgeAll() {
|
||||||
|
if (!fAtlas) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GrAtlas::PlotIter iter;
|
GrAtlas::PlotIter iter;
|
||||||
GrPlot* plot;
|
GrPlot* plot;
|
||||||
for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder);
|
for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder);
|
||||||
@ -419,7 +427,10 @@ void GrLayerCache::purgeAll() {
|
|||||||
|
|
||||||
this->purgePlot(plot);
|
this->purgePlot(plot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fContext->discardRenderTarget(fAtlas->getTexture()->asRenderTarget());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
class GrPictureDeletionListener : public SkPicture::DeletionListener {
|
class GrPictureDeletionListener : public SkPicture::DeletionListener {
|
||||||
virtual void onDeletion(uint32_t pictureID) SK_OVERRIDE{
|
virtual void onDeletion(uint32_t pictureID) SK_OVERRIDE{
|
||||||
@ -448,12 +459,14 @@ void GrLayerCache::processDeletedPictures() {
|
|||||||
#ifdef SK_DEVELOPER
|
#ifdef SK_DEVELOPER
|
||||||
void GrLayerCache::writeLayersToDisk(const SkString& dirName) {
|
void GrLayerCache::writeLayersToDisk(const SkString& dirName) {
|
||||||
|
|
||||||
GrTexture* atlasTexture = fAtlas->getTexture();
|
if (fAtlas) {
|
||||||
if (NULL != atlasTexture) {
|
GrTexture* atlasTexture = fAtlas->getTexture();
|
||||||
SkString fileName(dirName);
|
if (NULL != atlasTexture) {
|
||||||
fileName.append("\\atlas.png");
|
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);
|
SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash);
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
|
|
||||||
class SkPicture;
|
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.
|
// The layer cache listens for these messages to purge picture-related resources.
|
||||||
struct GrPictureDeletedMessage {
|
struct GrPictureDeletedMessage {
|
||||||
uint32_t pictureID;
|
uint32_t pictureID;
|
||||||
@ -249,6 +252,10 @@ public:
|
|||||||
return width <= kPlotWidth && height <= kPlotHeight;
|
return width <= kPlotWidth && height <= kPlotHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !GR_CACHE_HOISTED_LAYERS
|
||||||
|
void purgeAll();
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const int kAtlasTextureWidth = 1024;
|
static const int kAtlasTextureWidth = 1024;
|
||||||
static const int kAtlasTextureHeight = 1024;
|
static const int kAtlasTextureHeight = 1024;
|
||||||
@ -291,8 +298,6 @@ private:
|
|||||||
const SkIRect& bounds, const SkMatrix& ctm,
|
const SkIRect& bounds, const SkMatrix& ctm,
|
||||||
const SkPaint* paint);
|
const SkPaint* paint);
|
||||||
|
|
||||||
void purgeAll();
|
|
||||||
|
|
||||||
// Remove all the layers (and unlock any resources) associated with 'pictureID'
|
// Remove all the layers (and unlock any resources) associated with 'pictureID'
|
||||||
void purge(uint32_t pictureID);
|
void purge(uint32_t pictureID);
|
||||||
|
|
||||||
|
@ -314,13 +314,16 @@ void GrLayerHoister::UnlockLayers(GrContext* context,
|
|||||||
layerCache->removeUse(layers[i].fLayer);
|
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
|
// This code completely clears out the atlas. It is required when
|
||||||
// caching is disabled so the atlas doesn't fill up and force more
|
// caching is disabled so the atlas doesn't fill up and force more
|
||||||
// free floating layers
|
// free floating layers
|
||||||
layerCache->purgeAll();
|
layerCache->purgeAll();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SkDEBUGCODE(layerCache->validate();)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +87,12 @@ public:
|
|||||||
@param layers Unneeded layers in the atlas
|
@param layers Unneeded layers in the atlas
|
||||||
*/
|
*/
|
||||||
static void UnlockLayers(GrContext* context, const SkTDArray<GrHoistedLayer>& layers);
|
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
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user