Index: src/gpu/GrLayerCache.cpp |
diff --git a/src/gpu/GrLayerCache.cpp b/src/gpu/GrLayerCache.cpp |
index 9688cac650d094fbc4ebc169a24e70d8e3fd577e..ff26750df764cc1b1a33bcee0fee81096a42adc4 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 |
jvanverth1
2014/07/16 21:04:16
I don't think we're supposed to use GrTHashTable a
robertphillips
2014/07/17 11:57:45
Why don't I do that as a separate CL and just elim
|
+ * 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); |
+ } |
} |