aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar robertphillips <robertphillips@google.com>2014-07-17 08:26:44 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-07-17 08:26:44 -0700
commit261b8a98dc7378989ba8fa9c06b728e89162862b (patch)
tree05a4ed0b8d35af3af35ab51c68b6bad0b6f6375e /src
parenta8f774549e35b743afae35e3436f73e8849e869d (diff)
Make GrLayerCache use multiple plots in its atlas
Until we have a recycling Rectanizer the atlas purging must occur at the GrPlot level. This CL breaks the atlas into four plots to give some room for purging (without trashing the entire atlas). This is calved off of (Add atlased layer purging - https://codereview.chromium.org/367073002/) R=jvanverth@google.com Author: robertphillips@google.com Review URL: https://codereview.chromium.org/397873004
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrLayerCache.cpp87
-rw-r--r--src/gpu/GrLayerCache.h47
2 files changed, 109 insertions, 25 deletions
diff --git a/src/gpu/GrLayerCache.cpp b/src/gpu/GrLayerCache.cpp
index 9688cac650..ff26750df7 100644
--- a/src/gpu/GrLayerCache.cpp
+++ b/src/gpu/GrLayerCache.cpp
@@ -41,8 +41,33 @@ private:
int fLayerID;
};
+/**
+ * PictureKey just wraps a picture's unique ID for GrTHashTable. It is used to
+ * look up a picture's GrPictureInfo (i.e., its GrPlot usage).
+ */
+class GrLayerCache::PictureKey {
+public:
+ PictureKey(uint32_t pictureID) : fPictureID(pictureID) { }
+
+ uint32_t pictureID() const { return fPictureID; }
+
+ uint32_t getHash() const { return fPictureID; }
+
+ static bool LessThan(const GrPictureInfo& pictInfo, const PictureKey& key) {
+ return pictInfo.fPictureID < key.pictureID();
+ }
+
+ static bool Equals(const GrPictureInfo& pictInfo, const PictureKey& key) {
+ return pictInfo.fPictureID == key.pictureID();
+
+ }
+
+private:
+ uint32_t fPictureID;
+};
+
#ifdef SK_DEBUG
-void GrCachedLayer::validate(GrTexture* backingTexture) const {
+void GrCachedLayer::validate(const GrTexture* backingTexture) const {
SkASSERT(SK_InvalidGenID != fPictureID);
SkASSERT(-1 != fLayerID);
@@ -55,6 +80,14 @@ void GrCachedLayer::validate(GrTexture* backingTexture) const {
}
} else {
SkASSERT(fRect.isEmpty());
+ SkASSERT(NULL == fPlot);
+ }
+
+ if (NULL != fPlot) {
+ // If a layer has a plot (i.e., is atlased) then it must point to
+ // the backing texture. Additionally, its rect should be non-empty.
+ SkASSERT(NULL != fTexture && backingTexture == fTexture);
+ SkASSERT(!fRect.isEmpty());
}
}
@@ -72,9 +105,13 @@ public:
fLayer->validate(fBackingTexture);
}
}
+ void setBackingTexture(GrTexture* backingTexture) {
+ SkASSERT(NULL == fBackingTexture || fBackingTexture == backingTexture);
+ fBackingTexture = backingTexture;
+ }
private:
- GrTexture* fBackingTexture;
+ const GrTexture* fBackingTexture;
const GrCachedLayer* fLayer;
};
#endif
@@ -106,7 +143,7 @@ void GrLayerCache::initAtlas() {
SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight);
fAtlas.reset(SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kSkia8888_GrPixelConfig,
kRenderTarget_GrTextureFlagBit,
- textureSize, 1, 1, false)));
+ textureSize, kNumPlotsX, kNumPlotsY, false)));
}
void GrLayerCache::freeAll() {
@@ -165,14 +202,26 @@ bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) {
}
#if USE_ATLAS
- SkIPoint16 loc;
- GrPlot* plot = fAtlas->addToAtlas(&fPlotUsage, desc.fWidth, desc.fHeight, NULL, &loc);
- if (NULL != plot) {
- GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY,
- SkToS16(desc.fWidth), SkToS16(desc.fHeight));
- layer->setTexture(fAtlas->getTexture(), bounds);
- layer->setAtlased(true);
- return false;
+ {
+ GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(layer->pictureID()));
+ if (NULL == pictInfo) {
+ pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID()));
+ fPictureHash.insert(PictureKey(layer->pictureID()), pictInfo);
+ }
+
+ SkIPoint16 loc;
+ GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage,
+ desc.fWidth, desc.fHeight,
+ NULL, &loc);
+ // addToAtlas can allocate the backing texture
+ SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture()));
+ if (NULL != plot) {
+ GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY,
+ SkToS16(desc.fWidth), SkToS16(desc.fHeight));
+ layer->setTexture(fAtlas->getTexture(), bounds);
+ layer->setPlot(plot);
+ return false;
+ }
}
#endif
@@ -192,9 +241,13 @@ void GrLayerCache::unlock(GrCachedLayer* layer) {
}
if (layer->isAtlased()) {
- // The atlas doesn't currently use a scratch texture (and we would have
- // to free up space differently anyways)
- // TODO: unlock atlas space when a recycling rectanizer is available
+ SkASSERT(layer->texture() == fAtlas->getTexture());
+
+ GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(layer->pictureID()));
+ SkASSERT(NULL != pictInfo);
+ pictInfo->fPlotUsage.isEmpty(); // just to silence compiler warnings for the time being
+
+ // TODO: purging from atlas goes here
} else {
fContext->unlockScratchTexture(layer->texture());
layer->setTexture(NULL, GrIRect16::MakeEmpty());
@@ -247,4 +300,10 @@ void GrLayerCache::purge(const SkPicture* picture) {
fLayerHash.remove(key, toBeRemoved[i]);
SkDELETE(toBeRemoved[i]);
}
+
+ GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(picture->uniqueID()));
+ if (NULL != pictInfo) {
+ fPictureHash.remove(PictureKey(picture->uniqueID()), pictInfo);
+ SkDELETE(pictInfo);
+ }
}
diff --git a/src/gpu/GrLayerCache.h b/src/gpu/GrLayerCache.h
index 566a738279..347fa232ab 100644
--- a/src/gpu/GrLayerCache.h
+++ b/src/gpu/GrLayerCache.h
@@ -16,20 +16,29 @@
#include "GrPictureUtils.h"
#include "GrRect.h"
-class GrGpu;
class SkPicture;
+// GrPictureInfo stores the atlas plots used by a single picture. A single
+// plot may be used to store layers from multiple pictures.
+struct GrPictureInfo {
+public:
+ GrPictureInfo(uint32_t pictureID) : fPictureID(pictureID) { }
+
+ uint32_t fPictureID;
+
+ GrAtlas::ClientPlotUsage fPlotUsage;
+};
+
// GrCachedLayer encapsulates the caching information for a single saveLayer.
//
// Atlased layers get a ref to the backing GrTexture while non-atlased layers
// get a ref to the GrTexture in which they reside. In both cases 'fRect'
// contains the layer's extent in its texture.
-//
-// TODO: can we easily reuse the empty space in the non-atlased GrTexture's?
+// Atlased layers also get a pointer to the plot in which they reside.
struct GrCachedLayer {
public:
GrCachedLayer(uint32_t pictureID, int layerID)
- : fAtlased(false) {
+ : fPlot(NULL) {
fPictureID = pictureID;
fLayerID = layerID;
fTexture = NULL;
@@ -51,10 +60,15 @@ public:
GrTexture* texture() { return fTexture; }
const GrIRect16& rect() const { return fRect; }
- void setAtlased(bool atlased) { fAtlased = atlased; }
- bool isAtlased() const { return fAtlased; }
+ void setPlot(GrPlot* plot) {
+ SkASSERT(NULL == fPlot);
+ fPlot = plot;
+ }
+ GrPlot* plot() { return fPlot; }
+
+ bool isAtlased() const { return NULL != fPlot; }
- SkDEBUGCODE(void validate(GrTexture* backingTexture) const;)
+ SkDEBUGCODE(void validate(const GrTexture* backingTexture) const;)
private:
// ID of the picture of which this layer is a part
@@ -69,13 +83,14 @@ private:
// non-NULL, that means that the texture is locked in the texture cache.
GrTexture* fTexture;
- // True if this layer is in an atlas; false otherwise.
- bool fAtlased;
-
// For both atlased and non-atlased layers 'fRect' contains the bound of
// the layer in whichever texture it resides. It is empty when 'fTexture'
// is NULL.
GrIRect16 fRect;
+
+ // For atlased layers, fPlot stores the atlas plot in which the layer rests.
+ // It is always NULL for non-atlased layers.
+ GrPlot* fPlot;
};
// The GrLayerCache caches pre-computed saveLayers for later rendering.
@@ -112,9 +127,19 @@ public:
SkDEBUGCODE(void validate() const;)
private:
+ static const int kNumPlotsX = 2;
+ static const int kNumPlotsY = 2;
+
GrContext* fContext; // pointer back to owning context
SkAutoTDelete<GrAtlas> fAtlas; // TODO: could lazily allocate
- GrAtlas::ClientPlotUsage fPlotUsage;
+
+ // We cache this information here (rather then, say, on the owning picture)
+ // because we want to be able to clean it up as needed (e.g., if a picture
+ // is leaked and never cleans itself up we still want to be able to
+ // remove the GrPictureInfo once its layers are purged from all the atlas
+ // plots).
+ class PictureKey;
+ GrTHashTable<GrPictureInfo, PictureKey, 7> fPictureHash;
class PictureLayerKey;
GrTHashTable<GrCachedLayer, PictureLayerKey, 7> fLayerHash;