Fix bug in aggressive layer cache purging

A picture may possess many layers that get placed in one plot of the atlas. In this case we can only remove the plot from the plotUsage tracking structure when all the layers belonging to the picture in that plot have been removed.

Review URL: https://codereview.chromium.org/654463004
This commit is contained in:
robertphillips 2014-10-30 11:39:19 -07:00 committed by Commit bot
parent a3a706fcd4
commit 225a627ccb
2 changed files with 46 additions and 4 deletions

View File

@ -100,6 +100,7 @@ GrLayerCache::~GrLayerCache() {
void GrLayerCache::initAtlas() {
SkASSERT(NULL == fAtlas.get());
GR_STATIC_ASSERT(kNumPlotsX*kNumPlotsX == GrPictureInfo::kNumPlots);
SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight);
fAtlas.reset(SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kSkia8888_GrPixelConfig,
@ -201,6 +202,9 @@ bool GrLayerCache::tryToAtlas(GrCachedLayer* layer,
// 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
GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY,
SkToS16(desc.fWidth),
@ -264,8 +268,12 @@ void GrLayerCache::unlock(GrCachedLayer* layer) {
// render target pingponging from that due to the re-use of cached layers
GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID());
SkASSERT(pictInfo);
GrAtlas::RemovePlot(&pictInfo->fPlotUsage, layer->plot());
pictInfo->decPlotUsage(plotID);
if (0 == pictInfo->plotUsage(plotID)) {
GrAtlas::RemovePlot(&pictInfo->fPlotUsage, layer->plot());
}
layer->setPlot(NULL);
layer->setTexture(NULL, GrIRect16::MakeEmpty());
@ -301,6 +309,9 @@ void GrLayerCache::validate() const {
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()]++;
@ -400,6 +411,9 @@ void GrLayerCache::purgePlot(GrPlot* plot) {
GrPictureInfo* pictInfo = fPictureHash.find(pictureIDToRemove);
if (pictInfo) {
#if !GR_CACHE_HOISTED_LAYERS
SkASSERT(0 == pictInfo->plotUsage(plot->id()));
#endif
GrAtlas::RemovePlot(&pictInfo->fPlotUsage, plot);
if (pictInfo->fPlotUsage.isEmpty()) {

View File

@ -30,16 +30,44 @@ struct GrPictureDeletedMessage {
// plot may be used to store layers from multiple pictures.
struct GrPictureInfo {
public:
static const int kNumPlots = 4;
// for SkTDynamicHash - just use the pictureID as the hash key
static const uint32_t& GetKey(const GrPictureInfo& pictInfo) { return pictInfo.fPictureID; }
static uint32_t Hash(const uint32_t& key) { return SkChecksum::Mix(key); }
// GrPictureInfo proper
GrPictureInfo(uint32_t pictureID) : fPictureID(pictureID) { }
GrPictureInfo(uint32_t pictureID) : fPictureID(pictureID) {
#if !GR_CACHE_HOISTED_LAYERS
memset(fPlotUses, 0, sizeof(fPlotUses));
#endif
}
#if !GR_CACHE_HOISTED_LAYERS
void incPlotUsage(int plotID) {
SkASSERT(plotID < kNumPlots);
fPlotUses[plotID]++;
}
void decPlotUsage(int plotID) {
SkASSERT(plotID < kNumPlots);
SkASSERT(fPlotUses[plotID] > 0);
fPlotUses[plotID]--;
}
int plotUsage(int plotID) const {
SkASSERT(plotID < kNumPlots);
return fPlotUses[plotID];
}
#endif
const uint32_t fPictureID;
GrAtlas::ClientPlotUsage fPlotUsage;
#if !GR_CACHE_HOISTED_LAYERS
private:
int fPlotUses[kNumPlots];
#endif
};
// GrCachedLayer encapsulates the caching information for a single saveLayer.