| 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 "GrContext.h" | 9 #include "GrContext.h" |
| 10 #include "GrDrawContext.h" | 10 #include "GrDrawContext.h" |
| 11 #include "GrGpu.h" | 11 #include "GrGpu.h" |
| 12 #include "GrLayerCache.h" | 12 #include "GrLayerCache.h" |
| 13 #include "GrSurfacePriv.h" | 13 #include "GrSurfacePriv.h" |
| 14 | 14 |
| 15 #ifdef SK_DEBUG | 15 #ifdef SK_DEBUG |
| 16 void GrCachedLayer::validate(const GrTexture* backingTexture) const { | 16 void GrCachedLayer::validate(const GrTexture* backingTexture) const { |
| 17 SkASSERT(SK_InvalidGenID != fKey.pictureID()); | 17 SkASSERT(SK_InvalidGenID != fKey.pictureID()); |
| 18 | 18 |
| 19 if (fTexture) { | 19 if (fTexture) { |
| 20 // 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 |
| 21 SkASSERT(!fRect.isEmpty()); | 21 SkASSERT(!fRect.isEmpty()); |
| 22 if (!this->isAtlased()) { | 22 if (!this->isAtlased()) { |
| 23 // 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 |
| 24 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); | 24 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); |
| 25 } | 25 } |
| 26 } else { | 26 } else { |
| 27 SkASSERT(fRect.isEmpty()); | 27 SkASSERT(fRect.isEmpty()); |
| 28 SkASSERT(NULL == fPlot); | 28 SkASSERT(nullptr == fPlot); |
| 29 SkASSERT(!fLocked); // layers without a texture cannot be locked | 29 SkASSERT(!fLocked); // layers without a texture cannot be locked |
| 30 } | 30 } |
| 31 | 31 |
| 32 if (fPlot) { | 32 if (fPlot) { |
| 33 // 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 |
| 34 // the backing texture. Additionally, its rect should be non-empty. | 34 // the backing texture. Additionally, its rect should be non-empty. |
| 35 SkASSERT(fTexture && backingTexture == fTexture); | 35 SkASSERT(fTexture && backingTexture == fTexture); |
| 36 SkASSERT(!fRect.isEmpty()); | 36 SkASSERT(!fRect.isEmpty()); |
| 37 } | 37 } |
| 38 | 38 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 61 if (fLayer) { | 61 if (fLayer) { |
| 62 fLayer->validate(backingTexture); | 62 fLayer->validate(backingTexture); |
| 63 } | 63 } |
| 64 } | 64 } |
| 65 ~GrAutoValidateLayer() { | 65 ~GrAutoValidateLayer() { |
| 66 if (fLayer) { | 66 if (fLayer) { |
| 67 fLayer->validate(fBackingTexture); | 67 fLayer->validate(fBackingTexture); |
| 68 } | 68 } |
| 69 } | 69 } |
| 70 void setBackingTexture(GrTexture* backingTexture) { | 70 void setBackingTexture(GrTexture* backingTexture) { |
| 71 SkASSERT(NULL == fBackingTexture || fBackingTexture == backingTexture); | 71 SkASSERT(nullptr == fBackingTexture || fBackingTexture == backingTexture
); |
| 72 fBackingTexture = backingTexture; | 72 fBackingTexture = backingTexture; |
| 73 } | 73 } |
| 74 | 74 |
| 75 private: | 75 private: |
| 76 const GrTexture* fBackingTexture; | 76 const GrTexture* fBackingTexture; |
| 77 const GrCachedLayer* fLayer; | 77 const GrCachedLayer* fLayer; |
| 78 }; | 78 }; |
| 79 #endif | 79 #endif |
| 80 | 80 |
| 81 GrLayerCache::GrLayerCache(GrContext* context) | 81 GrLayerCache::GrLayerCache(GrContext* context) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 93 delete layer; | 93 delete layer; |
| 94 } | 94 } |
| 95 | 95 |
| 96 SkASSERT(0 == fPictureHash.count()); | 96 SkASSERT(0 == fPictureHash.count()); |
| 97 | 97 |
| 98 // The atlas only lets go of its texture when the atlas is deleted. | 98 // The atlas only lets go of its texture when the atlas is deleted. |
| 99 fAtlas.free(); | 99 fAtlas.free(); |
| 100 } | 100 } |
| 101 | 101 |
| 102 void GrLayerCache::initAtlas() { | 102 void GrLayerCache::initAtlas() { |
| 103 SkASSERT(NULL == fAtlas.get()); | 103 SkASSERT(nullptr == fAtlas.get()); |
| 104 GR_STATIC_ASSERT(kNumPlotsX*kNumPlotsX == GrPictureInfo::kNumPlots); | 104 GR_STATIC_ASSERT(kNumPlotsX*kNumPlotsX == GrPictureInfo::kNumPlots); |
| 105 | 105 |
| 106 SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight)
; | 106 SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight)
; |
| 107 fAtlas.reset(new GrAtlas(fContext->getGpu(), kSkia8888_GrPixelConfig, | 107 fAtlas.reset(new GrAtlas(fContext->getGpu(), kSkia8888_GrPixelConfig, |
| 108 kRenderTarget_GrSurfaceFlag, textureSize, kNumPlots
X, kNumPlotsY, | 108 kRenderTarget_GrSurfaceFlag, textureSize, kNumPlots
X, kNumPlotsY, |
| 109 false)); | 109 false)); |
| 110 } | 110 } |
| 111 | 111 |
| 112 void GrLayerCache::freeAll() { | 112 void GrLayerCache::freeAll() { |
| 113 | 113 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 GrCachedLayer* GrLayerCache::findLayerOrCreate(uint32_t pictureID, | 148 GrCachedLayer* GrLayerCache::findLayerOrCreate(uint32_t pictureID, |
| 149 int start, int stop, | 149 int start, int stop, |
| 150 const SkIRect& srcIR, | 150 const SkIRect& srcIR, |
| 151 const SkIRect& dstIR, | 151 const SkIRect& dstIR, |
| 152 const SkMatrix& initialMat, | 152 const SkMatrix& initialMat, |
| 153 const int* key, | 153 const int* key, |
| 154 int keySize, | 154 int keySize, |
| 155 const SkPaint* paint) { | 155 const SkPaint* paint) { |
| 156 SkASSERT(pictureID != SK_InvalidGenID && start >= 0 && stop > 0); | 156 SkASSERT(pictureID != SK_InvalidGenID && start >= 0 && stop > 0); |
| 157 GrCachedLayer* layer = fLayerHash.find(GrCachedLayer::Key(pictureID, initial
Mat, key, keySize)); | 157 GrCachedLayer* layer = fLayerHash.find(GrCachedLayer::Key(pictureID, initial
Mat, key, keySize)); |
| 158 if (NULL == layer) { | 158 if (nullptr == layer) { |
| 159 layer = this->createLayer(pictureID, start, stop, | 159 layer = this->createLayer(pictureID, start, stop, |
| 160 srcIR, dstIR, initialMat, | 160 srcIR, dstIR, initialMat, |
| 161 key, keySize, paint); | 161 key, keySize, paint); |
| 162 } | 162 } |
| 163 | 163 |
| 164 return layer; | 164 return layer; |
| 165 } | 165 } |
| 166 | 166 |
| 167 bool GrLayerCache::tryToAtlas(GrCachedLayer* layer, | 167 bool GrLayerCache::tryToAtlas(GrCachedLayer* layer, |
| 168 const GrSurfaceDesc& desc, | 168 const GrSurfaceDesc& desc, |
| 169 bool* needsRendering) { | 169 bool* needsRendering) { |
| 170 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas ? fAtlas->getTexture() : NULL, la
yer);) | 170 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas ? fAtlas->getTexture() : nullptr,
layer);) |
| 171 | 171 |
| 172 SkASSERT(PlausiblyAtlasable(desc.fWidth, desc.fHeight)); | 172 SkASSERT(PlausiblyAtlasable(desc.fWidth, desc.fHeight)); |
| 173 SkASSERT(0 == desc.fSampleCnt); | 173 SkASSERT(0 == desc.fSampleCnt); |
| 174 | 174 |
| 175 if (layer->locked()) { | 175 if (layer->locked()) { |
| 176 // This layer is already locked | 176 // This layer is already locked |
| 177 SkASSERT(fAtlas); | 177 SkASSERT(fAtlas); |
| 178 SkASSERT(layer->isAtlased()); | 178 SkASSERT(layer->isAtlased()); |
| 179 SkASSERT(layer->rect().width() == desc.fWidth); | 179 SkASSERT(layer->rect().width() == desc.fWidth); |
| 180 SkASSERT(layer->rect().height() == desc.fHeight); | 180 SkASSERT(layer->rect().height() == desc.fHeight); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 191 return true; | 191 return true; |
| 192 } else { | 192 } else { |
| 193 if (!fAtlas) { | 193 if (!fAtlas) { |
| 194 this->initAtlas(); | 194 this->initAtlas(); |
| 195 if (!fAtlas) { | 195 if (!fAtlas) { |
| 196 return false; | 196 return false; |
| 197 } | 197 } |
| 198 } | 198 } |
| 199 // Not in the atlas - will it fit? | 199 // Not in the atlas - will it fit? |
| 200 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 200 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
| 201 if (NULL == pictInfo) { | 201 if (nullptr == pictInfo) { |
| 202 pictInfo = new GrPictureInfo(layer->pictureID()); | 202 pictInfo = new GrPictureInfo(layer->pictureID()); |
| 203 fPictureHash.add(pictInfo); | 203 fPictureHash.add(pictInfo); |
| 204 } | 204 } |
| 205 | 205 |
| 206 SkIPoint16 loc; | 206 SkIPoint16 loc; |
| 207 for (int i = 0; i < 2; ++i) { // extra pass in case we fail to add but a
re able to purge | 207 for (int i = 0; i < 2; ++i) { // extra pass in case we fail to add but a
re able to purge |
| 208 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, | 208 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, |
| 209 desc.fWidth, desc.fHeight, | 209 desc.fWidth, desc.fHeight, |
| 210 NULL, &loc); | 210 nullptr, &loc); |
| 211 // addToAtlas can allocate the backing texture | 211 // addToAtlas can allocate the backing texture |
| 212 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); | 212 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); |
| 213 if (plot) { | 213 if (plot) { |
| 214 #if !GR_CACHE_HOISTED_LAYERS | 214 #if !GR_CACHE_HOISTED_LAYERS |
| 215 pictInfo->incPlotUsage(plot->id()); | 215 pictInfo->incPlotUsage(plot->id()); |
| 216 #endif | 216 #endif |
| 217 // The layer was successfully added to the atlas | 217 // The layer was successfully added to the atlas |
| 218 const SkIRect bounds = SkIRect::MakeXYWH(loc.fX, loc.fY, | 218 const SkIRect bounds = SkIRect::MakeXYWH(loc.fX, loc.fY, |
| 219 desc.fWidth, desc.fHeig
ht); | 219 desc.fWidth, desc.fHeig
ht); |
| 220 layer->setTexture(fAtlas->getTexture(), bounds); | 220 layer->setTexture(fAtlas->getTexture(), bounds); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 return false; | 260 return false; |
| 261 } | 261 } |
| 262 | 262 |
| 263 layer->setTexture(tex, SkIRect::MakeWH(desc.fWidth, desc.fHeight)); | 263 layer->setTexture(tex, SkIRect::MakeWH(desc.fWidth, desc.fHeight)); |
| 264 layer->setLocked(true); | 264 layer->setLocked(true); |
| 265 *needsRendering = true; | 265 *needsRendering = true; |
| 266 return true; | 266 return true; |
| 267 } | 267 } |
| 268 | 268 |
| 269 void GrLayerCache::unlock(GrCachedLayer* layer) { | 269 void GrLayerCache::unlock(GrCachedLayer* layer) { |
| 270 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas ? fAtlas->getTexture() : NULL, la
yer);) | 270 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas ? fAtlas->getTexture() : nullptr,
layer);) |
| 271 | 271 |
| 272 if (NULL == layer || !layer->locked()) { | 272 if (nullptr == layer || !layer->locked()) { |
| 273 // invalid or not locked | 273 // invalid or not locked |
| 274 return; | 274 return; |
| 275 } | 275 } |
| 276 | 276 |
| 277 if (layer->isAtlased()) { | 277 if (layer->isAtlased()) { |
| 278 const int plotID = layer->plot()->id(); | 278 const int plotID = layer->plot()->id(); |
| 279 | 279 |
| 280 this->decPlotLock(plotID); | 280 this->decPlotLock(plotID); |
| 281 // At this point we could aggressively clear out un-locked plots but | 281 // At this point we could aggressively clear out un-locked plots but |
| 282 // by delaying we may be able to reuse some of the atlased layers later. | 282 // by delaying we may be able to reuse some of the atlased layers later. |
| 283 #if !GR_CACHE_HOISTED_LAYERS | 283 #if !GR_CACHE_HOISTED_LAYERS |
| 284 // This testing code aggressively removes the atlased layers. This | 284 // This testing code aggressively removes the atlased layers. This |
| 285 // can be used to separate the performance contribution of less | 285 // can be used to separate the performance contribution of less |
| 286 // render target pingponging from that due to the re-use of cached layer
s | 286 // render target pingponging from that due to the re-use of cached layer
s |
| 287 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 287 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
| 288 SkASSERT(pictInfo); | 288 SkASSERT(pictInfo); |
| 289 | 289 |
| 290 pictInfo->decPlotUsage(plotID); | 290 pictInfo->decPlotUsage(plotID); |
| 291 | 291 |
| 292 if (0 == pictInfo->plotUsage(plotID)) { | 292 if (0 == pictInfo->plotUsage(plotID)) { |
| 293 GrAtlas::RemovePlot(&pictInfo->fPlotUsage, layer->plot()); | 293 GrAtlas::RemovePlot(&pictInfo->fPlotUsage, layer->plot()); |
| 294 | 294 |
| 295 if (pictInfo->fPlotUsage.isEmpty()) { | 295 if (pictInfo->fPlotUsage.isEmpty()) { |
| 296 fPictureHash.remove(pictInfo->fPictureID); | 296 fPictureHash.remove(pictInfo->fPictureID); |
| 297 delete pictInfo; | 297 delete pictInfo; |
| 298 } | 298 } |
| 299 } | 299 } |
| 300 | 300 |
| 301 layer->setPlot(NULL); | 301 layer->setPlot(nullptr); |
| 302 layer->setTexture(NULL, SkIRect::MakeEmpty()); | 302 layer->setTexture(nullptr, SkIRect::MakeEmpty()); |
| 303 #endif | 303 #endif |
| 304 | 304 |
| 305 } else { | 305 } else { |
| 306 layer->setTexture(NULL, SkIRect::MakeEmpty()); | 306 layer->setTexture(nullptr, SkIRect::MakeEmpty()); |
| 307 } | 307 } |
| 308 | 308 |
| 309 layer->setLocked(false); | 309 layer->setLocked(false); |
| 310 } | 310 } |
| 311 | 311 |
| 312 #ifdef SK_DEBUG | 312 #ifdef SK_DEBUG |
| 313 void GrLayerCache::validate() const { | 313 void GrLayerCache::validate() const { |
| 314 int plotLocks[kNumPlotsX * kNumPlotsY]; | 314 int plotLocks[kNumPlotsX * kNumPlotsY]; |
| 315 memset(plotLocks, 0, sizeof(plotLocks)); | 315 memset(plotLocks, 0, sizeof(plotLocks)); |
| 316 | 316 |
| 317 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::ConstIter iter(&fLayerHas
h); | 317 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::ConstIter iter(&fLayerHas
h); |
| 318 for (; !iter.done(); ++iter) { | 318 for (; !iter.done(); ++iter) { |
| 319 const GrCachedLayer* layer = &(*iter); | 319 const GrCachedLayer* layer = &(*iter); |
| 320 | 320 |
| 321 layer->validate(fAtlas.get() ? fAtlas->getTexture() : NULL); | 321 layer->validate(fAtlas.get() ? fAtlas->getTexture() : nullptr); |
| 322 | 322 |
| 323 const GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 323 const GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
| 324 if (!pictInfo) { | 324 if (!pictInfo) { |
| 325 // If there is no picture info for this picture then all of its | 325 // If there is no picture info for this picture then all of its |
| 326 // layers should be non-atlased. | 326 // layers should be non-atlased. |
| 327 SkASSERT(!layer->isAtlased()); | 327 SkASSERT(!layer->isAtlased()); |
| 328 } | 328 } |
| 329 | 329 |
| 330 if (layer->plot()) { | 330 if (layer->plot()) { |
| 331 SkASSERT(pictInfo); | 331 SkASSERT(pictInfo); |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 482 for (int i = 0; i < deletedPictures.count(); i++) { | 482 for (int i = 0; i < deletedPictures.count(); i++) { |
| 483 this->purge(deletedPictures[i].fUniqueID); | 483 this->purge(deletedPictures[i].fUniqueID); |
| 484 } | 484 } |
| 485 } | 485 } |
| 486 | 486 |
| 487 #ifdef SK_DEVELOPER | 487 #ifdef SK_DEVELOPER |
| 488 void GrLayerCache::writeLayersToDisk(const SkString& dirName) { | 488 void GrLayerCache::writeLayersToDisk(const SkString& dirName) { |
| 489 | 489 |
| 490 if (fAtlas) { | 490 if (fAtlas) { |
| 491 GrTexture* atlasTexture = fAtlas->getTexture(); | 491 GrTexture* atlasTexture = fAtlas->getTexture(); |
| 492 if (NULL != atlasTexture) { | 492 if (nullptr != atlasTexture) { |
| 493 SkString fileName(dirName); | 493 SkString fileName(dirName); |
| 494 fileName.append("\\atlas.png"); | 494 fileName.append("\\atlas.png"); |
| 495 | 495 |
| 496 atlasTexture->surfacePriv().savePixels(fileName.c_str()); | 496 atlasTexture->surfacePriv().savePixels(fileName.c_str()); |
| 497 } | 497 } |
| 498 } | 498 } |
| 499 | 499 |
| 500 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); | 500 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
| 501 for (; !iter.done(); ++iter) { | 501 for (; !iter.done(); ++iter) { |
| 502 GrCachedLayer* layer = &(*iter); | 502 GrCachedLayer* layer = &(*iter); |
| 503 | 503 |
| 504 if (layer->isAtlased() || !layer->texture()) { | 504 if (layer->isAtlased() || !layer->texture()) { |
| 505 continue; | 505 continue; |
| 506 } | 506 } |
| 507 | 507 |
| 508 SkString fileName(dirName); | 508 SkString fileName(dirName); |
| 509 fileName.appendf("\\%d", layer->fKey.pictureID()); | 509 fileName.appendf("\\%d", layer->fKey.pictureID()); |
| 510 for (int i = 0; i < layer->fKey.keySize(); ++i) { | 510 for (int i = 0; i < layer->fKey.keySize(); ++i) { |
| 511 fileName.appendf("-%d", layer->fKey.key()[i]); | 511 fileName.appendf("-%d", layer->fKey.key()[i]); |
| 512 } | 512 } |
| 513 fileName.appendf(".png"); | 513 fileName.appendf(".png"); |
| 514 | 514 |
| 515 layer->texture()->surfacePriv().savePixels(fileName.c_str()); | 515 layer->texture()->surfacePriv().savePixels(fileName.c_str()); |
| 516 } | 516 } |
| 517 } | 517 } |
| 518 #endif | 518 #endif |
| OLD | NEW |