aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/gpu/GrLayerCache.cpp105
-rw-r--r--src/gpu/GrLayerCache.h24
-rw-r--r--src/gpu/SkGpuDevice.cpp16
-rw-r--r--tests/GpuLayerCacheTest.cpp22
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);