diff options
-rw-r--r-- | src/gpu/GrLayerCache.cpp | 105 | ||||
-rw-r--r-- | src/gpu/GrLayerCache.h | 24 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 16 | ||||
-rw-r--r-- | tests/GpuLayerCacheTest.cpp | 22 |
4 files changed, 101 insertions, 66 deletions
diff --git a/src/gpu/GrLayerCache.cpp b/src/gpu/GrLayerCache.cpp index 5fb76d7392..c0510c0365 100644 --- a/src/gpu/GrLayerCache.cpp +++ b/src/gpu/GrLayerCache.cpp @@ -117,37 +117,36 @@ void GrLayerCache::freeAll() { this->initAtlas(); } -GrCachedLayer* GrLayerCache::createLayer(const SkPicture* picture, +GrCachedLayer* GrLayerCache::createLayer(uint32_t pictureID, int start, int stop, const SkMatrix& ctm) { - SkASSERT(picture->uniqueID() != SK_InvalidGenID && start > 0 && stop > 0); + SkASSERT(pictureID != SK_InvalidGenID && start > 0 && stop > 0); - GrCachedLayer* layer = SkNEW_ARGS(GrCachedLayer, (picture->uniqueID(), start, stop, ctm)); + GrCachedLayer* layer = SkNEW_ARGS(GrCachedLayer, (pictureID, start, stop, ctm)); fLayerHash.add(layer); return layer; } -GrCachedLayer* GrLayerCache::findLayer(const SkPicture* picture, +GrCachedLayer* GrLayerCache::findLayer(uint32_t pictureID, int start, int stop, const SkMatrix& ctm) { - SkASSERT(picture->uniqueID() != SK_InvalidGenID && start > 0 && stop > 0); - return fLayerHash.find(GrCachedLayer::Key(picture->uniqueID(), start, stop, ctm)); + SkASSERT(pictureID != SK_InvalidGenID && start > 0 && stop > 0); + return fLayerHash.find(GrCachedLayer::Key(pictureID, start, stop, ctm)); } -GrCachedLayer* GrLayerCache::findLayerOrCreate(const SkPicture* picture, +GrCachedLayer* GrLayerCache::findLayerOrCreate(uint32_t pictureID, int start, int stop, const SkMatrix& ctm) { - SkASSERT(picture->uniqueID() != SK_InvalidGenID && start > 0 && stop > 0); - GrCachedLayer* layer = fLayerHash.find(GrCachedLayer::Key(picture->uniqueID(), - start, stop, ctm)); + SkASSERT(pictureID != SK_InvalidGenID && start > 0 && stop > 0); + GrCachedLayer* layer = fLayerHash.find(GrCachedLayer::Key(pictureID, start, stop, ctm)); if (NULL == layer) { - layer = this->createLayer(picture, start, stop, ctm); + layer = this->createLayer(pictureID, start, stop, ctm); } return layer; } -bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) { +bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc, bool dontAtlas) { SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) if (layer->locked()) { @@ -155,19 +154,21 @@ bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) { #ifdef SK_DEBUG if (layer->isAtlased()) { // It claims to be atlased + SkASSERT(!dontAtlas); SkASSERT(layer->rect().width() == desc.fWidth); SkASSERT(layer->rect().height() == desc.fHeight); } #endif - return true; + return false; } if (layer->isAtlased()) { // Hooray it is still in the atlas - make sure it stays there + SkASSERT(!dontAtlas); layer->setLocked(true); fPlotLocks[layer->plot()->id()]++; - return true; - } else if (PlausiblyAtlasable(desc.fWidth, desc.fHeight)) { + return false; + } else if (!dontAtlas && PlausiblyAtlasable(desc.fWidth, desc.fHeight)) { // Not in the atlas - will it fit? GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); if (NULL == pictInfo) { @@ -185,13 +186,13 @@ bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) { if (NULL != plot) { // The layer was successfully added to the atlas GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, - SkToS16(desc.fWidth), + SkToS16(desc.fWidth), SkToS16(desc.fHeight)); layer->setTexture(fAtlas->getTexture(), bounds); layer->setPlot(plot); layer->setLocked(true); fPlotLocks[layer->plot()->id()]++; - return false; + return true; } // The layer was rejected by the atlas (even though we know it is @@ -210,7 +211,7 @@ bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) { layer->setTexture(tex, GrIRect16::MakeWH(SkToS16(desc.fWidth), SkToS16(desc.fHeight))); layer->setLocked(true); - return false; + return true; } void GrLayerCache::unlock(GrCachedLayer* layer) { @@ -228,7 +229,7 @@ void GrLayerCache::unlock(GrCachedLayer* layer) { fPlotLocks[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 0 +#if DISABLE_CACHING // 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 @@ -264,7 +265,9 @@ void GrLayerCache::validate() const { if (NULL != pictInfo) { // In aggressive cleanup mode a picture info should only exist if // it has some atlased layers +#if !DISABLE_CACHING SkASSERT(!pictInfo->fPlotUsage.isEmpty()); +#endif } else { // If there is no picture info for this layer then all of its // layers should be non-atlased. @@ -341,39 +344,57 @@ bool GrLayerCache::purgePlot() { continue; } - // We need to find all the layers in 'plot' and remove them. - SkTDArray<GrCachedLayer*> toBeRemoved; + this->purgePlot(plot); + return true; + } - SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); - for (; !iter.done(); ++iter) { - if (plot == (*iter).plot()) { - *toBeRemoved.append() = &(*iter); - } + return false; +} + +void GrLayerCache::purgePlot(GrPlot* 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(!toBeRemoved[i]->locked()); + for (int i = 0; i < toBeRemoved.count(); ++i) { + SkASSERT(!toBeRemoved[i]->locked()); - GrPictureInfo* pictInfo = fPictureHash.find(toBeRemoved[i]->pictureID()); - SkASSERT(NULL != pictInfo); + GrPictureInfo* pictInfo = fPictureHash.find(toBeRemoved[i]->pictureID()); + SkASSERT(NULL != pictInfo); - GrAtlas::RemovePlot(&pictInfo->fPlotUsage, plot); + GrAtlas::RemovePlot(&pictInfo->fPlotUsage, plot); - // Aggressively remove layers and, if now totally uncached, picture info - fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); - SkDELETE(toBeRemoved[i]); + // Aggressively remove layers and, if now totally uncached, picture info + fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); + SkDELETE(toBeRemoved[i]); - if (pictInfo->fPlotUsage.isEmpty()) { - fPictureHash.remove(pictInfo->fPictureID); - SkDELETE(pictInfo); - } + if (pictInfo->fPlotUsage.isEmpty()) { + fPictureHash.remove(pictInfo->fPictureID); + SkDELETE(pictInfo); } - - plot->resetRects(); - return true; } - return false; + plot->resetRects(); +} + +void GrLayerCache::purgeAll() { + GrAtlas::PlotIter iter; + GrPlot* plot; + for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder); + NULL != plot; + plot = iter.prev()) { + SkASSERT(0 == fPlotLocks[plot->id()]); + + this->purgePlot(plot); + } } class GrPictureDeletionListener : public SkPicture::DeletionListener { diff --git a/src/gpu/GrLayerCache.h b/src/gpu/GrLayerCache.h index f027a26cbc..fcf62f9c3a 100644 --- a/src/gpu/GrLayerCache.h +++ b/src/gpu/GrLayerCache.h @@ -117,7 +117,7 @@ public: const GrIRect16& rect() const { return fRect; } void setPlot(GrPlot* plot) { - SkASSERT(NULL == fPlot); + SkASSERT(NULL == plot || NULL == fPlot); fPlot = plot; } GrPlot* plot() { return fPlot; } @@ -171,16 +171,15 @@ public: // elements by the GrContext void freeAll(); - GrCachedLayer* findLayer(const SkPicture* picture, int start, int stop, const SkMatrix& ctm); - GrCachedLayer* findLayerOrCreate(const SkPicture* picture, + GrCachedLayer* findLayer(uint32_t pictureID, int start, int stop, const SkMatrix& ctm); + GrCachedLayer* findLayerOrCreate(uint32_t pictureID, int start, int stop, const SkMatrix& ctm); - - // Inform the cache that layer's cached image is now required. Return true - // if it was found in the ResourceCache and doesn't need to be regenerated. - // If false is returned the caller should (re)render the layer into the - // newly acquired texture. - bool lock(GrCachedLayer* layer, const GrTextureDesc& desc); + + // Inform the cache that layer's cached image is now required. + // Return true if the layer must be re-rendered. Return false if the + // layer was found in the cache and can be reused. + bool lock(GrCachedLayer* layer, const GrTextureDesc& desc, bool dontAtlas); // Inform the cache that layer's cached image is not currently required void unlock(GrCachedLayer* layer); @@ -228,7 +227,10 @@ private: int fPlotLocks[kNumPlotsX * kNumPlotsY]; void initAtlas(); - GrCachedLayer* createLayer(const SkPicture* picture, int start, int stop, const SkMatrix& ctm); + GrCachedLayer* createLayer(uint32_t pictureID, int start, int stop, const SkMatrix& ctm); + +public: + void purgeAll(); // Remove all the layers (and unlock any resources) associated with 'pictureID' void purge(uint32_t pictureID); @@ -237,6 +239,8 @@ private: return width <= kPlotWidth && height <= kPlotHeight; } + void purgePlot(GrPlot* plot); + // Try to find a purgeable plot and clear it out. Return true if a plot // was purged; false otherwise. bool purgePlot(); diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index e459a116df..64439a1882 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -1989,7 +1989,7 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture if (pullForward[i]) { const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i); - GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture, + GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture->uniqueID(), info.fSaveLayerOpID, info.fRestoreOpID, info.fCTM); @@ -2007,7 +2007,8 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture desc.fConfig = kSkia8888_GrPixelConfig; // TODO: need to deal with sample count - bool needsRendering = !fContext->getLayerCache()->lock(layer, desc); + bool needsRendering = fContext->getLayerCache()->lock(layer, desc, + info.fHasNestedLayers || info.fIsNested); if (NULL == layer->texture()) { continue; } @@ -2126,13 +2127,22 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture for (int i = 0; i < gpuData->numSaveLayers(); ++i) { const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i); - GrCachedLayer* layer = fContext->getLayerCache()->findLayer(picture, + GrCachedLayer* layer = fContext->getLayerCache()->findLayer(picture->uniqueID(), info.fSaveLayerOpID, info.fRestoreOpID, info.fCTM); fContext->getLayerCache()->unlock(layer); } +#if DISABLE_CACHING + // 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 + fContext->getLayerCache()->purge(picture->uniqueID()); + + fContext->getLayerCache()->purgeAll(); +#endif + return true; } diff --git a/tests/GpuLayerCacheTest.cpp b/tests/GpuLayerCacheTest.cpp index 789854cf1f..5e18197ed7 100644 --- a/tests/GpuLayerCacheTest.cpp +++ b/tests/GpuLayerCacheTest.cpp @@ -31,11 +31,11 @@ static void create_layers(skiatest::Reporter* reporter, int idOffset) { for (int i = 0; i < numToAdd; ++i) { - GrCachedLayer* layer = cache->findLayerOrCreate(&picture, + GrCachedLayer* layer = cache->findLayerOrCreate(picture.uniqueID(), idOffset+i+1, idOffset+i+2, SkMatrix::I()); REPORTER_ASSERT(reporter, NULL != layer); - GrCachedLayer* temp = cache->findLayer(&picture, idOffset+i+1, idOffset+i+2, SkMatrix::I()); + GrCachedLayer* temp = cache->findLayer(picture.uniqueID(), idOffset+i+1, idOffset+i+2, SkMatrix::I()); REPORTER_ASSERT(reporter, temp == layer); REPORTER_ASSERT(reporter, TestingAccess::NumLayers(cache) == idOffset + i + 1); @@ -60,11 +60,11 @@ static void lock_layer(skiatest::Reporter* reporter, desc.fHeight = 512; desc.fConfig = kSkia8888_GrPixelConfig; - bool foundInCache = cache->lock(layer, desc); - REPORTER_ASSERT(reporter, !foundInCache); + bool needsRerendering = cache->lock(layer, desc, false); + REPORTER_ASSERT(reporter, needsRerendering); - foundInCache = cache->lock(layer, desc); - REPORTER_ASSERT(reporter, foundInCache); + needsRerendering = cache->lock(layer, desc, false); + REPORTER_ASSERT(reporter, !needsRerendering); REPORTER_ASSERT(reporter, NULL != layer->texture()); REPORTER_ASSERT(reporter, layer->locked()); @@ -99,7 +99,7 @@ DEF_GPUTEST(GpuLayerCache, reporter, factory) { create_layers(reporter, &cache, *picture, kInitialNumLayers, 0); for (int i = 0; i < kInitialNumLayers; ++i) { - GrCachedLayer* layer = cache.findLayer(picture, i+1, i+2, SkMatrix::I()); + GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, i+2, SkMatrix::I()); REPORTER_ASSERT(reporter, NULL != layer); lock_layer(reporter, &cache, layer); @@ -116,14 +116,14 @@ DEF_GPUTEST(GpuLayerCache, reporter, factory) { // Unlock the textures for (int i = 0; i < kInitialNumLayers; ++i) { - GrCachedLayer* layer = cache.findLayer(picture, i+1, i+2, SkMatrix::I()); + GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, i+2, SkMatrix::I()); REPORTER_ASSERT(reporter, NULL != layer); cache.unlock(layer); } for (int i = 0; i < kInitialNumLayers; ++i) { - GrCachedLayer* layer = cache.findLayer(picture, i+1, i+2, SkMatrix::I()); + GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, i+2, SkMatrix::I()); REPORTER_ASSERT(reporter, NULL != layer); REPORTER_ASSERT(reporter, !layer->locked()); @@ -142,7 +142,7 @@ DEF_GPUTEST(GpuLayerCache, reporter, factory) { // Add an additional layer. Since all the layers are unlocked this // will force out the first atlased layer create_layers(reporter, &cache, *picture, 1, kInitialNumLayers); - GrCachedLayer* layer = cache.findLayer(picture, + GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), kInitialNumLayers+1, kInitialNumLayers+2, SkMatrix::I()); REPORTER_ASSERT(reporter, NULL != layer); @@ -152,7 +152,7 @@ DEF_GPUTEST(GpuLayerCache, reporter, factory) { } for (int i = 0; i < kInitialNumLayers+1; ++i) { - GrCachedLayer* layer = cache.findLayer(picture, i+1, i+2, SkMatrix::I()); + GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, i+2, SkMatrix::I()); // 3 old layers plus the new one should be in the atlas. if (1 == i || 2 == i || 3 == i || 5 == i) { REPORTER_ASSERT(reporter, NULL != layer); |