| 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 && fKey.stop() > 0); | 17 SkASSERT(fKey.start() > 0 && fKey.stop() > 0); |
| 18 | 18 |
| 19 | 19 |
| 20 if (NULL != fTexture) { | 20 if (fTexture) { |
| 21 // If the layer is in some texture then it must occupy some rectangle | 21 // If the layer is in some texture then it must occupy some rectangle |
| 22 SkASSERT(!fRect.isEmpty()); | 22 SkASSERT(!fRect.isEmpty()); |
| 23 if (!this->isAtlased()) { | 23 if (!this->isAtlased()) { |
| 24 // If it isn't atlased then the rectangle should start at the origin | 24 // If it isn't atlased then the rectangle should start at the origin |
| 25 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); | 25 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); |
| 26 } | 26 } |
| 27 } else { | 27 } else { |
| 28 SkASSERT(fRect.isEmpty()); | 28 SkASSERT(fRect.isEmpty()); |
| 29 SkASSERT(NULL == fPlot); | 29 SkASSERT(NULL == fPlot); |
| 30 SkASSERT(!fLocked); // layers without a texture cannot be locked | 30 SkASSERT(!fLocked); // layers without a texture cannot be locked |
| 31 } | 31 } |
| 32 | 32 |
| 33 if (NULL != fPlot) { | 33 if (fPlot) { |
| 34 // If a layer has a plot (i.e., is atlased) then it must point to | 34 // 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. | 35 // the backing texture. Additionally, its rect should be non-empty. |
| 36 SkASSERT(NULL != fTexture && backingTexture == fTexture); | 36 SkASSERT(fTexture && backingTexture == fTexture); |
| 37 SkASSERT(!fRect.isEmpty()); | 37 SkASSERT(!fRect.isEmpty()); |
| 38 } | 38 } |
| 39 | 39 |
| 40 if (fLocked) { | 40 if (fLocked) { |
| 41 // If a layer is locked it must have a texture (though it need not be | 41 // If a layer is locked it must have a texture (though it need not be |
| 42 // the atlas-backing texture) and occupy some space. | 42 // the atlas-backing texture) and occupy some space. |
| 43 SkASSERT(NULL != fTexture); | 43 SkASSERT(fTexture); |
| 44 SkASSERT(!fRect.isEmpty()); | 44 SkASSERT(!fRect.isEmpty()); |
| 45 } | 45 } |
| 46 } | 46 } |
| 47 | 47 |
| 48 class GrAutoValidateLayer : ::SkNoncopyable { | 48 class GrAutoValidateLayer : ::SkNoncopyable { |
| 49 public: | 49 public: |
| 50 GrAutoValidateLayer(GrTexture* backingTexture, const GrCachedLayer* layer) | 50 GrAutoValidateLayer(GrTexture* backingTexture, const GrCachedLayer* layer) |
| 51 : fBackingTexture(backingTexture) | 51 : fBackingTexture(backingTexture) |
| 52 , fLayer(layer) { | 52 , fLayer(layer) { |
| 53 if (NULL != fLayer) { | 53 if (fLayer) { |
| 54 fLayer->validate(backingTexture); | 54 fLayer->validate(backingTexture); |
| 55 } | 55 } |
| 56 } | 56 } |
| 57 ~GrAutoValidateLayer() { | 57 ~GrAutoValidateLayer() { |
| 58 if (NULL != fLayer) { | 58 if (fLayer) { |
| 59 fLayer->validate(fBackingTexture); | 59 fLayer->validate(fBackingTexture); |
| 60 } | 60 } |
| 61 } | 61 } |
| 62 void setBackingTexture(GrTexture* backingTexture) { | 62 void setBackingTexture(GrTexture* backingTexture) { |
| 63 SkASSERT(NULL == fBackingTexture || fBackingTexture == backingTexture); | 63 SkASSERT(NULL == fBackingTexture || fBackingTexture == backingTexture); |
| 64 fBackingTexture = backingTexture; | 64 fBackingTexture = backingTexture; |
| 65 } | 65 } |
| 66 | 66 |
| 67 private: | 67 private: |
| 68 const GrTexture* fBackingTexture; | 68 const GrTexture* fBackingTexture; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 fPictureHash.add(pictInfo); | 176 fPictureHash.add(pictInfo); |
| 177 } | 177 } |
| 178 | 178 |
| 179 SkIPoint16 loc; | 179 SkIPoint16 loc; |
| 180 for (int i = 0; i < 2; ++i) { // extra pass in case we fail to add but a
re able to purge | 180 for (int i = 0; i < 2; ++i) { // extra pass in case we fail to add but a
re able to purge |
| 181 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, | 181 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, |
| 182 desc.fWidth, desc.fHeight, | 182 desc.fWidth, desc.fHeight, |
| 183 NULL, &loc); | 183 NULL, &loc); |
| 184 // addToAtlas can allocate the backing texture | 184 // addToAtlas can allocate the backing texture |
| 185 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); | 185 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); |
| 186 if (NULL != plot) { | 186 if (plot) { |
| 187 // The layer was successfully added to the atlas | 187 // The layer was successfully added to the atlas |
| 188 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, | 188 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, |
| 189 SkToS16(desc.fWidth), | 189 SkToS16(desc.fWidth), |
| 190 SkToS16(desc.fHeight)); | 190 SkToS16(desc.fHeight)); |
| 191 layer->setTexture(fAtlas->getTexture(), bounds); | 191 layer->setTexture(fAtlas->getTexture(), bounds); |
| 192 layer->setPlot(plot); | 192 layer->setPlot(plot); |
| 193 layer->setLocked(true); | 193 layer->setLocked(true); |
| 194 fPlotLocks[layer->plot()->id()]++; | 194 fPlotLocks[layer->plot()->id()]++; |
| 195 return true; | 195 return true; |
| 196 } | 196 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 227 | 227 |
| 228 SkASSERT(fPlotLocks[plotID] > 0); | 228 SkASSERT(fPlotLocks[plotID] > 0); |
| 229 fPlotLocks[plotID]--; | 229 fPlotLocks[plotID]--; |
| 230 // At this point we could aggressively clear out un-locked plots but | 230 // At this point we could aggressively clear out un-locked plots but |
| 231 // by delaying we may be able to reuse some of the atlased layers later. | 231 // by delaying we may be able to reuse some of the atlased layers later. |
| 232 #if DISABLE_CACHING | 232 #if DISABLE_CACHING |
| 233 // This testing code aggressively removes the atlased layers. This | 233 // This testing code aggressively removes the atlased layers. This |
| 234 // can be used to separate the performance contribution of less | 234 // can be used to separate the performance contribution of less |
| 235 // render target pingponging from that due to the re-use of cached layer
s | 235 // render target pingponging from that due to the re-use of cached layer
s |
| 236 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 236 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
| 237 SkASSERT(NULL != pictInfo); | 237 SkASSERT(pictInfo); |
| 238 | 238 |
| 239 GrAtlas::RemovePlot(&pictInfo->fPlotUsage, layer->plot()); | 239 GrAtlas::RemovePlot(&pictInfo->fPlotUsage, layer->plot()); |
| 240 | 240 |
| 241 layer->setPlot(NULL); | 241 layer->setPlot(NULL); |
| 242 layer->setTexture(NULL, GrIRect16::MakeEmpty()); | 242 layer->setTexture(NULL, GrIRect16::MakeEmpty()); |
| 243 #endif | 243 #endif |
| 244 | 244 |
| 245 } else { | 245 } else { |
| 246 fContext->unlockScratchTexture(layer->texture()); | 246 fContext->unlockScratchTexture(layer->texture()); |
| 247 layer->setTexture(NULL, GrIRect16::MakeEmpty()); | 247 layer->setTexture(NULL, GrIRect16::MakeEmpty()); |
| 248 } | 248 } |
| 249 | 249 |
| 250 layer->setLocked(false); | 250 layer->setLocked(false); |
| 251 } | 251 } |
| 252 | 252 |
| 253 #ifdef SK_DEBUG | 253 #ifdef SK_DEBUG |
| 254 void GrLayerCache::validate() const { | 254 void GrLayerCache::validate() const { |
| 255 int plotLocks[kNumPlotsX * kNumPlotsY]; | 255 int plotLocks[kNumPlotsX * kNumPlotsY]; |
| 256 memset(plotLocks, 0, sizeof(plotLocks)); | 256 memset(plotLocks, 0, sizeof(plotLocks)); |
| 257 | 257 |
| 258 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::ConstIter iter(&fLayerHas
h); | 258 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::ConstIter iter(&fLayerHas
h); |
| 259 for (; !iter.done(); ++iter) { | 259 for (; !iter.done(); ++iter) { |
| 260 const GrCachedLayer* layer = &(*iter); | 260 const GrCachedLayer* layer = &(*iter); |
| 261 | 261 |
| 262 layer->validate(fAtlas->getTexture()); | 262 layer->validate(fAtlas->getTexture()); |
| 263 | 263 |
| 264 const GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 264 const GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
| 265 if (NULL != pictInfo) { | 265 if (pictInfo) { |
| 266 // In aggressive cleanup mode a picture info should only exist if | 266 // In aggressive cleanup mode a picture info should only exist if |
| 267 // it has some atlased layers | 267 // it has some atlased layers |
| 268 #if !DISABLE_CACHING | 268 #if !DISABLE_CACHING |
| 269 SkASSERT(!pictInfo->fPlotUsage.isEmpty()); | 269 SkASSERT(!pictInfo->fPlotUsage.isEmpty()); |
| 270 #endif | 270 #endif |
| 271 } else { | 271 } else { |
| 272 // If there is no picture info for this layer then all of its | 272 // If there is no picture info for this layer then all of its |
| 273 // layers should be non-atlased. | 273 // layers should be non-atlased. |
| 274 SkASSERT(!layer->isAtlased()); | 274 SkASSERT(!layer->isAtlased()); |
| 275 } | 275 } |
| 276 | 276 |
| 277 if (NULL != layer->plot()) { | 277 if (layer->plot()) { |
| 278 SkASSERT(NULL != pictInfo); | 278 SkASSERT(pictInfo); |
| 279 SkASSERT(pictInfo->fPictureID == layer->pictureID()); | 279 SkASSERT(pictInfo->fPictureID == layer->pictureID()); |
| 280 | 280 |
| 281 SkASSERT(pictInfo->fPlotUsage.contains(layer->plot())); | 281 SkASSERT(pictInfo->fPlotUsage.contains(layer->plot())); |
| 282 | 282 |
| 283 if (layer->locked()) { | 283 if (layer->locked()) { |
| 284 plotLocks[layer->plot()->id()]++; | 284 plotLocks[layer->plot()->id()]++; |
| 285 } | 285 } |
| 286 } | 286 } |
| 287 } | 287 } |
| 288 | 288 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 319 } | 319 } |
| 320 } | 320 } |
| 321 | 321 |
| 322 for (int i = 0; i < toBeRemoved.count(); ++i) { | 322 for (int i = 0; i < toBeRemoved.count(); ++i) { |
| 323 this->unlock(toBeRemoved[i]); | 323 this->unlock(toBeRemoved[i]); |
| 324 fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); | 324 fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); |
| 325 SkDELETE(toBeRemoved[i]); | 325 SkDELETE(toBeRemoved[i]); |
| 326 } | 326 } |
| 327 | 327 |
| 328 GrPictureInfo* pictInfo = fPictureHash.find(pictureID); | 328 GrPictureInfo* pictInfo = fPictureHash.find(pictureID); |
| 329 if (NULL != pictInfo) { | 329 if (pictInfo) { |
| 330 fPictureHash.remove(pictureID); | 330 fPictureHash.remove(pictureID); |
| 331 SkDELETE(pictInfo); | 331 SkDELETE(pictInfo); |
| 332 } | 332 } |
| 333 } | 333 } |
| 334 | 334 |
| 335 bool GrLayerCache::purgePlot() { | 335 bool GrLayerCache::purgePlot() { |
| 336 SkDEBUGCODE(GrAutoValidateCache avc(this);) | 336 SkDEBUGCODE(GrAutoValidateCache avc(this);) |
| 337 | 337 |
| 338 GrAtlas::PlotIter iter; | 338 GrAtlas::PlotIter iter; |
| 339 GrPlot* plot; | 339 GrPlot* plot; |
| 340 for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder); | 340 for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder); |
| 341 NULL != plot; | 341 plot; |
| 342 plot = iter.prev()) { | 342 plot = iter.prev()) { |
| 343 if (fPlotLocks[plot->id()] > 0) { | 343 if (fPlotLocks[plot->id()] > 0) { |
| 344 continue; | 344 continue; |
| 345 } | 345 } |
| 346 | 346 |
| 347 this->purgePlot(plot); | 347 this->purgePlot(plot); |
| 348 return true; | 348 return true; |
| 349 } | 349 } |
| 350 | 350 |
| 351 return false; | 351 return false; |
| 352 } | 352 } |
| 353 | 353 |
| 354 void GrLayerCache::purgePlot(GrPlot* plot) { | 354 void GrLayerCache::purgePlot(GrPlot* plot) { |
| 355 SkASSERT(0 == fPlotLocks[plot->id()]); | 355 SkASSERT(0 == fPlotLocks[plot->id()]); |
| 356 | 356 |
| 357 // We need to find all the layers in 'plot' and remove them. | 357 // We need to find all the layers in 'plot' and remove them. |
| 358 SkTDArray<GrCachedLayer*> toBeRemoved; | 358 SkTDArray<GrCachedLayer*> toBeRemoved; |
| 359 | 359 |
| 360 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); | 360 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
| 361 for (; !iter.done(); ++iter) { | 361 for (; !iter.done(); ++iter) { |
| 362 if (plot == (*iter).plot()) { | 362 if (plot == (*iter).plot()) { |
| 363 *toBeRemoved.append() = &(*iter); | 363 *toBeRemoved.append() = &(*iter); |
| 364 } | 364 } |
| 365 } | 365 } |
| 366 | 366 |
| 367 for (int i = 0; i < toBeRemoved.count(); ++i) { | 367 for (int i = 0; i < toBeRemoved.count(); ++i) { |
| 368 SkASSERT(!toBeRemoved[i]->locked()); | 368 SkASSERT(!toBeRemoved[i]->locked()); |
| 369 | 369 |
| 370 GrPictureInfo* pictInfo = fPictureHash.find(toBeRemoved[i]->pictureID())
; | 370 GrPictureInfo* pictInfo = fPictureHash.find(toBeRemoved[i]->pictureID())
; |
| 371 SkASSERT(NULL != pictInfo); | 371 SkASSERT(pictInfo); |
| 372 | 372 |
| 373 GrAtlas::RemovePlot(&pictInfo->fPlotUsage, plot); | 373 GrAtlas::RemovePlot(&pictInfo->fPlotUsage, plot); |
| 374 | 374 |
| 375 // Aggressively remove layers and, if now totally uncached, picture info | 375 // Aggressively remove layers and, if now totally uncached, picture info |
| 376 fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); | 376 fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); |
| 377 SkDELETE(toBeRemoved[i]); | 377 SkDELETE(toBeRemoved[i]); |
| 378 | 378 |
| 379 if (pictInfo->fPlotUsage.isEmpty()) { | 379 if (pictInfo->fPlotUsage.isEmpty()) { |
| 380 fPictureHash.remove(pictInfo->fPictureID); | 380 fPictureHash.remove(pictInfo->fPictureID); |
| 381 SkDELETE(pictInfo); | 381 SkDELETE(pictInfo); |
| 382 } | 382 } |
| 383 } | 383 } |
| 384 | 384 |
| 385 plot->resetRects(); | 385 plot->resetRects(); |
| 386 } | 386 } |
| 387 | 387 |
| 388 void GrLayerCache::purgeAll() { | 388 void GrLayerCache::purgeAll() { |
| 389 GrAtlas::PlotIter iter; | 389 GrAtlas::PlotIter iter; |
| 390 GrPlot* plot; | 390 GrPlot* plot; |
| 391 for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder); | 391 for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder); |
| 392 NULL != plot; | 392 plot; |
| 393 plot = iter.prev()) { | 393 plot = iter.prev()) { |
| 394 SkASSERT(0 == fPlotLocks[plot->id()]); | 394 SkASSERT(0 == fPlotLocks[plot->id()]); |
| 395 | 395 |
| 396 this->purgePlot(plot); | 396 this->purgePlot(plot); |
| 397 } | 397 } |
| 398 } | 398 } |
| 399 | 399 |
| 400 class GrPictureDeletionListener : public SkPicture::DeletionListener { | 400 class GrPictureDeletionListener : public SkPicture::DeletionListener { |
| 401 virtual void onDeletion(uint32_t pictureID) SK_OVERRIDE{ | 401 virtual void onDeletion(uint32_t pictureID) SK_OVERRIDE{ |
| 402 const GrPictureDeletedMessage message = { pictureID }; | 402 const GrPictureDeletedMessage message = { pictureID }; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 414 | 414 |
| 415 void GrLayerCache::processDeletedPictures() { | 415 void GrLayerCache::processDeletedPictures() { |
| 416 SkTDArray<GrPictureDeletedMessage> deletedPictures; | 416 SkTDArray<GrPictureDeletedMessage> deletedPictures; |
| 417 fPictDeletionInbox.poll(&deletedPictures); | 417 fPictDeletionInbox.poll(&deletedPictures); |
| 418 | 418 |
| 419 for (int i = 0; i < deletedPictures.count(); i++) { | 419 for (int i = 0; i < deletedPictures.count(); i++) { |
| 420 this->purge(deletedPictures[i].pictureID); | 420 this->purge(deletedPictures[i].pictureID); |
| 421 } | 421 } |
| 422 } | 422 } |
| 423 | 423 |
| OLD | NEW |