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