Chromium Code Reviews| 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 114 const GrTexture* fBackingTexture; | 58 const GrTexture* fBackingTexture; |
| 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 class UnlockAndDeleteFunctor { |
| 125 SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 69 public: |
| 126 for (int i = 0; i < fLayerHash.count(); ++i) { | 70 UnlockAndDeleteFunctor(GrLayerCache* cache) : fCache(cache) {} |
|
mtklein
2014/07/17 20:23:29
Dead code now?
robertphillips
2014/07/18 15:00:36
Done.
| |
| 127 this->unlock(layerArray[i]); | 71 |
| 72 void operator()(GrCachedLayer& layer) { | |
| 73 fCache->unlock(&layer); | |
| 74 SkDELETE(&layer); | |
| 128 } | 75 } |
| 129 | 76 |
| 130 fLayerHash.deleteAll(); | 77 private: |
| 78 GrLayerCache* fCache; | |
| 79 }; | |
| 80 | |
| 81 GrLayerCache::~GrLayerCache() { | |
| 82 | |
| 83 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); | |
| 84 for (; !iter.done(); ++iter) { | |
| 85 GrCachedLayer* layer = &(*iter); | |
| 86 this->unlock(layer); | |
| 87 SkDELETE(layer); | |
| 88 } | |
| 131 | 89 |
| 132 // The atlas only lets go of its texture when the atlas is deleted. | 90 // The atlas only lets go of its texture when the atlas is deleted. |
| 133 fAtlas.free(); | 91 fAtlas.free(); |
| 134 } | 92 } |
| 135 | 93 |
| 136 void GrLayerCache::initAtlas() { | 94 void GrLayerCache::initAtlas() { |
| 137 static const int kAtlasTextureWidth = 1024; | 95 static const int kAtlasTextureWidth = 1024; |
| 138 static const int kAtlasTextureHeight = 1024; | 96 static const int kAtlasTextureHeight = 1024; |
| 139 | 97 |
| 140 SkASSERT(NULL == fAtlas.get()); | 98 SkASSERT(NULL == fAtlas.get()); |
| 141 | 99 |
| 142 // The layer cache only gets 1 plot | 100 // The layer cache only gets 1 plot |
| 143 SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight) ; | 101 SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight) ; |
| 144 fAtlas.reset(SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kSkia8888_GrPixelConfi g, | 102 fAtlas.reset(SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kSkia8888_GrPixelConfi g, |
| 145 kRenderTarget_GrTextureFlagBit, | 103 kRenderTarget_GrTextureFlagBit, |
| 146 textureSize, kNumPlotsX, kNumPlotsY, false ))); | 104 textureSize, kNumPlotsX, kNumPlotsY, false ))); |
| 147 } | 105 } |
| 148 | 106 |
| 149 void GrLayerCache::freeAll() { | 107 void GrLayerCache::freeAll() { |
| 150 SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 108 |
| 151 for (int i = 0; i < fLayerHash.count(); ++i) { | 109 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
| 152 this->unlock(layerArray[i]); | 110 for (; !iter.done(); ++iter) { |
| 111 GrCachedLayer* layer = &(*iter); | |
| 112 this->unlock(layer); | |
| 113 SkDELETE(layer); | |
| 153 } | 114 } |
| 154 | 115 fLayerHash.rewind(); |
| 155 fLayerHash.deleteAll(); | |
| 156 | 116 |
| 157 // The atlas only lets go of its texture when the atlas is deleted. | 117 // The atlas only lets go of its texture when the atlas is deleted. |
| 158 fAtlas.free(); | 118 fAtlas.free(); |
| 159 // GrLayerCache always assumes an atlas exists so recreate it. The atlas | 119 // GrLayerCache always assumes an atlas exists so recreate it. The atlas |
| 160 // lazily allocates a replacement texture so reallocating a new | 120 // lazily allocates a replacement texture so reallocating a new |
| 161 // atlas here won't disrupt a GrContext::contextDestroyed or freeGpuResource s. | 121 // atlas here won't disrupt a GrContext::contextDestroyed or freeGpuResource s. |
| 162 // TODO: Make GrLayerCache lazily allocate the atlas manager? | 122 // TODO: Make GrLayerCache lazily allocate the atlas manager? |
| 163 this->initAtlas(); | 123 this->initAtlas(); |
| 164 } | 124 } |
| 165 | 125 |
| 166 GrCachedLayer* GrLayerCache::createLayer(const SkPicture* picture, int layerID) { | 126 GrCachedLayer* GrLayerCache::createLayer(const SkPicture* picture, int layerID) { |
| 167 SkASSERT(picture->uniqueID() != SK_InvalidGenID); | 127 SkASSERT(picture->uniqueID() != SK_InvalidGenID && layerID >= 0); |
| 168 | 128 |
| 169 GrCachedLayer* layer = SkNEW_ARGS(GrCachedLayer, (picture->uniqueID(), layer ID)); | 129 GrCachedLayer* layer = SkNEW_ARGS(GrCachedLayer, (picture->uniqueID(), layer ID)); |
| 170 fLayerHash.insert(PictureLayerKey(picture->uniqueID(), layerID), layer); | 130 fLayerHash.add(layer); |
| 171 return layer; | 131 return layer; |
| 172 } | 132 } |
| 173 | 133 |
| 174 GrCachedLayer* GrLayerCache::findLayer(const SkPicture* picture, int layerID) { | 134 GrCachedLayer* GrLayerCache::findLayer(const SkPicture* picture, int layerID) { |
| 175 SkASSERT(picture->uniqueID() != SK_InvalidGenID); | 135 SkASSERT(picture->uniqueID() != SK_InvalidGenID && layerID >= 0); |
| 176 return fLayerHash.find(PictureLayerKey(picture->uniqueID(), layerID)); | 136 return fLayerHash.find(GrCachedLayer::Key(picture->uniqueID(), layerID)); |
| 177 } | 137 } |
| 178 | 138 |
| 179 GrCachedLayer* GrLayerCache::findLayerOrCreate(const SkPicture* picture, int lay erID) { | 139 GrCachedLayer* GrLayerCache::findLayerOrCreate(const SkPicture* picture, int lay erID) { |
| 180 SkASSERT(picture->uniqueID() != SK_InvalidGenID); | 140 SkASSERT(picture->uniqueID() != SK_InvalidGenID && layerID >= 0); |
| 181 GrCachedLayer* layer = fLayerHash.find(PictureLayerKey(picture->uniqueID(), layerID)); | 141 GrCachedLayer* layer = fLayerHash.find(GrCachedLayer::Key(picture->uniqueID( ), layerID)); |
| 182 if (NULL == layer) { | 142 if (NULL == layer) { |
| 183 layer = this->createLayer(picture, layerID); | 143 layer = this->createLayer(picture, layerID); |
| 184 } | 144 } |
| 185 | 145 |
| 186 return layer; | 146 return layer; |
| 187 } | 147 } |
| 188 | 148 |
| 189 bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) { | 149 bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) { |
| 190 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) | 150 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) |
| 191 | 151 |
| 192 if (NULL != layer->texture()) { | 152 if (NULL != layer->texture()) { |
| 193 // This layer is already locked | 153 // This layer is already locked |
| 194 #ifdef SK_DEBUG | 154 #ifdef SK_DEBUG |
| 195 if (layer->isAtlased()) { | 155 if (layer->isAtlased()) { |
| 196 // It claims to be atlased | 156 // It claims to be atlased |
| 197 SkASSERT(layer->rect().width() == desc.fWidth); | 157 SkASSERT(layer->rect().width() == desc.fWidth); |
| 198 SkASSERT(layer->rect().height() == desc.fHeight); | 158 SkASSERT(layer->rect().height() == desc.fHeight); |
| 199 } | 159 } |
| 200 #endif | 160 #endif |
| 201 return true; | 161 return true; |
| 202 } | 162 } |
| 203 | 163 |
| 204 #if USE_ATLAS | 164 #if USE_ATLAS |
| 205 { | 165 { |
| 206 GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(layer->pictureID( ))); | 166 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
| 207 if (NULL == pictInfo) { | 167 if (NULL == pictInfo) { |
| 208 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); | 168 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); |
| 209 fPictureHash.insert(PictureKey(layer->pictureID()), pictInfo); | 169 fPictureHash.add(pictInfo); |
| 210 } | 170 } |
| 211 | 171 |
| 212 SkIPoint16 loc; | 172 SkIPoint16 loc; |
| 213 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, | 173 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, |
| 214 desc.fWidth, desc.fHeight, | 174 desc.fWidth, desc.fHeight, |
| 215 NULL, &loc); | 175 NULL, &loc); |
| 216 // addToAtlas can allocate the backing texture | 176 // addToAtlas can allocate the backing texture |
| 217 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); | 177 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); |
| 218 if (NULL != plot) { | 178 if (NULL != plot) { |
| 219 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, | 179 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 236 void GrLayerCache::unlock(GrCachedLayer* layer) { | 196 void GrLayerCache::unlock(GrCachedLayer* layer) { |
| 237 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) | 197 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) |
| 238 | 198 |
| 239 if (NULL == layer || NULL == layer->texture()) { | 199 if (NULL == layer || NULL == layer->texture()) { |
| 240 return; | 200 return; |
| 241 } | 201 } |
| 242 | 202 |
| 243 if (layer->isAtlased()) { | 203 if (layer->isAtlased()) { |
| 244 SkASSERT(layer->texture() == fAtlas->getTexture()); | 204 SkASSERT(layer->texture() == fAtlas->getTexture()); |
| 245 | 205 |
| 246 GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(layer->pictureID( ))); | 206 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
| 247 SkASSERT(NULL != pictInfo); | 207 SkASSERT(NULL != pictInfo); |
| 248 pictInfo->fPlotUsage.isEmpty(); // just to silence compiler warnings for the time being | 208 pictInfo->fPlotUsage.isEmpty(); // just to silence compiler warnings for the time being |
| 249 | 209 |
| 250 // TODO: purging from atlas goes here | 210 // TODO: purging from atlas goes here |
| 251 } else { | 211 } else { |
| 252 fContext->unlockScratchTexture(layer->texture()); | 212 fContext->unlockScratchTexture(layer->texture()); |
| 253 layer->setTexture(NULL, GrIRect16::MakeEmpty()); | 213 layer->setTexture(NULL, GrIRect16::MakeEmpty()); |
| 254 } | 214 } |
| 255 } | 215 } |
| 256 | 216 |
| 257 #ifdef SK_DEBUG | 217 #ifdef SK_DEBUG |
| 258 void GrLayerCache::validate() const { | 218 void GrLayerCache::validate() const { |
| 259 const SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 219 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::ConstIter iter(&fLayerHas h); |
| 260 for (int i = 0; i < fLayerHash.count(); ++i) { | 220 for (; !iter.done(); ++iter) { |
| 261 layerArray[i]->validate(fAtlas->getTexture()); | 221 (*iter).validate(fAtlas->getTexture()); |
| 262 } | 222 } |
| 263 } | 223 } |
| 264 | 224 |
| 265 class GrAutoValidateCache : ::SkNoncopyable { | 225 class GrAutoValidateCache : ::SkNoncopyable { |
| 266 public: | 226 public: |
| 267 explicit GrAutoValidateCache(GrLayerCache* cache) | 227 explicit GrAutoValidateCache(GrLayerCache* cache) |
| 268 : fCache(cache) { | 228 : fCache(cache) { |
| 269 fCache->validate(); | 229 fCache->validate(); |
| 270 } | 230 } |
| 271 ~GrAutoValidateCache() { | 231 ~GrAutoValidateCache() { |
| 272 fCache->validate(); | 232 fCache->validate(); |
| 273 } | 233 } |
| 274 private: | 234 private: |
| 275 GrLayerCache* fCache; | 235 GrLayerCache* fCache; |
| 276 }; | 236 }; |
| 277 #endif | 237 #endif |
| 278 | 238 |
| 279 void GrLayerCache::purge(const SkPicture* picture) { | 239 void GrLayerCache::purge(const SkPicture* picture) { |
| 280 SkDEBUGCODE(GrAutoValidateCache avc(this);) | 240 SkDEBUGCODE(GrAutoValidateCache avc(this);) |
| 281 | 241 |
| 282 // This is somewhat of an abuse of GrTHashTable. We need to find all the | 242 // 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; | 243 SkTDArray<GrCachedLayer*> toBeRemoved; |
| 288 | 244 |
| 289 const SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 245 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
| 290 for (int i = 0; i < fLayerHash.count(); ++i) { | 246 for (; !iter.done(); ++iter) { |
| 291 if (picture->uniqueID() == layerArray[i]->pictureID()) { | 247 if (picture->uniqueID() == (*iter).pictureID()) { |
| 292 *toBeRemoved.append() = layerArray[i]; | 248 *toBeRemoved.append() = &(*iter); |
| 293 } | 249 } |
| 294 } | 250 } |
| 295 | 251 |
| 296 for (int i = 0; i < toBeRemoved.count(); ++i) { | 252 for (int i = 0; i < toBeRemoved.count(); ++i) { |
| 297 this->unlock(toBeRemoved[i]); | 253 this->unlock(toBeRemoved[i]); |
| 298 | 254 fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); |
| 299 PictureLayerKey key(picture->uniqueID(), toBeRemoved[i]->layerID()); | |
| 300 fLayerHash.remove(key, toBeRemoved[i]); | |
| 301 SkDELETE(toBeRemoved[i]); | 255 SkDELETE(toBeRemoved[i]); |
| 302 } | 256 } |
| 303 | 257 |
| 304 GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(picture->uniqueID())) ; | 258 GrPictureInfo* pictInfo = fPictureHash.find(picture->uniqueID()); |
| 305 if (NULL != pictInfo) { | 259 if (NULL != pictInfo) { |
| 306 fPictureHash.remove(PictureKey(picture->uniqueID()), pictInfo); | 260 fPictureHash.remove(picture->uniqueID()); |
| 307 SkDELETE(pictInfo); | 261 SkDELETE(pictInfo); |
| 308 } | 262 } |
| 309 } | 263 } |
| OLD | NEW |