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 DECLARE_SKMESSAGEBUS_MESSAGE(GrPictureDeletedMessage); | 12 DECLARE_SKMESSAGEBUS_MESSAGE(GrPictureDeletedMessage); |
| 13 | 13 |
| 14 #ifdef SK_DEBUG | 14 #ifdef SK_DEBUG |
| 15 void GrCachedLayer::validate(const GrTexture* backingTexture) const { | 15 void GrCachedLayer::validate(const GrTexture* backingTexture) const { |
| 16 SkASSERT(SK_InvalidGenID != fKey.pictureID()); | 16 SkASSERT(SK_InvalidGenID != fKey.pictureID()); |
| 17 SkASSERT(fKey.start() >= 0); | 17 SkASSERT(fKey.start() >= 0); |
| 18 | 18 |
| 19 | |
| 20 if (fTexture) { | 19 if (fTexture) { |
| 21 // If the layer is in some texture then it must occupy some rectangle | 20 // If the layer is in some texture then it must occupy some rectangle |
| 22 SkASSERT(!fRect.isEmpty()); | 21 SkASSERT(!fRect.isEmpty()); |
| 23 if (!this->isAtlased()) { | 22 if (!this->isAtlased()) { |
| 24 // If it isn't atlased then the rectangle should start at the origin | 23 // If it isn't atlased then the rectangle should start at the origin |
| 25 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); | 24 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); |
| 26 } | 25 } |
| 27 } else { | 26 } else { |
| 28 SkASSERT(fRect.isEmpty()); | 27 SkASSERT(fRect.isEmpty()); |
| 29 SkASSERT(NULL == fPlot); | 28 SkASSERT(NULL == fPlot); |
| 30 SkASSERT(!fLocked); // layers without a texture cannot be locked | 29 SkASSERT(!fLocked); // layers without a texture cannot be locked |
| 31 } | 30 } |
| 32 | 31 |
| 33 if (fPlot) { | 32 if (fPlot) { |
| 34 // If a layer has a plot (i.e., is atlased) then it must point to | 33 // If a layer has a plot (i.e., is atlased) then it must point to |
| 35 // the backing texture. Additionally, its rect should be non-empty. | 34 // the backing texture. Additionally, its rect should be non-empty. |
| 36 SkASSERT(fTexture && backingTexture == fTexture); | 35 SkASSERT(fTexture && backingTexture == fTexture); |
| 37 SkASSERT(!fRect.isEmpty()); | 36 SkASSERT(!fRect.isEmpty()); |
| 38 } | 37 } |
| 39 | 38 |
| 40 if (fLocked) { | 39 if (fLocked) { |
| 41 // If a layer is locked it must have a texture (though it need not be | 40 // If a layer is locked it must have a texture (though it need not be |
| 42 // the atlas-backing texture) and occupy some space. | 41 // the atlas-backing texture) and occupy some space. |
| 43 SkASSERT(fTexture); | 42 SkASSERT(fTexture); |
| 44 SkASSERT(!fRect.isEmpty()); | 43 SkASSERT(!fRect.isEmpty()); |
| 45 } | 44 } |
| 45 | |
| 46 // Unfortunately there is a brief time where a layer can be locked | |
| 47 // but not used. | |
|
jvanverth1
2014/10/10 18:21:44
This comment is a little confusing. Maybe "There i
robertphillips
2014/10/10 18:37:43
Done.
| |
| 48 if (fUses > 0) { | |
| 49 SkASSERT(fLocked); | |
| 50 } else { | |
| 51 SkASSERT(0 == fUses); | |
| 52 } | |
| 46 } | 53 } |
| 47 | 54 |
| 48 class GrAutoValidateLayer : ::SkNoncopyable { | 55 class GrAutoValidateLayer : ::SkNoncopyable { |
| 49 public: | 56 public: |
| 50 GrAutoValidateLayer(GrTexture* backingTexture, const GrCachedLayer* layer) | 57 GrAutoValidateLayer(GrTexture* backingTexture, const GrCachedLayer* layer) |
| 51 : fBackingTexture(backingTexture) | 58 : fBackingTexture(backingTexture) |
| 52 , fLayer(layer) { | 59 , fLayer(layer) { |
| 53 if (fLayer) { | 60 if (fLayer) { |
| 54 fLayer->validate(backingTexture); | 61 fLayer->validate(backingTexture); |
| 55 } | 62 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 74 : fContext(context) { | 81 : fContext(context) { |
| 75 this->initAtlas(); | 82 this->initAtlas(); |
| 76 memset(fPlotLocks, 0, sizeof(fPlotLocks)); | 83 memset(fPlotLocks, 0, sizeof(fPlotLocks)); |
| 77 } | 84 } |
| 78 | 85 |
| 79 GrLayerCache::~GrLayerCache() { | 86 GrLayerCache::~GrLayerCache() { |
| 80 | 87 |
| 81 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); | 88 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
| 82 for (; !iter.done(); ++iter) { | 89 for (; !iter.done(); ++iter) { |
| 83 GrCachedLayer* layer = &(*iter); | 90 GrCachedLayer* layer = &(*iter); |
| 91 SkASSERT(0 == layer->uses()); | |
| 84 this->unlock(layer); | 92 this->unlock(layer); |
| 85 SkDELETE(layer); | 93 SkDELETE(layer); |
| 86 } | 94 } |
| 87 | 95 |
| 88 // The atlas only lets go of its texture when the atlas is deleted. | 96 // The atlas only lets go of its texture when the atlas is deleted. |
| 89 fAtlas.free(); | 97 fAtlas.free(); |
| 90 } | 98 } |
| 91 | 99 |
| 92 void GrLayerCache::initAtlas() { | 100 void GrLayerCache::initAtlas() { |
| 93 SkASSERT(NULL == fAtlas.get()); | 101 SkASSERT(NULL == fAtlas.get()); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 161 SkASSERT(layer->rect().height() == desc.fHeight); | 169 SkASSERT(layer->rect().height() == desc.fHeight); |
| 162 } | 170 } |
| 163 #endif | 171 #endif |
| 164 return false; | 172 return false; |
| 165 } | 173 } |
| 166 | 174 |
| 167 if (layer->isAtlased()) { | 175 if (layer->isAtlased()) { |
| 168 // Hooray it is still in the atlas - make sure it stays there | 176 // Hooray it is still in the atlas - make sure it stays there |
| 169 SkASSERT(!dontAtlas); | 177 SkASSERT(!dontAtlas); |
| 170 layer->setLocked(true); | 178 layer->setLocked(true); |
| 171 fPlotLocks[layer->plot()->id()]++; | 179 this->incPlotLock(layer->plot()->id()); |
| 172 return false; | 180 return false; |
| 173 } else if (!dontAtlas && PlausiblyAtlasable(desc.fWidth, desc.fHeight)) { | 181 } else if (!dontAtlas && PlausiblyAtlasable(desc.fWidth, desc.fHeight)) { |
| 174 // Not in the atlas - will it fit? | 182 // Not in the atlas - will it fit? |
| 175 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 183 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
| 176 if (NULL == pictInfo) { | 184 if (NULL == pictInfo) { |
| 177 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); | 185 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); |
| 178 fPictureHash.add(pictInfo); | 186 fPictureHash.add(pictInfo); |
| 179 } | 187 } |
| 180 | 188 |
| 181 SkIPoint16 loc; | 189 SkIPoint16 loc; |
| 182 for (int i = 0; i < 2; ++i) { // extra pass in case we fail to add but a re able to purge | 190 for (int i = 0; i < 2; ++i) { // extra pass in case we fail to add but a re able to purge |
| 183 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, | 191 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, |
| 184 desc.fWidth, desc.fHeight, | 192 desc.fWidth, desc.fHeight, |
| 185 NULL, &loc); | 193 NULL, &loc); |
| 186 // addToAtlas can allocate the backing texture | 194 // addToAtlas can allocate the backing texture |
| 187 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); | 195 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); |
| 188 if (plot) { | 196 if (plot) { |
| 189 // The layer was successfully added to the atlas | 197 // The layer was successfully added to the atlas |
| 190 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, | 198 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, |
| 191 SkToS16(desc.fWidth), | 199 SkToS16(desc.fWidth), |
| 192 SkToS16(desc.fHeight)); | 200 SkToS16(desc.fHeight)); |
| 193 layer->setTexture(fAtlas->getTexture(), bounds); | 201 layer->setTexture(fAtlas->getTexture(), bounds); |
| 194 layer->setPlot(plot); | 202 layer->setPlot(plot); |
| 195 layer->setLocked(true); | 203 layer->setLocked(true); |
| 196 fPlotLocks[layer->plot()->id()]++; | 204 this->incPlotLock(layer->plot()->id()); |
| 197 return true; | 205 return true; |
| 198 } | 206 } |
| 199 | 207 |
| 200 // The layer was rejected by the atlas (even though we know it is | 208 // The layer was rejected by the atlas (even though we know it is |
| 201 // plausibly atlas-able). See if a plot can be purged and try again. | 209 // plausibly atlas-able). See if a plot can be purged and try again. |
| 202 if (!this->purgePlot()) { | 210 if (!this->purgePlot()) { |
| 203 break; // We weren't able to purge any plots | 211 break; // We weren't able to purge any plots |
| 204 } | 212 } |
| 205 } | 213 } |
| 206 } | 214 } |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 220 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) | 228 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) |
| 221 | 229 |
| 222 if (NULL == layer || !layer->locked()) { | 230 if (NULL == layer || !layer->locked()) { |
| 223 // invalid or not locked | 231 // invalid or not locked |
| 224 return; | 232 return; |
| 225 } | 233 } |
| 226 | 234 |
| 227 if (layer->isAtlased()) { | 235 if (layer->isAtlased()) { |
| 228 const int plotID = layer->plot()->id(); | 236 const int plotID = layer->plot()->id(); |
| 229 | 237 |
| 230 SkASSERT(fPlotLocks[plotID] > 0); | 238 this->decPlotLock(plotID); |
| 231 fPlotLocks[plotID]--; | |
| 232 // At this point we could aggressively clear out un-locked plots but | 239 // At this point we could aggressively clear out un-locked plots but |
| 233 // by delaying we may be able to reuse some of the atlased layers later. | 240 // by delaying we may be able to reuse some of the atlased layers later. |
| 234 #if DISABLE_CACHING | 241 #if DISABLE_CACHING |
| 235 // This testing code aggressively removes the atlased layers. This | 242 // This testing code aggressively removes the atlased layers. This |
| 236 // can be used to separate the performance contribution of less | 243 // can be used to separate the performance contribution of less |
| 237 // render target pingponging from that due to the re-use of cached layer s | 244 // render target pingponging from that due to the re-use of cached layer s |
| 238 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 245 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
| 239 SkASSERT(pictInfo); | 246 SkASSERT(pictInfo); |
| 240 | 247 |
| 241 GrAtlas::RemovePlot(&pictInfo->fPlotUsage, layer->plot()); | 248 GrAtlas::RemovePlot(&pictInfo->fPlotUsage, layer->plot()); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 263 layer->validate(fAtlas->getTexture()); | 270 layer->validate(fAtlas->getTexture()); |
| 264 | 271 |
| 265 const GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 272 const GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
| 266 if (pictInfo) { | 273 if (pictInfo) { |
| 267 // In aggressive cleanup mode a picture info should only exist if | 274 // In aggressive cleanup mode a picture info should only exist if |
| 268 // it has some atlased layers | 275 // it has some atlased layers |
| 269 #if !DISABLE_CACHING | 276 #if !DISABLE_CACHING |
| 270 SkASSERT(!pictInfo->fPlotUsage.isEmpty()); | 277 SkASSERT(!pictInfo->fPlotUsage.isEmpty()); |
| 271 #endif | 278 #endif |
| 272 } else { | 279 } else { |
| 273 // If there is no picture info for this layer then all of its | 280 // If there is no picture info for this picture then all of its |
| 274 // layers should be non-atlased. | 281 // layers should be non-atlased. |
| 275 SkASSERT(!layer->isAtlased()); | 282 SkASSERT(!layer->isAtlased()); |
| 276 } | 283 } |
| 277 | 284 |
| 278 if (layer->plot()) { | 285 if (layer->plot()) { |
| 279 SkASSERT(pictInfo); | 286 SkASSERT(pictInfo); |
| 280 SkASSERT(pictInfo->fPictureID == layer->pictureID()); | 287 SkASSERT(pictInfo->fPictureID == layer->pictureID()); |
| 281 | 288 |
| 282 SkASSERT(pictInfo->fPlotUsage.contains(layer->plot())); | 289 SkASSERT(pictInfo->fPlotUsage.contains(layer->plot())); |
| 283 | 290 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 314 SkTDArray<GrCachedLayer*> toBeRemoved; | 321 SkTDArray<GrCachedLayer*> toBeRemoved; |
| 315 | 322 |
| 316 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); | 323 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
| 317 for (; !iter.done(); ++iter) { | 324 for (; !iter.done(); ++iter) { |
| 318 if (pictureID == (*iter).pictureID()) { | 325 if (pictureID == (*iter).pictureID()) { |
| 319 *toBeRemoved.append() = &(*iter); | 326 *toBeRemoved.append() = &(*iter); |
| 320 } | 327 } |
| 321 } | 328 } |
| 322 | 329 |
| 323 for (int i = 0; i < toBeRemoved.count(); ++i) { | 330 for (int i = 0; i < toBeRemoved.count(); ++i) { |
| 331 SkASSERT(0 == toBeRemoved[i]->uses()); | |
| 324 this->unlock(toBeRemoved[i]); | 332 this->unlock(toBeRemoved[i]); |
| 325 fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); | 333 fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); |
| 326 SkDELETE(toBeRemoved[i]); | 334 SkDELETE(toBeRemoved[i]); |
| 327 } | 335 } |
| 328 | 336 |
| 329 GrPictureInfo* pictInfo = fPictureHash.find(pictureID); | 337 GrPictureInfo* pictInfo = fPictureHash.find(pictureID); |
| 330 if (pictInfo) { | 338 if (pictInfo) { |
| 331 fPictureHash.remove(pictureID); | 339 fPictureHash.remove(pictureID); |
| 332 SkDELETE(pictInfo); | 340 SkDELETE(pictInfo); |
| 333 } | 341 } |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 359 SkTDArray<GrCachedLayer*> toBeRemoved; | 367 SkTDArray<GrCachedLayer*> toBeRemoved; |
| 360 | 368 |
| 361 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); | 369 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
| 362 for (; !iter.done(); ++iter) { | 370 for (; !iter.done(); ++iter) { |
| 363 if (plot == (*iter).plot()) { | 371 if (plot == (*iter).plot()) { |
| 364 *toBeRemoved.append() = &(*iter); | 372 *toBeRemoved.append() = &(*iter); |
| 365 } | 373 } |
| 366 } | 374 } |
| 367 | 375 |
| 368 for (int i = 0; i < toBeRemoved.count(); ++i) { | 376 for (int i = 0; i < toBeRemoved.count(); ++i) { |
| 377 SkASSERT(0 == toBeRemoved[i]->uses()); | |
| 369 SkASSERT(!toBeRemoved[i]->locked()); | 378 SkASSERT(!toBeRemoved[i]->locked()); |
| 370 | 379 |
| 371 uint32_t pictureIDToRemove = toBeRemoved[i]->pictureID(); | 380 uint32_t pictureIDToRemove = toBeRemoved[i]->pictureID(); |
| 372 | 381 |
| 373 // Aggressively remove layers and, if it becomes totally uncached, delet e the picture info | 382 // Aggressively remove layers and, if it becomes totally uncached, delet e the picture info |
| 374 fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); | 383 fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); |
| 375 SkDELETE(toBeRemoved[i]); | 384 SkDELETE(toBeRemoved[i]); |
| 376 | 385 |
| 377 GrPictureInfo* pictInfo = fPictureHash.find(pictureIDToRemove); | 386 GrPictureInfo* pictInfo = fPictureHash.find(pictureIDToRemove); |
| 378 if (pictInfo) { | 387 if (pictInfo) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 417 | 426 |
| 418 void GrLayerCache::processDeletedPictures() { | 427 void GrLayerCache::processDeletedPictures() { |
| 419 SkTDArray<GrPictureDeletedMessage> deletedPictures; | 428 SkTDArray<GrPictureDeletedMessage> deletedPictures; |
| 420 fPictDeletionInbox.poll(&deletedPictures); | 429 fPictDeletionInbox.poll(&deletedPictures); |
| 421 | 430 |
| 422 for (int i = 0; i < deletedPictures.count(); i++) { | 431 for (int i = 0; i < deletedPictures.count(); i++) { |
| 423 this->purge(deletedPictures[i].pictureID); | 432 this->purge(deletedPictures[i].pictureID); |
| 424 } | 433 } |
| 425 } | 434 } |
| 426 | 435 |
| OLD | NEW |