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 "GrLayerAtlas.h" | 8 #include "GrLayerAtlas.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(nullptr == 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 SkASSERT(!fAtlased); // can't be atlased if it doesn't have a texture |
30 } | 31 } |
31 | 32 |
32 if (fPlot) { | 33 if (fPlot) { |
| 34 SkASSERT(fAtlased); |
33 // If a layer has a plot (i.e., is atlased) then it must point to | 35 // 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. | 36 // the backing texture. Additionally, its rect should be non-empty. |
35 SkASSERT(fTexture && backingTexture == fTexture); | 37 SkASSERT(fTexture && backingTexture == fTexture); |
36 SkASSERT(!fRect.isEmpty()); | 38 SkASSERT(!fRect.isEmpty()); |
37 } | 39 } |
38 | 40 |
39 if (fLocked) { | 41 if (fLocked) { |
40 // If a layer is locked it must have a texture (though it need not be | 42 // If a layer is locked it must have a texture (though it need not be |
41 // the atlas-backing texture) and occupy some space. | 43 // the atlas-backing texture) and occupy some space. |
42 SkASSERT(fTexture); | 44 SkASSERT(fTexture); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 void GrLayerCache::freeAll() { | 114 void GrLayerCache::freeAll() { |
113 | 115 |
114 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); | 116 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
115 for (; !iter.done(); ++iter) { | 117 for (; !iter.done(); ++iter) { |
116 GrCachedLayer* layer = &(*iter); | 118 GrCachedLayer* layer = &(*iter); |
117 this->unlock(layer); | 119 this->unlock(layer); |
118 delete layer; | 120 delete layer; |
119 } | 121 } |
120 fLayerHash.rewind(); | 122 fLayerHash.rewind(); |
121 | 123 |
122 // The atlas only lets go of its texture when the atlas is deleted. | 124 if (fAtlas) { |
123 fAtlas.free(); | 125 fAtlas->resetPlots(); |
| 126 fAtlas->detachBackingTexture(); |
| 127 } |
124 } | 128 } |
125 | 129 |
126 GrCachedLayer* GrLayerCache::createLayer(uint32_t pictureID, | 130 GrCachedLayer* GrLayerCache::createLayer(uint32_t pictureID, |
127 int start, int stop, | 131 int start, int stop, |
128 const SkIRect& srcIR, | 132 const SkIRect& srcIR, |
129 const SkIRect& dstIR, | 133 const SkIRect& dstIR, |
130 const SkMatrix& initialMat, | 134 const SkMatrix& initialMat, |
131 const int* key, | 135 const int* key, |
132 int keySize, | 136 int keySize, |
133 const SkPaint* paint) { | 137 const SkPaint* paint) { |
(...skipping 26 matching lines...) Expand all Loading... |
160 srcIR, dstIR, initialMat, | 164 srcIR, dstIR, initialMat, |
161 key, keySize, paint); | 165 key, keySize, paint); |
162 } | 166 } |
163 | 167 |
164 return layer; | 168 return layer; |
165 } | 169 } |
166 | 170 |
167 bool GrLayerCache::tryToAtlas(GrCachedLayer* layer, | 171 bool GrLayerCache::tryToAtlas(GrCachedLayer* layer, |
168 const GrSurfaceDesc& desc, | 172 const GrSurfaceDesc& desc, |
169 bool* needsRendering) { | 173 bool* needsRendering) { |
170 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas ? fAtlas->getTexture() : nullptr,
layer);) | 174 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas ? fAtlas->getTextureOrNull() : nu
llptr, layer);) |
171 | 175 |
172 SkASSERT(PlausiblyAtlasable(desc.fWidth, desc.fHeight)); | 176 SkASSERT(PlausiblyAtlasable(desc.fWidth, desc.fHeight)); |
173 SkASSERT(0 == desc.fSampleCnt); | 177 SkASSERT(0 == desc.fSampleCnt); |
174 | 178 |
175 if (layer->locked()) { | 179 if (layer->locked()) { |
176 // This layer is already locked | 180 // This layer is already locked |
177 SkASSERT(fAtlas); | 181 SkASSERT(fAtlas); |
178 SkASSERT(layer->isAtlased()); | 182 SkASSERT(layer->isAtlased()); |
179 SkASSERT(layer->rect().width() == desc.fWidth); | 183 SkASSERT(layer->rect().width() == desc.fWidth); |
180 SkASSERT(layer->rect().height() == desc.fHeight); | 184 SkASSERT(layer->rect().height() == desc.fHeight); |
(...skipping 29 matching lines...) Expand all Loading... |
210 &loc); | 214 &loc); |
211 // addToAtlas can allocate the backing texture | 215 // addToAtlas can allocate the backing texture |
212 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); | 216 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); |
213 if (plot) { | 217 if (plot) { |
214 #if !GR_CACHE_HOISTED_LAYERS | 218 #if !GR_CACHE_HOISTED_LAYERS |
215 pictInfo->incPlotUsage(plot->id()); | 219 pictInfo->incPlotUsage(plot->id()); |
216 #endif | 220 #endif |
217 // The layer was successfully added to the atlas | 221 // The layer was successfully added to the atlas |
218 const SkIRect bounds = SkIRect::MakeXYWH(loc.fX, loc.fY, | 222 const SkIRect bounds = SkIRect::MakeXYWH(loc.fX, loc.fY, |
219 desc.fWidth, desc.fHeig
ht); | 223 desc.fWidth, desc.fHeig
ht); |
220 layer->setTexture(fAtlas->getTexture(), bounds); | 224 layer->setTexture(fAtlas->getTexture(), bounds, true); |
221 layer->setPlot(plot); | 225 layer->setPlot(plot); |
222 layer->setLocked(true); | 226 layer->setLocked(true); |
223 this->incPlotLock(layer->plot()->id()); | 227 this->incPlotLock(layer->plot()->id()); |
224 *needsRendering = true; | 228 *needsRendering = true; |
225 return true; | 229 return true; |
226 } | 230 } |
227 | 231 |
228 // The layer was rejected by the atlas (even though we know it is | 232 // The layer was rejected by the atlas (even though we know it is |
229 // plausibly atlas-able). See if a plot can be purged and try again. | 233 // plausibly atlas-able). See if a plot can be purged and try again. |
230 if (!this->purgePlot()) { | 234 if (!this->purgePlots(true)) { |
231 break; // We weren't able to purge any plots | 235 break; // We weren't able to purge any plots |
232 } | 236 } |
233 } | 237 } |
234 | 238 |
235 if (pictInfo->fPlotUsage.isEmpty()) { | 239 if (pictInfo->fPlotUsage.isEmpty()) { |
236 fPictureHash.remove(pictInfo->fPictureID); | 240 fPictureHash.remove(pictInfo->fPictureID); |
237 delete pictInfo; | 241 delete pictInfo; |
238 } | 242 } |
239 } | 243 } |
240 | 244 |
(...skipping 12 matching lines...) Expand all Loading... |
253 if (layer->fFilter) { | 257 if (layer->fFilter) { |
254 tex.reset(fContext->textureProvider()->createTexture(desc, true)); | 258 tex.reset(fContext->textureProvider()->createTexture(desc, true)); |
255 } else { | 259 } else { |
256 tex.reset(fContext->textureProvider()->createApproxTexture(desc)); | 260 tex.reset(fContext->textureProvider()->createApproxTexture(desc)); |
257 } | 261 } |
258 | 262 |
259 if (!tex) { | 263 if (!tex) { |
260 return false; | 264 return false; |
261 } | 265 } |
262 | 266 |
263 layer->setTexture(tex, SkIRect::MakeWH(desc.fWidth, desc.fHeight)); | 267 layer->setTexture(tex, SkIRect::MakeWH(desc.fWidth, desc.fHeight), false); |
264 layer->setLocked(true); | 268 layer->setLocked(true); |
265 *needsRendering = true; | 269 *needsRendering = true; |
266 return true; | 270 return true; |
267 } | 271 } |
268 | 272 |
269 void GrLayerCache::unlock(GrCachedLayer* layer) { | 273 void GrLayerCache::unlock(GrCachedLayer* layer) { |
270 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas ? fAtlas->getTexture() : nullptr,
layer);) | 274 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas ? fAtlas->getTextureOrNull() : nu
llptr, layer);) |
271 | 275 |
272 if (nullptr == layer || !layer->locked()) { | 276 if (nullptr == layer || !layer->locked()) { |
273 // invalid or not locked | 277 // invalid or not locked |
274 return; | 278 return; |
275 } | 279 } |
276 | 280 |
277 if (layer->isAtlased()) { | 281 if (layer->isAtlased()) { |
278 const int plotID = layer->plot()->id(); | 282 const int plotID = layer->plot()->id(); |
279 | 283 |
280 this->decPlotLock(plotID); | 284 this->decPlotLock(plotID); |
(...skipping 11 matching lines...) Expand all Loading... |
292 if (0 == pictInfo->plotUsage(plotID)) { | 296 if (0 == pictInfo->plotUsage(plotID)) { |
293 pictInfo->fPlotUsage.removePlot(layer->plot()); | 297 pictInfo->fPlotUsage.removePlot(layer->plot()); |
294 | 298 |
295 if (pictInfo->fPlotUsage.isEmpty()) { | 299 if (pictInfo->fPlotUsage.isEmpty()) { |
296 fPictureHash.remove(pictInfo->fPictureID); | 300 fPictureHash.remove(pictInfo->fPictureID); |
297 delete pictInfo; | 301 delete pictInfo; |
298 } | 302 } |
299 } | 303 } |
300 | 304 |
301 layer->setPlot(nullptr); | 305 layer->setPlot(nullptr); |
302 layer->setTexture(nullptr, SkIRect::MakeEmpty()); | 306 layer->setTexture(nullptr, SkIRect::MakeEmpty(), false); |
303 #endif | 307 #endif |
304 | 308 |
305 } else { | 309 } else { |
306 layer->setTexture(nullptr, SkIRect::MakeEmpty()); | 310 layer->setTexture(nullptr, SkIRect::MakeEmpty(), false); |
307 } | 311 } |
308 | 312 |
309 layer->setLocked(false); | 313 layer->setLocked(false); |
310 } | 314 } |
311 | 315 |
312 #ifdef SK_DEBUG | 316 #ifdef SK_DEBUG |
313 void GrLayerCache::validate() const { | 317 void GrLayerCache::validate() const { |
314 int plotLocks[kNumPlotsX * kNumPlotsY]; | 318 int plotLocks[kNumPlotsX * kNumPlotsY]; |
315 memset(plotLocks, 0, sizeof(plotLocks)); | 319 memset(plotLocks, 0, sizeof(plotLocks)); |
316 | 320 |
317 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::ConstIter iter(&fLayerHas
h); | 321 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::ConstIter iter(&fLayerHas
h); |
318 for (; !iter.done(); ++iter) { | 322 for (; !iter.done(); ++iter) { |
319 const GrCachedLayer* layer = &(*iter); | 323 const GrCachedLayer* layer = &(*iter); |
320 | 324 |
321 layer->validate(fAtlas.get() ? fAtlas->getTexture() : nullptr); | 325 layer->validate(fAtlas.get() ? fAtlas->getTextureOrNull() : nullptr); |
322 | 326 |
323 const GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 327 const GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
324 if (!pictInfo) { | 328 if (!pictInfo) { |
325 // If there is no picture info for this picture then all of its | 329 // If there is no picture info for this picture then all of its |
326 // layers should be non-atlased. | 330 // layers should be non-atlased. |
327 SkASSERT(!layer->isAtlased()); | 331 SkASSERT(!layer->isAtlased()); |
328 } | 332 } |
329 | 333 |
330 if (layer->plot()) { | 334 if (layer->plot()) { |
331 SkASSERT(pictInfo); | 335 SkASSERT(pictInfo); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 delete toBeRemoved[i]; | 386 delete toBeRemoved[i]; |
383 } | 387 } |
384 | 388 |
385 GrPictureInfo* pictInfo = fPictureHash.find(pictureID); | 389 GrPictureInfo* pictInfo = fPictureHash.find(pictureID); |
386 if (pictInfo) { | 390 if (pictInfo) { |
387 fPictureHash.remove(pictureID); | 391 fPictureHash.remove(pictureID); |
388 delete pictInfo; | 392 delete pictInfo; |
389 } | 393 } |
390 } | 394 } |
391 | 395 |
392 bool GrLayerCache::purgePlot() { | 396 bool GrLayerCache::purgePlots(bool justOne) { |
393 SkDEBUGCODE(GrAutoValidateCache avc(this);) | 397 SkDEBUGCODE(GrAutoValidateCache avc(this);) |
394 SkASSERT(fAtlas); | 398 SkASSERT(fAtlas); |
395 | 399 |
| 400 bool anyPurged = false; |
396 GrLayerAtlas::PlotIter iter; | 401 GrLayerAtlas::PlotIter iter; |
397 GrLayerAtlas::Plot* plot; | 402 GrLayerAtlas::Plot* plot; |
398 for (plot = fAtlas->iterInit(&iter, GrLayerAtlas::kLRUFirst_IterOrder); | 403 for (plot = fAtlas->iterInit(&iter, GrLayerAtlas::kLRUFirst_IterOrder); |
399 plot; | 404 plot; |
400 plot = iter.prev()) { | 405 plot = iter.prev()) { |
401 if (fPlotLocks[plot->id()] > 0) { | 406 if (fPlotLocks[plot->id()] > 0) { |
402 continue; | 407 continue; |
403 } | 408 } |
404 | 409 |
| 410 anyPurged = true; |
405 this->purgePlot(plot); | 411 this->purgePlot(plot); |
406 return true; | 412 if (justOne) { |
| 413 break; |
| 414 } |
407 } | 415 } |
408 | 416 |
409 return false; | 417 return anyPurged; |
410 } | 418 } |
411 | 419 |
412 void GrLayerCache::purgePlot(GrLayerAtlas::Plot* plot) { | 420 void GrLayerCache::purgePlot(GrLayerAtlas::Plot* plot) { |
413 SkASSERT(0 == fPlotLocks[plot->id()]); | 421 SkASSERT(0 == fPlotLocks[plot->id()]); |
414 | 422 |
415 // We need to find all the layers in 'plot' and remove them. | 423 // We need to find all the layers in 'plot' and remove them. |
416 SkTDArray<GrCachedLayer*> toBeRemoved; | 424 SkTDArray<GrCachedLayer*> toBeRemoved; |
417 | 425 |
418 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); | 426 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
419 for (; !iter.done(); ++iter) { | 427 for (; !iter.done(); ++iter) { |
(...skipping 28 matching lines...) Expand all Loading... |
448 | 456 |
449 plot->reset(); | 457 plot->reset(); |
450 } | 458 } |
451 | 459 |
452 #if !GR_CACHE_HOISTED_LAYERS | 460 #if !GR_CACHE_HOISTED_LAYERS |
453 void GrLayerCache::purgeAll() { | 461 void GrLayerCache::purgeAll() { |
454 if (!fAtlas) { | 462 if (!fAtlas) { |
455 return; | 463 return; |
456 } | 464 } |
457 | 465 |
458 GrLayerAtlas::PlotIter iter; | 466 this->purgePlots(false); // clear them all out |
459 GrLayerAtlas::Plot* plot; | |
460 for (plot = fAtlas->iterInit(&iter, GrLayerAtlas::kLRUFirst_IterOrder); | |
461 plot; | |
462 plot = iter.prev()) { | |
463 SkASSERT(0 == fPlotLocks[plot->id()]); | |
464 | |
465 this->purgePlot(plot); | |
466 } | |
467 | 467 |
468 SkASSERT(0 == fPictureHash.count()); | 468 SkASSERT(0 == fPictureHash.count()); |
469 | 469 |
470 SkAutoTUnref<GrDrawContext> drawContext( | 470 if (fAtlas->getTextureOrNull()) { |
471 fContext->drawContext(fAtlas->getTexture()->asRe
nderTarget())); | 471 SkAutoTUnref<GrDrawContext> drawContext( |
| 472 fContext->drawContext(fAtlas->getTexture()->
asRenderTarget())); |
472 | 473 |
473 if (drawContext) { | 474 if (drawContext) { |
474 drawContext->discard(); | 475 drawContext->discard(); |
| 476 } |
475 } | 477 } |
476 } | 478 } |
477 #endif | 479 #endif |
478 | 480 |
| 481 void GrLayerCache::begin() { |
| 482 if (!fAtlas) { |
| 483 return; |
| 484 } |
| 485 |
| 486 if (!fAtlas->reattachBackingTexture()) { |
| 487 // We weren't able to re-attach. Clear out all the atlased layers. |
| 488 this->purgePlots(false); |
| 489 SkASSERT(0 == fPictureHash.count()); |
| 490 } |
| 491 #ifdef SK_DEBUG |
| 492 else { |
| 493 // we've reattached - everything had better make sense |
| 494 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash
); |
| 495 for (; !iter.done(); ++iter) { |
| 496 GrCachedLayer* layer = &(*iter); |
| 497 |
| 498 if (layer->isAtlased()) { |
| 499 SkASSERT(fAtlas->getTexture() == layer->texture()); |
| 500 } |
| 501 } |
| 502 } |
| 503 #endif |
| 504 } |
| 505 |
| 506 void GrLayerCache::end() { |
| 507 if (!fAtlas) { |
| 508 return; |
| 509 } |
| 510 |
| 511 // Adding this call will clear out all the layers in the atlas |
| 512 //this->purgePlots(false); |
| 513 |
| 514 fAtlas->detachBackingTexture(); |
| 515 } |
| 516 |
479 void GrLayerCache::processDeletedPictures() { | 517 void GrLayerCache::processDeletedPictures() { |
480 SkTArray<SkPicture::DeletionMessage> deletedPictures; | 518 SkTArray<SkPicture::DeletionMessage> deletedPictures; |
481 fPictDeletionInbox.poll(&deletedPictures); | 519 fPictDeletionInbox.poll(&deletedPictures); |
482 | 520 |
483 for (int i = 0; i < deletedPictures.count(); i++) { | 521 for (int i = 0; i < deletedPictures.count(); i++) { |
484 this->purge(deletedPictures[i].fUniqueID); | 522 this->purge(deletedPictures[i].fUniqueID); |
485 } | 523 } |
486 } | 524 } |
487 | 525 |
488 #ifdef SK_DEVELOPER | 526 #ifdef SK_DEVELOPER |
489 void GrLayerCache::writeLayersToDisk(const SkString& dirName) { | 527 void GrLayerCache::writeLayersToDisk(const SkString& dirName) { |
490 | 528 |
491 if (fAtlas) { | 529 if (fAtlas) { |
492 GrTexture* atlasTexture = fAtlas->getTexture(); | 530 GrTexture* atlasTexture = fAtlas->getTextureOrNull(); |
493 if (nullptr != atlasTexture) { | 531 if (nullptr != atlasTexture) { |
494 SkString fileName(dirName); | 532 SkString fileName(dirName); |
495 fileName.append("\\atlas.png"); | 533 fileName.append("\\atlas.png"); |
496 | 534 |
497 atlasTexture->surfacePriv().savePixels(fileName.c_str()); | 535 atlasTexture->surfacePriv().savePixels(fileName.c_str()); |
498 } | 536 } |
499 } | 537 } |
500 | 538 |
501 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); | 539 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
502 for (; !iter.done(); ++iter) { | 540 for (; !iter.done(); ++iter) { |
503 GrCachedLayer* layer = &(*iter); | 541 GrCachedLayer* layer = &(*iter); |
504 | 542 |
505 if (layer->isAtlased() || !layer->texture()) { | 543 if (layer->isAtlased() || !layer->texture()) { |
506 continue; | 544 continue; |
507 } | 545 } |
508 | 546 |
509 SkString fileName(dirName); | 547 SkString fileName(dirName); |
510 fileName.appendf("\\%d", layer->fKey.pictureID()); | 548 fileName.appendf("\\%d", layer->fKey.pictureID()); |
511 for (int i = 0; i < layer->fKey.keySize(); ++i) { | 549 for (int i = 0; i < layer->fKey.keySize(); ++i) { |
512 fileName.appendf("-%d", layer->fKey.key()[i]); | 550 fileName.appendf("-%d", layer->fKey.key()[i]); |
513 } | 551 } |
514 fileName.appendf(".png"); | 552 fileName.appendf(".png"); |
515 | 553 |
516 layer->texture()->surfacePriv().savePixels(fileName.c_str()); | 554 layer->texture()->surfacePriv().savePixels(fileName.c_str()); |
517 } | 555 } |
518 } | 556 } |
519 #endif | 557 #endif |
OLD | NEW |