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