1e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com/* 2e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com * Copyright 2014 Google Inc. 3e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com * 4e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com * Use of this source code is governed by a BSD-style license that can be 5e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com * found in the LICENSE file. 6e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com */ 7e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com 8e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com#include "GrAtlas.h" 9e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com#include "GrGpu.h" 10e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com#include "GrLayerCache.h" 11e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com 12d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillipsDECLARE_SKMESSAGEBUS_MESSAGE(GrPictureDeletedMessage); 13d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips 1421048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips#ifdef SK_DEBUG 15261b8a98dc7378989ba8fa9c06b728e89162862brobertphillipsvoid GrCachedLayer::validate(const GrTexture* backingTexture) const { 160c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips SkASSERT(SK_InvalidGenID != fKey.pictureID()); 170c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips SkASSERT(fKey.start() > 0 && fKey.stop() > 0); 183d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips 1921048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips 2049f085dddff10473b6ebf832a974288300224e60bsalomon if (fTexture) { 2121048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips // If the layer is in some texture then it must occupy some rectangle 2221048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips SkASSERT(!fRect.isEmpty()); 2321048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips if (!this->isAtlased()) { 2421048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips // If it isn't atlased then the rectangle should start at the origin 2521048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); 2621048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips } 2721048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips } else { 2821048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips SkASSERT(fRect.isEmpty()); 29261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips SkASSERT(NULL == fPlot); 30320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips SkASSERT(!fLocked); // layers without a texture cannot be locked 31261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips } 32261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips 3349f085dddff10473b6ebf832a974288300224e60bsalomon if (fPlot) { 34261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips // If a layer has a plot (i.e., is atlased) then it must point to 35261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips // the backing texture. Additionally, its rect should be non-empty. 3649f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(fTexture && backingTexture == fTexture); 37261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips SkASSERT(!fRect.isEmpty()); 3821048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips } 39320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 40320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips if (fLocked) { 41320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips // If a layer is locked it must have a texture (though it need not be 42320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips // the atlas-backing texture) and occupy some space. 4349f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(fTexture); 44320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips SkASSERT(!fRect.isEmpty()); 45320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips } 4621048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips} 4721048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips 4821048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillipsclass GrAutoValidateLayer : ::SkNoncopyable { 4921048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillipspublic: 5021048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips GrAutoValidateLayer(GrTexture* backingTexture, const GrCachedLayer* layer) 5121048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips : fBackingTexture(backingTexture) 5221048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips , fLayer(layer) { 5349f085dddff10473b6ebf832a974288300224e60bsalomon if (fLayer) { 5421048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips fLayer->validate(backingTexture); 5521048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips } 5621048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips } 5721048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips ~GrAutoValidateLayer() { 5849f085dddff10473b6ebf832a974288300224e60bsalomon if (fLayer) { 5921048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips fLayer->validate(fBackingTexture); 6021048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips } 6121048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips } 62261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips void setBackingTexture(GrTexture* backingTexture) { 63261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips SkASSERT(NULL == fBackingTexture || fBackingTexture == backingTexture); 64261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips fBackingTexture = backingTexture; 65261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips } 6621048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips 6721048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillipsprivate: 68261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips const GrTexture* fBackingTexture; 6921048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips const GrCachedLayer* fLayer; 7021048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips}; 7121048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips#endif 7221048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips 734ec84da746d66e1bcb76ab2f8b94602b8e966589robertphillipsGrLayerCache::GrLayerCache(GrContext* context) 74952841bf41a81228c23d16c7204b458abe0d7136robertphillips : fContext(context) { 75952841bf41a81228c23d16c7204b458abe0d7136robertphillips this->initAtlas(); 76320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips memset(fPlotLocks, 0, sizeof(fPlotLocks)); 77e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com} 78e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com 79e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.comGrLayerCache::~GrLayerCache() { 80952841bf41a81228c23d16c7204b458abe0d7136robertphillips 813d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); 823d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips for (; !iter.done(); ++iter) { 833d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips GrCachedLayer* layer = &(*iter); 843d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips this->unlock(layer); 853d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips SkDELETE(layer); 863d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips } 87952841bf41a81228c23d16c7204b458abe0d7136robertphillips 88952841bf41a81228c23d16c7204b458abe0d7136robertphillips // The atlas only lets go of its texture when the atlas is deleted. 89952841bf41a81228c23d16c7204b458abe0d7136robertphillips fAtlas.free(); 90e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com} 91e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com 92952841bf41a81228c23d16c7204b458abe0d7136robertphillipsvoid GrLayerCache::initAtlas() { 931d86ee8363018d71245d23573619473ae7e7d1c9robertphillips SkASSERT(NULL == fAtlas.get()); 94e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com 95e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight); 961d86ee8363018d71245d23573619473ae7e7d1c9robertphillips fAtlas.reset(SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kSkia8888_GrPixelConfig, 97952841bf41a81228c23d16c7204b458abe0d7136robertphillips kRenderTarget_GrTextureFlagBit, 98261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips textureSize, kNumPlotsX, kNumPlotsY, false))); 99e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com} 100e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com 101e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.comvoid GrLayerCache::freeAll() { 102952841bf41a81228c23d16c7204b458abe0d7136robertphillips 1033d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); 1043d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips for (; !iter.done(); ++iter) { 1053d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips GrCachedLayer* layer = &(*iter); 1063d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips this->unlock(layer); 1073d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips SkDELETE(layer); 1083d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips } 1093d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips fLayerHash.rewind(); 110952841bf41a81228c23d16c7204b458abe0d7136robertphillips 111952841bf41a81228c23d16c7204b458abe0d7136robertphillips // The atlas only lets go of its texture when the atlas is deleted. 1121d86ee8363018d71245d23573619473ae7e7d1c9robertphillips fAtlas.free(); 113952841bf41a81228c23d16c7204b458abe0d7136robertphillips // GrLayerCache always assumes an atlas exists so recreate it. The atlas 114952841bf41a81228c23d16c7204b458abe0d7136robertphillips // lazily allocates a replacement texture so reallocating a new 115c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon // atlas here won't disrupt a GrContext::abandonContext or freeGpuResources. 116952841bf41a81228c23d16c7204b458abe0d7136robertphillips // TODO: Make GrLayerCache lazily allocate the atlas manager? 117952841bf41a81228c23d16c7204b458abe0d7136robertphillips this->initAtlas(); 118e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com} 119e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com 1206f294af43bcd94ed9616a7e4f5892589813d0a01robertphillipsGrCachedLayer* GrLayerCache::createLayer(uint32_t pictureID, 1210c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips int start, int stop, 1224815fe5a0a497b676677fb4e4a0f05c511855490robertphillips const SkIPoint& offset, 1234aa6dfc0b77af9ac298bb9d48991b72a2fec00b2robertphillips const SkMatrix& ctm, 1244aa6dfc0b77af9ac298bb9d48991b72a2fec00b2robertphillips const SkPaint* paint) { 1256f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips SkASSERT(pictureID != SK_InvalidGenID && start > 0 && stop > 0); 126952841bf41a81228c23d16c7204b458abe0d7136robertphillips 1274aa6dfc0b77af9ac298bb9d48991b72a2fec00b2robertphillips GrCachedLayer* layer = SkNEW_ARGS(GrCachedLayer, (pictureID, start, stop, offset, ctm, paint)); 1283d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips fLayerHash.add(layer); 129e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com return layer; 130e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com} 131e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com 1326f294af43bcd94ed9616a7e4f5892589813d0a01robertphillipsGrCachedLayer* GrLayerCache::findLayer(uint32_t pictureID, 1330c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips int start, int stop, 1344815fe5a0a497b676677fb4e4a0f05c511855490robertphillips const SkIPoint& offset, 1350c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips const SkMatrix& ctm) { 1366f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips SkASSERT(pictureID != SK_InvalidGenID && start > 0 && stop > 0); 1374815fe5a0a497b676677fb4e4a0f05c511855490robertphillips return fLayerHash.find(GrCachedLayer::Key(pictureID, start, stop, offset, ctm)); 1384ec84da746d66e1bcb76ab2f8b94602b8e966589robertphillips} 139e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com 1406f294af43bcd94ed9616a7e4f5892589813d0a01robertphillipsGrCachedLayer* GrLayerCache::findLayerOrCreate(uint32_t pictureID, 1410c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips int start, int stop, 1424815fe5a0a497b676677fb4e4a0f05c511855490robertphillips const SkIPoint& offset, 1434aa6dfc0b77af9ac298bb9d48991b72a2fec00b2robertphillips const SkMatrix& ctm, 1444aa6dfc0b77af9ac298bb9d48991b72a2fec00b2robertphillips const SkPaint* paint) { 1456f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips SkASSERT(pictureID != SK_InvalidGenID && start > 0 && stop > 0); 1464815fe5a0a497b676677fb4e4a0f05c511855490robertphillips GrCachedLayer* layer = fLayerHash.find(GrCachedLayer::Key(pictureID, start, stop, offset, ctm)); 147e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com if (NULL == layer) { 1484aa6dfc0b77af9ac298bb9d48991b72a2fec00b2robertphillips layer = this->createLayer(pictureID, start, stop, offset, ctm, paint); 149e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com } 1504ec84da746d66e1bcb76ab2f8b94602b8e966589robertphillips 151e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com return layer; 152e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com} 1534ec84da746d66e1bcb76ab2f8b94602b8e966589robertphillips 1546f294af43bcd94ed9616a7e4f5892589813d0a01robertphillipsbool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc, bool dontAtlas) { 15521048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) 1564ec84da746d66e1bcb76ab2f8b94602b8e966589robertphillips 157320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips if (layer->locked()) { 158952841bf41a81228c23d16c7204b458abe0d7136robertphillips // This layer is already locked 159952841bf41a81228c23d16c7204b458abe0d7136robertphillips#ifdef SK_DEBUG 16021048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips if (layer->isAtlased()) { 161952841bf41a81228c23d16c7204b458abe0d7136robertphillips // It claims to be atlased 1626f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips SkASSERT(!dontAtlas); 163952841bf41a81228c23d16c7204b458abe0d7136robertphillips SkASSERT(layer->rect().width() == desc.fWidth); 164952841bf41a81228c23d16c7204b458abe0d7136robertphillips SkASSERT(layer->rect().height() == desc.fHeight); 165952841bf41a81228c23d16c7204b458abe0d7136robertphillips } 166952841bf41a81228c23d16c7204b458abe0d7136robertphillips#endif 1676f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips return false; 168952841bf41a81228c23d16c7204b458abe0d7136robertphillips } 169952841bf41a81228c23d16c7204b458abe0d7136robertphillips 170320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips if (layer->isAtlased()) { 171320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips // Hooray it is still in the atlas - make sure it stays there 1726f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips SkASSERT(!dontAtlas); 173320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips layer->setLocked(true); 174320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips fPlotLocks[layer->plot()->id()]++; 1756f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips return false; 1766f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips } else if (!dontAtlas && PlausiblyAtlasable(desc.fWidth, desc.fHeight)) { 177320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips // Not in the atlas - will it fit? 1783d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); 179261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips if (NULL == pictInfo) { 180261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); 1813d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips fPictureHash.add(pictInfo); 182261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips } 183261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips 184261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips SkIPoint16 loc; 185320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips for (int i = 0; i < 2; ++i) { // extra pass in case we fail to add but are able to purge 186320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, 187320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips desc.fWidth, desc.fHeight, 188320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips NULL, &loc); 189320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips // addToAtlas can allocate the backing texture 190320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); 19149f085dddff10473b6ebf832a974288300224e60bsalomon if (plot) { 192320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips // The layer was successfully added to the atlas 193320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, 1946f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips SkToS16(desc.fWidth), 195320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips SkToS16(desc.fHeight)); 196320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips layer->setTexture(fAtlas->getTexture(), bounds); 197320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips layer->setPlot(plot); 198320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips layer->setLocked(true); 199320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips fPlotLocks[layer->plot()->id()]++; 2006f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips return true; 201320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips } 202320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 203320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips // The layer was rejected by the atlas (even though we know it is 204320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips // plausibly atlas-able). See if a plot can be purged and try again. 205320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips if (!this->purgePlot()) { 206320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips break; // We weren't able to purge any plots 207320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips } 208261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips } 209952841bf41a81228c23d16c7204b458abe0d7136robertphillips } 210952841bf41a81228c23d16c7204b458abe0d7136robertphillips 21121048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips // The texture wouldn't fit in the cache - give it it's own texture. 212952841bf41a81228c23d16c7204b458abe0d7136robertphillips // This path always uses a new scratch texture and (thus) doesn't cache anything. 2134ec84da746d66e1bcb76ab2f8b94602b8e966589robertphillips // This can yield a lot of re-rendering 214ed6f03e5edea3fb803ac937184796a5bef65cd9brobertphillips SkAutoTUnref<GrTexture> tex(fContext->lockAndRefScratchTexture(desc, 215ed6f03e5edea3fb803ac937184796a5bef65cd9brobertphillips GrContext::kApprox_ScratchTexMatch)); 216ed6f03e5edea3fb803ac937184796a5bef65cd9brobertphillips 217ed6f03e5edea3fb803ac937184796a5bef65cd9brobertphillips layer->setTexture(tex, GrIRect16::MakeWH(SkToS16(desc.fWidth), SkToS16(desc.fHeight))); 218320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips layer->setLocked(true); 2196f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips return true; 2204ec84da746d66e1bcb76ab2f8b94602b8e966589robertphillips} 2214ec84da746d66e1bcb76ab2f8b94602b8e966589robertphillips 2224ec84da746d66e1bcb76ab2f8b94602b8e966589robertphillipsvoid GrLayerCache::unlock(GrCachedLayer* layer) { 22321048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) 22421048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips 225320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips if (NULL == layer || !layer->locked()) { 226320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips // invalid or not locked 2274ec84da746d66e1bcb76ab2f8b94602b8e966589robertphillips return; 2284ec84da746d66e1bcb76ab2f8b94602b8e966589robertphillips } 2294ec84da746d66e1bcb76ab2f8b94602b8e966589robertphillips 23021048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips if (layer->isAtlased()) { 231320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips const int plotID = layer->plot()->id(); 232261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips 233320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips SkASSERT(fPlotLocks[plotID] > 0); 234320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips fPlotLocks[plotID]--; 235320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips // At this point we could aggressively clear out un-locked plots but 236320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips // by delaying we may be able to reuse some of the atlased layers later. 2376f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips#if DISABLE_CACHING 2380c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips // This testing code aggressively removes the atlased layers. This 2390c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips // can be used to separate the performance contribution of less 2400c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips // render target pingponging from that due to the re-use of cached layers 2410c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); 24249f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(pictInfo); 2430c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips 2440c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips GrAtlas::RemovePlot(&pictInfo->fPlotUsage, layer->plot()); 2450c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips 2460c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips layer->setPlot(NULL); 2470c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips layer->setTexture(NULL, GrIRect16::MakeEmpty()); 2480c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips#endif 2490c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips 25021048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips } else { 251952841bf41a81228c23d16c7204b458abe0d7136robertphillips fContext->unlockScratchTexture(layer->texture()); 252952841bf41a81228c23d16c7204b458abe0d7136robertphillips layer->setTexture(NULL, GrIRect16::MakeEmpty()); 253952841bf41a81228c23d16c7204b458abe0d7136robertphillips } 254320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 255320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips layer->setLocked(false); 256952841bf41a81228c23d16c7204b458abe0d7136robertphillips} 257952841bf41a81228c23d16c7204b458abe0d7136robertphillips 25821048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips#ifdef SK_DEBUG 25921048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillipsvoid GrLayerCache::validate() const { 260320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips int plotLocks[kNumPlotsX * kNumPlotsY]; 261320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips memset(plotLocks, 0, sizeof(plotLocks)); 262320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 2633d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::ConstIter iter(&fLayerHash); 2643d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips for (; !iter.done(); ++iter) { 265320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips const GrCachedLayer* layer = &(*iter); 266320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 267320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips layer->validate(fAtlas->getTexture()); 268320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 269320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips const GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); 27049f085dddff10473b6ebf832a974288300224e60bsalomon if (pictInfo) { 271320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips // In aggressive cleanup mode a picture info should only exist if 272320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips // it has some atlased layers 2736f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips#if !DISABLE_CACHING 274320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips SkASSERT(!pictInfo->fPlotUsage.isEmpty()); 2756f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips#endif 276320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips } else { 277320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips // If there is no picture info for this layer then all of its 278320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips // layers should be non-atlased. 279320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips SkASSERT(!layer->isAtlased()); 280320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips } 281320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 28249f085dddff10473b6ebf832a974288300224e60bsalomon if (layer->plot()) { 28349f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(pictInfo); 284320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips SkASSERT(pictInfo->fPictureID == layer->pictureID()); 285320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 286320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips SkASSERT(pictInfo->fPlotUsage.contains(layer->plot())); 287320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 288320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips if (layer->locked()) { 289320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips plotLocks[layer->plot()->id()]++; 290320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips } 291320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips } 292320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips } 293320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 294320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips for (int i = 0; i < kNumPlotsX*kNumPlotsY; ++i) { 295320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips SkASSERT(plotLocks[i] == fPlotLocks[i]); 29621048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips } 29721048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips} 29821048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips 29921048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillipsclass GrAutoValidateCache : ::SkNoncopyable { 30021048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillipspublic: 30121048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips explicit GrAutoValidateCache(GrLayerCache* cache) 30221048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips : fCache(cache) { 30321048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips fCache->validate(); 30421048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips } 30521048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips ~GrAutoValidateCache() { 30621048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips fCache->validate(); 30721048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips } 30821048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillipsprivate: 30921048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips GrLayerCache* fCache; 31021048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips}; 31121048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips#endif 31221048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips 313d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillipsvoid GrLayerCache::purge(uint32_t pictureID) { 314d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips 31521048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips SkDEBUGCODE(GrAutoValidateCache avc(this);) 31621048b588faa6a1c84949603ba82d9d4ba2f0cddrobertphillips 3173d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips // We need to find all the layers associated with 'picture' and remove them. 318952841bf41a81228c23d16c7204b458abe0d7136robertphillips SkTDArray<GrCachedLayer*> toBeRemoved; 319952841bf41a81228c23d16c7204b458abe0d7136robertphillips 3203d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); 3213d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips for (; !iter.done(); ++iter) { 322d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips if (pictureID == (*iter).pictureID()) { 3233d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips *toBeRemoved.append() = &(*iter); 324952841bf41a81228c23d16c7204b458abe0d7136robertphillips } 325952841bf41a81228c23d16c7204b458abe0d7136robertphillips } 326952841bf41a81228c23d16c7204b458abe0d7136robertphillips 327952841bf41a81228c23d16c7204b458abe0d7136robertphillips for (int i = 0; i < toBeRemoved.count(); ++i) { 328952841bf41a81228c23d16c7204b458abe0d7136robertphillips this->unlock(toBeRemoved[i]); 3293d533ac917eaadf2fb3561f57d7266d8c0e665fdrobertphillips fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); 330952841bf41a81228c23d16c7204b458abe0d7136robertphillips SkDELETE(toBeRemoved[i]); 331952841bf41a81228c23d16c7204b458abe0d7136robertphillips } 332261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips 333d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips GrPictureInfo* pictInfo = fPictureHash.find(pictureID); 33449f085dddff10473b6ebf832a974288300224e60bsalomon if (pictInfo) { 335d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips fPictureHash.remove(pictureID); 336261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips SkDELETE(pictInfo); 337261b8a98dc7378989ba8fa9c06b728e89162862brobertphillips } 3384ec84da746d66e1bcb76ab2f8b94602b8e966589robertphillips} 339d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips 340320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillipsbool GrLayerCache::purgePlot() { 341320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips SkDEBUGCODE(GrAutoValidateCache avc(this);) 342320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 343320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips GrAtlas::PlotIter iter; 344320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips GrPlot* plot; 345320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder); 34649f085dddff10473b6ebf832a974288300224e60bsalomon plot; 347320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips plot = iter.prev()) { 348320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips if (fPlotLocks[plot->id()] > 0) { 349320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips continue; 350320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips } 351320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 3526f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips this->purgePlot(plot); 3536f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips return true; 3546f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips } 355320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 3566f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips return false; 3576f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips} 3586f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips 3596f294af43bcd94ed9616a7e4f5892589813d0a01robertphillipsvoid GrLayerCache::purgePlot(GrPlot* plot) { 3606f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips SkASSERT(0 == fPlotLocks[plot->id()]); 3616f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips 3626f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips // We need to find all the layers in 'plot' and remove them. 3636f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips SkTDArray<GrCachedLayer*> toBeRemoved; 3646f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips 3656f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); 3666f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips for (; !iter.done(); ++iter) { 3676f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips if (plot == (*iter).plot()) { 3686f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips *toBeRemoved.append() = &(*iter); 369320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips } 3706f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips } 371320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 3726f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips for (int i = 0; i < toBeRemoved.count(); ++i) { 3736f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips SkASSERT(!toBeRemoved[i]->locked()); 374320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 3756f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips GrPictureInfo* pictInfo = fPictureHash.find(toBeRemoved[i]->pictureID()); 37649f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(pictInfo); 377320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 3786f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips GrAtlas::RemovePlot(&pictInfo->fPlotUsage, plot); 379320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 3806f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips // Aggressively remove layers and, if now totally uncached, picture info 3816f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); 3826f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips SkDELETE(toBeRemoved[i]); 383320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 3846f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips if (pictInfo->fPlotUsage.isEmpty()) { 3856f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips fPictureHash.remove(pictInfo->fPictureID); 3866f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips SkDELETE(pictInfo); 387320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips } 388320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips } 389320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 3906f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips plot->resetRects(); 3916f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips} 3926f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips 3936f294af43bcd94ed9616a7e4f5892589813d0a01robertphillipsvoid GrLayerCache::purgeAll() { 3946f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips GrAtlas::PlotIter iter; 3956f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips GrPlot* plot; 3966f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder); 39749f085dddff10473b6ebf832a974288300224e60bsalomon plot; 3986f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips plot = iter.prev()) { 3996f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips SkASSERT(0 == fPlotLocks[plot->id()]); 4006f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips 4016f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips this->purgePlot(plot); 4026f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips } 403320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips} 404320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips 405d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillipsclass GrPictureDeletionListener : public SkPicture::DeletionListener { 406d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips virtual void onDeletion(uint32_t pictureID) SK_OVERRIDE{ 407d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips const GrPictureDeletedMessage message = { pictureID }; 408d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips SkMessageBus<GrPictureDeletedMessage>::Post(message); 409d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips } 410d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips}; 411d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips 412d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillipsvoid GrLayerCache::trackPicture(const SkPicture* picture) { 413d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips if (NULL == fDeletionListener) { 414d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips fDeletionListener.reset(SkNEW(GrPictureDeletionListener)); 415d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips } 416d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips 417d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips picture->addDeletionListener(fDeletionListener); 418d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips} 419d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips 420d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillipsvoid GrLayerCache::processDeletedPictures() { 421d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips SkTDArray<GrPictureDeletedMessage> deletedPictures; 422d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips fPictDeletionInbox.poll(&deletedPictures); 423d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips 424d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips for (int i = 0; i < deletedPictures.count(); i++) { 425d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips this->purge(deletedPictures[i].pictureID); 426d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips } 427d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips} 428d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips 429