| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrAtlas.h" | 8 #include "GrAtlas.h" |
| 9 #include "GrGpu.h" | 9 #include "GrGpu.h" |
| 10 #include "GrLayerCache.h" | 10 #include "GrLayerCache.h" |
| 11 | 11 |
| 12 /** | |
| 13 * PictureLayerKey just wraps a saveLayer's id in a picture for GrTHashTable. | |
| 14 */ | |
| 15 class GrLayerCache::PictureLayerKey { | |
| 16 public: | |
| 17 PictureLayerKey(uint32_t pictureID, int layerID) | |
| 18 : fPictureID(pictureID) | |
| 19 , fLayerID(layerID) { | |
| 20 } | |
| 21 | |
| 22 uint32_t pictureID() const { return fPictureID; } | |
| 23 int layerID() const { return fLayerID; } | |
| 24 | |
| 25 uint32_t getHash() const { return (fPictureID << 16) | fLayerID; } | |
| 26 | |
| 27 static bool LessThan(const GrCachedLayer& layer, const PictureLayerKey& key)
{ | |
| 28 if (layer.pictureID() == key.pictureID()) { | |
| 29 return layer.layerID() < key.layerID(); | |
| 30 } | |
| 31 | |
| 32 return layer.pictureID() < key.pictureID(); | |
| 33 } | |
| 34 | |
| 35 static bool Equals(const GrCachedLayer& layer, const PictureLayerKey& key) { | |
| 36 return layer.pictureID() == key.pictureID() && layer.layerID() == key.la
yerID(); | |
| 37 } | |
| 38 | |
| 39 private: | |
| 40 uint32_t fPictureID; | |
| 41 int fLayerID; | |
| 42 }; | |
| 43 | |
| 44 /** | |
| 45 * PictureKey just wraps a picture's unique ID for GrTHashTable. It is used to | |
| 46 * look up a picture's GrPictureInfo (i.e., its GrPlot usage). | |
| 47 */ | |
| 48 class GrLayerCache::PictureKey { | |
| 49 public: | |
| 50 PictureKey(uint32_t pictureID) : fPictureID(pictureID) { } | |
| 51 | |
| 52 uint32_t pictureID() const { return fPictureID; } | |
| 53 | |
| 54 uint32_t getHash() const { return fPictureID; } | |
| 55 | |
| 56 static bool LessThan(const GrPictureInfo& pictInfo, const PictureKey& key) { | |
| 57 return pictInfo.fPictureID < key.pictureID(); | |
| 58 } | |
| 59 | |
| 60 static bool Equals(const GrPictureInfo& pictInfo, const PictureKey& key) { | |
| 61 return pictInfo.fPictureID == key.pictureID(); | |
| 62 | |
| 63 } | |
| 64 | |
| 65 private: | |
| 66 uint32_t fPictureID; | |
| 67 }; | |
| 68 | |
| 69 #ifdef SK_DEBUG | 12 #ifdef SK_DEBUG |
| 70 void GrCachedLayer::validate(const GrTexture* backingTexture) const { | 13 void GrCachedLayer::validate(const GrTexture* backingTexture) const { |
| 71 SkASSERT(SK_InvalidGenID != fPictureID); | 14 SkASSERT(SK_InvalidGenID != fKey.getPictureID()); |
| 72 SkASSERT(-1 != fLayerID); | 15 SkASSERT(-1 != fKey.getLayerID()); |
| 16 |
| 73 | 17 |
| 74 if (NULL != fTexture) { | 18 if (NULL != fTexture) { |
| 75 // If the layer is in some texture then it must occupy some rectangle | 19 // If the layer is in some texture then it must occupy some rectangle |
| 76 SkASSERT(!fRect.isEmpty()); | 20 SkASSERT(!fRect.isEmpty()); |
| 77 if (!this->isAtlased()) { | 21 if (!this->isAtlased()) { |
| 78 // If it isn't atlased then the rectangle should start at the origin | 22 // If it isn't atlased then the rectangle should start at the origin |
| 79 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); | 23 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); |
| 80 } | 24 } |
| 81 } else { | 25 } else { |
| 82 SkASSERT(fRect.isEmpty()); | 26 SkASSERT(fRect.isEmpty()); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 const GrCachedLayer* fLayer; | 59 const GrCachedLayer* fLayer; |
| 116 }; | 60 }; |
| 117 #endif | 61 #endif |
| 118 | 62 |
| 119 GrLayerCache::GrLayerCache(GrContext* context) | 63 GrLayerCache::GrLayerCache(GrContext* context) |
| 120 : fContext(context) { | 64 : fContext(context) { |
| 121 this->initAtlas(); | 65 this->initAtlas(); |
| 122 } | 66 } |
| 123 | 67 |
| 124 GrLayerCache::~GrLayerCache() { | 68 GrLayerCache::~GrLayerCache() { |
| 125 SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 69 |
| 126 for (int i = 0; i < fLayerHash.count(); ++i) { | 70 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
| 127 this->unlock(layerArray[i]); | 71 for (; !iter.done(); ++iter) { |
| 72 GrCachedLayer* layer = &(*iter); |
| 73 this->unlock(layer); |
| 74 SkDELETE(layer); |
| 128 } | 75 } |
| 129 | 76 |
| 130 fLayerHash.deleteAll(); | |
| 131 | |
| 132 // The atlas only lets go of its texture when the atlas is deleted. | 77 // The atlas only lets go of its texture when the atlas is deleted. |
| 133 fAtlas.free(); | 78 fAtlas.free(); |
| 134 } | 79 } |
| 135 | 80 |
| 136 void GrLayerCache::initAtlas() { | 81 void GrLayerCache::initAtlas() { |
| 137 static const int kAtlasTextureWidth = 1024; | 82 static const int kAtlasTextureWidth = 1024; |
| 138 static const int kAtlasTextureHeight = 1024; | 83 static const int kAtlasTextureHeight = 1024; |
| 139 | 84 |
| 140 SkASSERT(NULL == fAtlas.get()); | 85 SkASSERT(NULL == fAtlas.get()); |
| 141 | 86 |
| 142 // The layer cache only gets 1 plot | 87 // The layer cache only gets 1 plot |
| 143 SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight)
; | 88 SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight)
; |
| 144 fAtlas.reset(SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kSkia8888_GrPixelConfi
g, | 89 fAtlas.reset(SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kSkia8888_GrPixelConfi
g, |
| 145 kRenderTarget_GrTextureFlagBit, | 90 kRenderTarget_GrTextureFlagBit, |
| 146 textureSize, kNumPlotsX, kNumPlotsY, false
))); | 91 textureSize, kNumPlotsX, kNumPlotsY, false
))); |
| 147 } | 92 } |
| 148 | 93 |
| 149 void GrLayerCache::freeAll() { | 94 void GrLayerCache::freeAll() { |
| 150 SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 95 |
| 151 for (int i = 0; i < fLayerHash.count(); ++i) { | 96 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
| 152 this->unlock(layerArray[i]); | 97 for (; !iter.done(); ++iter) { |
| 98 GrCachedLayer* layer = &(*iter); |
| 99 this->unlock(layer); |
| 100 SkDELETE(layer); |
| 153 } | 101 } |
| 154 | 102 fLayerHash.rewind(); |
| 155 fLayerHash.deleteAll(); | |
| 156 | 103 |
| 157 // The atlas only lets go of its texture when the atlas is deleted. | 104 // The atlas only lets go of its texture when the atlas is deleted. |
| 158 fAtlas.free(); | 105 fAtlas.free(); |
| 159 // GrLayerCache always assumes an atlas exists so recreate it. The atlas | 106 // GrLayerCache always assumes an atlas exists so recreate it. The atlas |
| 160 // lazily allocates a replacement texture so reallocating a new | 107 // lazily allocates a replacement texture so reallocating a new |
| 161 // atlas here won't disrupt a GrContext::contextDestroyed or freeGpuResource
s. | 108 // atlas here won't disrupt a GrContext::contextDestroyed or freeGpuResource
s. |
| 162 // TODO: Make GrLayerCache lazily allocate the atlas manager? | 109 // TODO: Make GrLayerCache lazily allocate the atlas manager? |
| 163 this->initAtlas(); | 110 this->initAtlas(); |
| 164 } | 111 } |
| 165 | 112 |
| 166 GrCachedLayer* GrLayerCache::createLayer(const SkPicture* picture, int layerID)
{ | 113 GrCachedLayer* GrLayerCache::createLayer(const SkPicture* picture, int layerID)
{ |
| 167 SkASSERT(picture->uniqueID() != SK_InvalidGenID); | 114 SkASSERT(picture->uniqueID() != SK_InvalidGenID && layerID >= 0); |
| 168 | 115 |
| 169 GrCachedLayer* layer = SkNEW_ARGS(GrCachedLayer, (picture->uniqueID(), layer
ID)); | 116 GrCachedLayer* layer = SkNEW_ARGS(GrCachedLayer, (picture->uniqueID(), layer
ID)); |
| 170 fLayerHash.insert(PictureLayerKey(picture->uniqueID(), layerID), layer); | 117 fLayerHash.add(layer); |
| 171 return layer; | 118 return layer; |
| 172 } | 119 } |
| 173 | 120 |
| 174 GrCachedLayer* GrLayerCache::findLayer(const SkPicture* picture, int layerID) { | 121 GrCachedLayer* GrLayerCache::findLayer(const SkPicture* picture, int layerID) { |
| 175 SkASSERT(picture->uniqueID() != SK_InvalidGenID); | 122 SkASSERT(picture->uniqueID() != SK_InvalidGenID && layerID >= 0); |
| 176 return fLayerHash.find(PictureLayerKey(picture->uniqueID(), layerID)); | 123 return fLayerHash.find(GrCachedLayer::Key(picture->uniqueID(), layerID)); |
| 177 } | 124 } |
| 178 | 125 |
| 179 GrCachedLayer* GrLayerCache::findLayerOrCreate(const SkPicture* picture, int lay
erID) { | 126 GrCachedLayer* GrLayerCache::findLayerOrCreate(const SkPicture* picture, int lay
erID) { |
| 180 SkASSERT(picture->uniqueID() != SK_InvalidGenID); | 127 SkASSERT(picture->uniqueID() != SK_InvalidGenID && layerID >= 0); |
| 181 GrCachedLayer* layer = fLayerHash.find(PictureLayerKey(picture->uniqueID(),
layerID)); | 128 GrCachedLayer* layer = fLayerHash.find(GrCachedLayer::Key(picture->uniqueID(
), layerID)); |
| 182 if (NULL == layer) { | 129 if (NULL == layer) { |
| 183 layer = this->createLayer(picture, layerID); | 130 layer = this->createLayer(picture, layerID); |
| 184 } | 131 } |
| 185 | 132 |
| 186 return layer; | 133 return layer; |
| 187 } | 134 } |
| 188 | 135 |
| 189 bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) { | 136 bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) { |
| 190 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) | 137 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) |
| 191 | 138 |
| 192 if (NULL != layer->texture()) { | 139 if (NULL != layer->texture()) { |
| 193 // This layer is already locked | 140 // This layer is already locked |
| 194 #ifdef SK_DEBUG | 141 #ifdef SK_DEBUG |
| 195 if (layer->isAtlased()) { | 142 if (layer->isAtlased()) { |
| 196 // It claims to be atlased | 143 // It claims to be atlased |
| 197 SkASSERT(layer->rect().width() == desc.fWidth); | 144 SkASSERT(layer->rect().width() == desc.fWidth); |
| 198 SkASSERT(layer->rect().height() == desc.fHeight); | 145 SkASSERT(layer->rect().height() == desc.fHeight); |
| 199 } | 146 } |
| 200 #endif | 147 #endif |
| 201 return true; | 148 return true; |
| 202 } | 149 } |
| 203 | 150 |
| 204 #if USE_ATLAS | 151 #if USE_ATLAS |
| 205 { | 152 { |
| 206 GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(layer->pictureID(
))); | 153 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
| 207 if (NULL == pictInfo) { | 154 if (NULL == pictInfo) { |
| 208 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); | 155 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); |
| 209 fPictureHash.insert(PictureKey(layer->pictureID()), pictInfo); | 156 fPictureHash.add(pictInfo); |
| 210 } | 157 } |
| 211 | 158 |
| 212 SkIPoint16 loc; | 159 SkIPoint16 loc; |
| 213 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, | 160 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, |
| 214 desc.fWidth, desc.fHeight, | 161 desc.fWidth, desc.fHeight, |
| 215 NULL, &loc); | 162 NULL, &loc); |
| 216 // addToAtlas can allocate the backing texture | 163 // addToAtlas can allocate the backing texture |
| 217 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); | 164 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); |
| 218 if (NULL != plot) { | 165 if (NULL != plot) { |
| 219 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, | 166 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 236 void GrLayerCache::unlock(GrCachedLayer* layer) { | 183 void GrLayerCache::unlock(GrCachedLayer* layer) { |
| 237 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) | 184 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) |
| 238 | 185 |
| 239 if (NULL == layer || NULL == layer->texture()) { | 186 if (NULL == layer || NULL == layer->texture()) { |
| 240 return; | 187 return; |
| 241 } | 188 } |
| 242 | 189 |
| 243 if (layer->isAtlased()) { | 190 if (layer->isAtlased()) { |
| 244 SkASSERT(layer->texture() == fAtlas->getTexture()); | 191 SkASSERT(layer->texture() == fAtlas->getTexture()); |
| 245 | 192 |
| 246 GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(layer->pictureID(
))); | 193 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
| 247 SkASSERT(NULL != pictInfo); | 194 SkASSERT(NULL != pictInfo); |
| 248 pictInfo->fPlotUsage.isEmpty(); // just to silence compiler warnings for
the time being | 195 pictInfo->fPlotUsage.isEmpty(); // just to silence compiler warnings for
the time being |
| 249 | 196 |
| 250 // TODO: purging from atlas goes here | 197 // TODO: purging from atlas goes here |
| 251 } else { | 198 } else { |
| 252 fContext->unlockScratchTexture(layer->texture()); | 199 fContext->unlockScratchTexture(layer->texture()); |
| 253 layer->setTexture(NULL, GrIRect16::MakeEmpty()); | 200 layer->setTexture(NULL, GrIRect16::MakeEmpty()); |
| 254 } | 201 } |
| 255 } | 202 } |
| 256 | 203 |
| 257 #ifdef SK_DEBUG | 204 #ifdef SK_DEBUG |
| 258 void GrLayerCache::validate() const { | 205 void GrLayerCache::validate() const { |
| 259 const SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 206 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::ConstIter iter(&fLayerHas
h); |
| 260 for (int i = 0; i < fLayerHash.count(); ++i) { | 207 for (; !iter.done(); ++iter) { |
| 261 layerArray[i]->validate(fAtlas->getTexture()); | 208 (*iter).validate(fAtlas->getTexture()); |
| 262 } | 209 } |
| 263 } | 210 } |
| 264 | 211 |
| 265 class GrAutoValidateCache : ::SkNoncopyable { | 212 class GrAutoValidateCache : ::SkNoncopyable { |
| 266 public: | 213 public: |
| 267 explicit GrAutoValidateCache(GrLayerCache* cache) | 214 explicit GrAutoValidateCache(GrLayerCache* cache) |
| 268 : fCache(cache) { | 215 : fCache(cache) { |
| 269 fCache->validate(); | 216 fCache->validate(); |
| 270 } | 217 } |
| 271 ~GrAutoValidateCache() { | 218 ~GrAutoValidateCache() { |
| 272 fCache->validate(); | 219 fCache->validate(); |
| 273 } | 220 } |
| 274 private: | 221 private: |
| 275 GrLayerCache* fCache; | 222 GrLayerCache* fCache; |
| 276 }; | 223 }; |
| 277 #endif | 224 #endif |
| 278 | 225 |
| 279 void GrLayerCache::purge(const SkPicture* picture) { | 226 void GrLayerCache::purge(const SkPicture* picture) { |
| 280 SkDEBUGCODE(GrAutoValidateCache avc(this);) | 227 SkDEBUGCODE(GrAutoValidateCache avc(this);) |
| 281 | 228 |
| 282 // This is somewhat of an abuse of GrTHashTable. We need to find all the | 229 // We need to find all the layers associated with 'picture' and remove them. |
| 283 // layers associated with 'picture' but the usual hash calls only look for | |
| 284 // exact key matches. This code peeks into the hash table's innards to | |
| 285 // find all the 'picture'-related layers. | |
| 286 // TODO: use a different data structure for the layer hash? | |
| 287 SkTDArray<GrCachedLayer*> toBeRemoved; | 230 SkTDArray<GrCachedLayer*> toBeRemoved; |
| 288 | 231 |
| 289 const SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 232 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
| 290 for (int i = 0; i < fLayerHash.count(); ++i) { | 233 for (; !iter.done(); ++iter) { |
| 291 if (picture->uniqueID() == layerArray[i]->pictureID()) { | 234 if (picture->uniqueID() == (*iter).pictureID()) { |
| 292 *toBeRemoved.append() = layerArray[i]; | 235 *toBeRemoved.append() = &(*iter); |
| 293 } | 236 } |
| 294 } | 237 } |
| 295 | 238 |
| 296 for (int i = 0; i < toBeRemoved.count(); ++i) { | 239 for (int i = 0; i < toBeRemoved.count(); ++i) { |
| 297 this->unlock(toBeRemoved[i]); | 240 this->unlock(toBeRemoved[i]); |
| 298 | 241 fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); |
| 299 PictureLayerKey key(picture->uniqueID(), toBeRemoved[i]->layerID()); | |
| 300 fLayerHash.remove(key, toBeRemoved[i]); | |
| 301 SkDELETE(toBeRemoved[i]); | 242 SkDELETE(toBeRemoved[i]); |
| 302 } | 243 } |
| 303 | 244 |
| 304 GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(picture->uniqueID()))
; | 245 GrPictureInfo* pictInfo = fPictureHash.find(picture->uniqueID()); |
| 305 if (NULL != pictInfo) { | 246 if (NULL != pictInfo) { |
| 306 fPictureHash.remove(PictureKey(picture->uniqueID()), pictInfo); | 247 fPictureHash.remove(picture->uniqueID()); |
| 307 SkDELETE(pictInfo); | 248 SkDELETE(pictInfo); |
| 308 } | 249 } |
| 309 } | 250 } |
| OLD | NEW |