blob: 7d6f5ab1b3879b4f1648d459ec6bc3111405622c [file] [log] [blame]
robertphillips98d709b2014-09-02 10:20:50 -07001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrLayerCache.h"
9#include "GrLayerHoister.h"
robertphillips1c4c5282014-09-18 12:03:15 -070010#include "GrRecordReplaceDraw.h"
robertphillips3aac6e02014-10-20 08:52:40 -070011
12#include "SkCanvas.h"
robertphillips7b9e8a42014-12-11 08:20:31 -080013#include "SkGpuDevice.h"
robertphillips1c4c5282014-09-18 12:03:15 -070014#include "SkGrPixelRef.h"
robertphillips82365912014-11-12 09:32:34 -080015#include "SkLayerInfo.h"
robertphillips3aac6e02014-10-20 08:52:40 -070016#include "SkRecordDraw.h"
robertphillips98d709b2014-09-02 10:20:50 -070017#include "SkSurface.h"
robertphillips7b9e8a42014-12-11 08:20:31 -080018#include "SkSurface_Gpu.h"
robertphillips98d709b2014-09-02 10:20:50 -070019
robertphillipscbe80ca2014-10-09 15:36:06 -070020// Create the layer information for the hoisted layer and secure the
21// required texture/render target resources.
22static void prepare_for_hoisting(GrLayerCache* layerCache,
robertphillips232f6b02014-10-09 16:43:42 -070023 const SkPicture* topLevelPicture,
robertphillips01d6e5f2014-12-01 09:09:27 -080024 const SkMatrix& initialMat,
robertphillips82365912014-11-12 09:32:34 -080025 const SkLayerInfo::BlockInfo& info,
robertphillips478dd722014-12-16 08:25:55 -080026 const SkIRect& srcIR,
27 const SkIRect& dstIR,
robertphillipsfd61ed02014-10-28 07:21:44 -070028 SkTDArray<GrHoistedLayer>* needRendering,
29 SkTDArray<GrHoistedLayer>* recycled,
robertphillipsa63f32e2014-11-10 08:10:42 -080030 bool attemptToAtlas,
31 int numSamples) {
robertphillipscbe80ca2014-10-09 15:36:06 -070032 const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture;
33
robertphillips01d6e5f2014-12-01 09:09:27 -080034 GrCachedLayer* layer = layerCache->findLayerOrCreate(topLevelPicture->uniqueID(),
bsalomonfbaace02014-12-12 16:41:46 -080035 SkToInt(info.fSaveLayerOpID),
36 SkToInt(info.fRestoreOpID),
robertphillips478dd722014-12-16 08:25:55 -080037 srcIR,
38 dstIR,
robertphillips01d6e5f2014-12-01 09:09:27 -080039 initialMat,
40 info.fKey,
41 info.fKeySize,
robertphillipscbe80ca2014-10-09 15:36:06 -070042 info.fPaint);
bsalomonf2703d82014-10-28 14:33:06 -070043 GrSurfaceDesc desc;
44 desc.fFlags = kRenderTarget_GrSurfaceFlag;
robertphillips478dd722014-12-16 08:25:55 -080045 desc.fWidth = srcIR.width();
46 desc.fHeight = srcIR.height();
robertphillipscbe80ca2014-10-09 15:36:06 -070047 desc.fConfig = kSkia8888_GrPixelConfig;
robertphillipsa63f32e2014-11-10 08:10:42 -080048 desc.fSampleCnt = numSamples;
robertphillipscbe80ca2014-10-09 15:36:06 -070049
robertphillipsfd61ed02014-10-28 07:21:44 -070050 bool locked, needsRendering;
51 if (attemptToAtlas) {
52 locked = layerCache->tryToAtlas(layer, desc, &needsRendering);
53 } else {
54 locked = layerCache->lock(layer, desc, &needsRendering);
55 }
56 if (!locked) {
robertphillipscbe80ca2014-10-09 15:36:06 -070057 // GPU resources could not be secured for the hoisting of this layer
58 return;
59 }
60
robertphillipsfd61ed02014-10-28 07:21:44 -070061 if (attemptToAtlas) {
62 SkASSERT(layer->isAtlased());
63 }
64
robertphillipscbe80ca2014-10-09 15:36:06 -070065 GrHoistedLayer* hl;
66
67 if (needsRendering) {
robertphillipsfd61ed02014-10-28 07:21:44 -070068 if (!attemptToAtlas) {
69 SkASSERT(!layer->isAtlased());
robertphillipscbe80ca2014-10-09 15:36:06 -070070 }
robertphillipsfd61ed02014-10-28 07:21:44 -070071 hl = needRendering->append();
robertphillipscbe80ca2014-10-09 15:36:06 -070072 } else {
73 hl = recycled->append();
74 }
75
robertphillips7bb9ed72014-10-10 11:38:29 -070076 layerCache->addUse(layer);
robertphillipscbe80ca2014-10-09 15:36:06 -070077 hl->fLayer = layer;
78 hl->fPicture = pict;
robertphillips9e6835d2014-10-22 05:33:52 -070079 hl->fLocalMat = info.fLocalMat;
robertphillips01d6e5f2014-12-01 09:09:27 -080080 hl->fInitialMat = initialMat;
81 hl->fPreMat = initialMat;
robertphillips30d78412014-11-24 09:49:17 -080082 hl->fPreMat.preConcat(info.fPreMat);
robertphillipscbe80ca2014-10-09 15:36:06 -070083}
84
robertphillips57f192d2015-01-08 10:15:25 -080085// Compute the source rect and return false if it is empty.
robertphillips478dd722014-12-16 08:25:55 -080086static bool compute_source_rect(const SkLayerInfo::BlockInfo& info, const SkMatrix& initialMat,
87 const SkIRect& dstIR, SkIRect* srcIR) {
88 SkIRect clipBounds = dstIR;
89
90 SkMatrix totMat = initialMat;
91 totMat.preConcat(info.fPreMat);
92 totMat.preConcat(info.fLocalMat);
93
94 if (info.fPaint && info.fPaint->getImageFilter()) {
95 info.fPaint->getImageFilter()->filterBounds(clipBounds, totMat, &clipBounds);
96 }
97
98 if (!info.fSrcBounds.isEmpty()) {
99 SkRect r;
100
101 totMat.mapRect(&r, info.fSrcBounds);
102 r.roundOut(srcIR);
103
104 if (!srcIR->intersect(clipBounds)) {
105 return false;
106 }
107 } else {
108 *srcIR = clipBounds;
109 }
110
robertphillips478dd722014-12-16 08:25:55 -0800111 return true;
112}
113
robertphillipsfd61ed02014-10-28 07:21:44 -0700114// Atlased layers must be small enough to fit in the atlas, not have a
115// paint with an image filter and be neither nested nor nesting.
116// TODO: allow leaf nested layers to appear in the atlas.
117void GrLayerHoister::FindLayersToAtlas(GrContext* context,
robertphillipsd61ef012014-10-08 05:17:02 -0700118 const SkPicture* topLevelPicture,
robertphillips30d78412014-11-24 09:49:17 -0800119 const SkMatrix& initialMat,
robertphillips98d709b2014-09-02 10:20:50 -0700120 const SkRect& query,
robertphillipsd61ef012014-10-08 05:17:02 -0700121 SkTDArray<GrHoistedLayer>* atlased,
robertphillipsa63f32e2014-11-10 08:10:42 -0800122 SkTDArray<GrHoistedLayer>* recycled,
123 int numSamples) {
124 if (0 != numSamples) {
125 // MSAA layers are currently never atlased
126 return;
127 }
128
robertphillipsd61ef012014-10-08 05:17:02 -0700129 GrLayerCache* layerCache = context->getLayerCache();
130
131 layerCache->processDeletedPictures();
132
robertphillips82365912014-11-12 09:32:34 -0800133 SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
robertphillips30d2cc62014-09-24 08:52:18 -0700134
135 const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key);
robertphillipscbe80ca2014-10-09 15:36:06 -0700136 if (!topLevelData) {
robertphillipsfd61ed02014-10-28 07:21:44 -0700137 return;
robertphillips30d2cc62014-09-24 08:52:18 -0700138 }
139
robertphillips82365912014-11-12 09:32:34 -0800140 const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData);
141 if (0 == topLevelGPUData->numBlocks()) {
robertphillipsfd61ed02014-10-28 07:21:44 -0700142 return;
robertphillips30d2cc62014-09-24 08:52:18 -0700143 }
144
robertphillips82365912014-11-12 09:32:34 -0800145 atlased->setReserve(atlased->count() + topLevelGPUData->numBlocks());
robertphillipscbe80ca2014-10-09 15:36:06 -0700146
robertphillips82365912014-11-12 09:32:34 -0800147 for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) {
148 const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i);
robertphillips98d709b2014-09-02 10:20:50 -0700149
robertphillipsfd61ed02014-10-28 07:21:44 -0700150 // TODO: ignore perspective projected layers here?
151 bool disallowAtlasing = info.fHasNestedLayers || info.fIsNested ||
152 (info.fPaint && info.fPaint->getImageFilter());
153
154 if (disallowAtlasing) {
155 continue;
156 }
157
robertphillips30d78412014-11-24 09:49:17 -0800158 SkRect layerRect;
159 initialMat.mapRect(&layerRect, info.fBounds);
robertphillips3aac6e02014-10-20 08:52:40 -0700160 if (!layerRect.intersect(query)) {
robertphillips2ed8a752014-09-03 13:46:02 -0700161 continue;
robertphillips98d709b2014-09-02 10:20:50 -0700162 }
robertphillips98d709b2014-09-02 10:20:50 -0700163
robertphillips478dd722014-12-16 08:25:55 -0800164 const SkIRect dstIR = layerRect.roundOut();
robertphillips3aac6e02014-10-20 08:52:40 -0700165
robertphillips478dd722014-12-16 08:25:55 -0800166 SkIRect srcIR;
167
robertphillips57f192d2015-01-08 10:15:25 -0800168 if (!compute_source_rect(info, initialMat, dstIR, &srcIR) ||
169 !GrLayerCache::PlausiblyAtlasable(srcIR.width(), srcIR.height())) {
robertphillips2ed8a752014-09-03 13:46:02 -0700170 continue;
robertphillips98d709b2014-09-02 10:20:50 -0700171 }
robertphillips2ed8a752014-09-03 13:46:02 -0700172
robertphillips30d78412014-11-24 09:49:17 -0800173 prepare_for_hoisting(layerCache, topLevelPicture, initialMat,
robertphillips478dd722014-12-16 08:25:55 -0800174 info, srcIR, dstIR, atlased, recycled, true, 0);
robertphillips98d709b2014-09-02 10:20:50 -0700175 }
176
robertphillipsfd61ed02014-10-28 07:21:44 -0700177}
178
179void GrLayerHoister::FindLayersToHoist(GrContext* context,
180 const SkPicture* topLevelPicture,
robertphillips30d78412014-11-24 09:49:17 -0800181 const SkMatrix& initialMat,
robertphillipsfd61ed02014-10-28 07:21:44 -0700182 const SkRect& query,
183 SkTDArray<GrHoistedLayer>* needRendering,
robertphillipsa63f32e2014-11-10 08:10:42 -0800184 SkTDArray<GrHoistedLayer>* recycled,
185 int numSamples) {
robertphillipsfd61ed02014-10-28 07:21:44 -0700186 GrLayerCache* layerCache = context->getLayerCache();
187
188 layerCache->processDeletedPictures();
189
robertphillips82365912014-11-12 09:32:34 -0800190 SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
robertphillipsfd61ed02014-10-28 07:21:44 -0700191
192 const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key);
193 if (!topLevelData) {
194 return;
195 }
196
robertphillips82365912014-11-12 09:32:34 -0800197 const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData);
198 if (0 == topLevelGPUData->numBlocks()) {
robertphillipsfd61ed02014-10-28 07:21:44 -0700199 return;
200 }
201
202 // Find and prepare for hoisting all the layers that intersect the query rect
robertphillips82365912014-11-12 09:32:34 -0800203 for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) {
204 const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i);
robertphillipsfd61ed02014-10-28 07:21:44 -0700205 if (info.fIsNested) {
206 // Parent layers are currently hoisted while nested layers are not.
207 continue;
208 }
209
robertphillips30d78412014-11-24 09:49:17 -0800210 SkRect layerRect;
211 initialMat.mapRect(&layerRect, info.fBounds);
robertphillipsfd61ed02014-10-28 07:21:44 -0700212 if (!layerRect.intersect(query)) {
213 continue;
214 }
215
robertphillips478dd722014-12-16 08:25:55 -0800216 const SkIRect dstIR = layerRect.roundOut();
robertphillipsfd61ed02014-10-28 07:21:44 -0700217
robertphillips478dd722014-12-16 08:25:55 -0800218 SkIRect srcIR;
219 if (!compute_source_rect(info, initialMat, dstIR, &srcIR)) {
220 continue;
221 }
222
223 prepare_for_hoisting(layerCache, topLevelPicture, initialMat, info, srcIR, dstIR,
robertphillipsa63f32e2014-11-10 08:10:42 -0800224 needRendering, recycled, false, numSamples);
robertphillipsfd61ed02014-10-28 07:21:44 -0700225 }
robertphillips98d709b2014-09-02 10:20:50 -0700226}
227
robertphillipsfd61ed02014-10-28 07:21:44 -0700228void GrLayerHoister::DrawLayersToAtlas(GrContext* context,
229 const SkTDArray<GrHoistedLayer>& atlased) {
robertphillips98d709b2014-09-02 10:20:50 -0700230 if (atlased.count() > 0) {
231 // All the atlased layers are rendered into the same GrTexture
robertphillipsa86a2332014-12-16 14:25:08 -0800232 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
robertphillips98d709b2014-09-02 10:20:50 -0700233 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
robertphillipsa86a2332014-12-16 14:25:08 -0800234 atlased[0].fLayer->texture()->asRenderTarget(), &props));
robertphillips98d709b2014-09-02 10:20:50 -0700235
236 SkCanvas* atlasCanvas = surface->getCanvas();
237
robertphillips98d709b2014-09-02 10:20:50 -0700238 for (int i = 0; i < atlased.count(); ++i) {
robertphillips9e6835d2014-10-22 05:33:52 -0700239 const GrCachedLayer* layer = atlased[i].fLayer;
robertphillips30d2cc62014-09-24 08:52:18 -0700240 const SkPicture* pict = atlased[i].fPicture;
robertphillips478dd722014-12-16 08:25:55 -0800241 const SkIPoint offset = SkIPoint::Make(layer->srcIR().fLeft, layer->srcIR().fTop);
robertphillips9e6835d2014-10-22 05:33:52 -0700242 SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();)
243
244 SkASSERT(!layerPaint || !layerPaint->getImageFilter());
robertphillips7b9e8a42014-12-11 08:20:31 -0800245 SkASSERT(!layer->filter());
robertphillips98d709b2014-09-02 10:20:50 -0700246
247 atlasCanvas->save();
248
249 // Add a rect clip to make sure the rendering doesn't
250 // extend beyond the boundaries of the atlased sub-rect
robertphillipse99d4992014-12-03 07:33:57 -0800251 const SkRect bound = SkRect::Make(layer->rect());
robertphillips98d709b2014-09-02 10:20:50 -0700252 atlasCanvas->clipRect(bound);
reed8eddfb52014-12-04 07:50:14 -0800253 atlasCanvas->clear(0);
robertphillips98d709b2014-09-02 10:20:50 -0700254
robertphillipsfd61ed02014-10-28 07:21:44 -0700255 // '-offset' maps the layer's top/left to the origin.
robertphillips98d709b2014-09-02 10:20:50 -0700256 // Since this layer is atlased, the top/left corner needs
257 // to be offset to the correct location in the backing texture.
robertphillips4815fe52014-09-16 10:32:43 -0700258 SkMatrix initialCTM;
robertphillipsfd61ed02014-10-28 07:21:44 -0700259 initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY));
260 initialCTM.preTranslate(bound.fLeft, bound.fTop);
261 initialCTM.preConcat(atlased[i].fPreMat);
robertphillips9e6835d2014-10-22 05:33:52 -0700262
robertphillipsfd61ed02014-10-28 07:21:44 -0700263 atlasCanvas->setMatrix(initialCTM);
robertphillips9e6835d2014-10-22 05:33:52 -0700264 atlasCanvas->concat(atlased[i].fLocalMat);
robertphillips98d709b2014-09-02 10:20:50 -0700265
reed6be2aa92014-11-18 11:08:05 -0800266 SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas,
267 pict->drawablePicts(), pict->drawableCount(),
reed8eddfb52014-12-04 07:50:14 -0800268 layer->start() + 1, layer->stop(), initialCTM);
robertphillips98d709b2014-09-02 10:20:50 -0700269
270 atlasCanvas->restore();
271 }
272
273 atlasCanvas->flush();
274 }
robertphillipsfd61ed02014-10-28 07:21:44 -0700275}
robertphillips98d709b2014-09-02 10:20:50 -0700276
robertphillips478dd722014-12-16 08:25:55 -0800277void GrLayerHoister::FilterLayer(GrContext* context,
278 SkGpuDevice* device,
279 const GrHoistedLayer& info) {
280 GrCachedLayer* layer = info.fLayer;
281
robertphillips7b9e8a42014-12-11 08:20:31 -0800282 SkASSERT(layer->filter());
robertphillips478dd722014-12-16 08:25:55 -0800283 SkASSERT(layer->filter()->canFilterImageGPU());
robertphillips7b9e8a42014-12-11 08:20:31 -0800284
285 static const int kDefaultCacheSize = 32 * 1024 * 1024;
286
robertphillips478dd722014-12-16 08:25:55 -0800287 SkBitmap filteredBitmap;
288 SkIPoint offset = SkIPoint::Make(0, 0);
robertphillips7b9e8a42014-12-11 08:20:31 -0800289
robertphillips478dd722014-12-16 08:25:55 -0800290 const SkIPoint filterOffset = SkIPoint::Make(layer->srcIR().fLeft, layer->srcIR().fTop);
robertphillips7b9e8a42014-12-11 08:20:31 -0800291
robertphillips478dd722014-12-16 08:25:55 -0800292 SkMatrix totMat = SkMatrix::I();
293 totMat.preConcat(info.fPreMat);
294 totMat.preConcat(info.fLocalMat);
295 totMat.postTranslate(-SkIntToScalar(filterOffset.fX), -SkIntToScalar(filterOffset.fY));
robertphillips7b9e8a42014-12-11 08:20:31 -0800296
robertphillips7b9e8a42014-12-11 08:20:31 -0800297
robertphillips478dd722014-12-16 08:25:55 -0800298 SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop);
299 SkIRect clipBounds = layer->rect();
robertphillips7b9e8a42014-12-11 08:20:31 -0800300
robertphillips478dd722014-12-16 08:25:55 -0800301 // This cache is transient, and is freed (along with all its contained
302 // textures) when it goes out of scope.
303 SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(kDefaultCacheSize));
304 SkImageFilter::Context filterContext(totMat, clipBounds, cache);
305
306 if (!device->filterTexture(context, layer->texture(), layer->filter(),
307 filterContext, &filteredBitmap, &offset)) {
308 // Filtering failed. Press on with the unfiltered version
309 return;
robertphillips7b9e8a42014-12-11 08:20:31 -0800310 }
robertphillips478dd722014-12-16 08:25:55 -0800311
312 SkIRect newRect = SkIRect::MakeWH(filteredBitmap.width(), filteredBitmap.height());
313 layer->setTexture(filteredBitmap.getTexture(), newRect);
314 layer->setOffset(offset);
robertphillips7b9e8a42014-12-11 08:20:31 -0800315}
316
robertphillipsfd61ed02014-10-28 07:21:44 -0700317void GrLayerHoister::DrawLayers(GrContext* context, const SkTDArray<GrHoistedLayer>& layers) {
318 for (int i = 0; i < layers.count(); ++i) {
319 GrCachedLayer* layer = layers[i].fLayer;
320 const SkPicture* pict = layers[i].fPicture;
robertphillips478dd722014-12-16 08:25:55 -0800321 const SkIPoint offset = SkIPoint::Make(layer->srcIR().fLeft, layer->srcIR().fTop);
robertphillips98d709b2014-09-02 10:20:50 -0700322
323 // Each non-atlased layer has its own GrTexture
robertphillipsa86a2332014-12-16 14:25:08 -0800324 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
robertphillips98d709b2014-09-02 10:20:50 -0700325 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
robertphillipsa86a2332014-12-16 14:25:08 -0800326 layer->texture()->asRenderTarget(), &props));
robertphillips98d709b2014-09-02 10:20:50 -0700327
328 SkCanvas* layerCanvas = surface->getCanvas();
329
robertphillips9e6835d2014-10-22 05:33:52 -0700330 SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop);
331
robertphillips98d709b2014-09-02 10:20:50 -0700332 // Add a rect clip to make sure the rendering doesn't
robertphillipsfd61ed02014-10-28 07:21:44 -0700333 // extend beyond the boundaries of the layer
robertphillipse99d4992014-12-03 07:33:57 -0800334 const SkRect bound = SkRect::Make(layer->rect());
robertphillipsfd61ed02014-10-28 07:21:44 -0700335 layerCanvas->clipRect(bound);
robertphillips98d709b2014-09-02 10:20:50 -0700336 layerCanvas->clear(SK_ColorTRANSPARENT);
337
robertphillips4815fe52014-09-16 10:32:43 -0700338 SkMatrix initialCTM;
robertphillips9e6835d2014-10-22 05:33:52 -0700339 initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY));
robertphillipsfd61ed02014-10-28 07:21:44 -0700340 initialCTM.preConcat(layers[i].fPreMat);
robertphillips4815fe52014-09-16 10:32:43 -0700341
robertphillipsfd61ed02014-10-28 07:21:44 -0700342 layerCanvas->setMatrix(initialCTM);
343 layerCanvas->concat(layers[i].fLocalMat);
robertphillips98d709b2014-09-02 10:20:50 -0700344
reed6be2aa92014-11-18 11:08:05 -0800345 SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas,
346 pict->drawablePicts(), pict->drawableCount(),
reed8eddfb52014-12-04 07:50:14 -0800347 layer->start()+1, layer->stop(), initialCTM);
robertphillips98d709b2014-09-02 10:20:50 -0700348
349 layerCanvas->flush();
robertphillips7b9e8a42014-12-11 08:20:31 -0800350
351 if (layer->filter()) {
352 SkSurface_Gpu* gpuSurf = static_cast<SkSurface_Gpu*>(surface.get());
353
robertphillips478dd722014-12-16 08:25:55 -0800354 FilterLayer(context, gpuSurf->getDevice(), layers[i]);
robertphillips7b9e8a42014-12-11 08:20:31 -0800355 }
robertphillips98d709b2014-09-02 10:20:50 -0700356 }
357}
358
robertphillipsd61ef012014-10-08 05:17:02 -0700359void GrLayerHoister::UnlockLayers(GrContext* context,
robertphillipsfd61ed02014-10-28 07:21:44 -0700360 const SkTDArray<GrHoistedLayer>& layers) {
robertphillipsd61ef012014-10-08 05:17:02 -0700361 GrLayerCache* layerCache = context->getLayerCache();
robertphillips30d2cc62014-09-24 08:52:18 -0700362
robertphillipsfd61ed02014-10-28 07:21:44 -0700363 for (int i = 0; i < layers.count(); ++i) {
364 layerCache->removeUse(layers[i].fLayer);
robertphillipsb5a97152014-09-30 11:33:02 -0700365 }
366
robertphillips4ab5a902014-10-29 13:56:02 -0700367 SkDEBUGCODE(layerCache->validate();)
368}
369
370void GrLayerHoister::PurgeCache(GrContext* context) {
371#if !GR_CACHE_HOISTED_LAYERS
372 GrLayerCache* layerCache = context->getLayerCache();
373
robertphillips30d2cc62014-09-24 08:52:18 -0700374 // This code completely clears out the atlas. It is required when
375 // caching is disabled so the atlas doesn't fill up and force more
376 // free floating layers
robertphillips98d709b2014-09-02 10:20:50 -0700377 layerCache->purgeAll();
378#endif
robertphillips98d709b2014-09-02 10:20:50 -0700379}