blob: 493e2f752a53440d9e46cb145a55a1a85433c8bc [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,
robertphillips3aac6e02014-10-20 08:52:40 -070026 const SkIRect& layerRect,
robertphillipsfd61ed02014-10-28 07:21:44 -070027 SkTDArray<GrHoistedLayer>* needRendering,
28 SkTDArray<GrHoistedLayer>* recycled,
robertphillipsa63f32e2014-11-10 08:10:42 -080029 bool attemptToAtlas,
30 int numSamples) {
robertphillipscbe80ca2014-10-09 15:36:06 -070031 const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture;
32
robertphillips01d6e5f2014-12-01 09:09:27 -080033 GrCachedLayer* layer = layerCache->findLayerOrCreate(topLevelPicture->uniqueID(),
robertphillipscbe80ca2014-10-09 15:36:06 -070034 info.fSaveLayerOpID,
35 info.fRestoreOpID,
robertphillips3aac6e02014-10-20 08:52:40 -070036 layerRect,
robertphillips01d6e5f2014-12-01 09:09:27 -080037 initialMat,
38 info.fKey,
39 info.fKeySize,
robertphillipscbe80ca2014-10-09 15:36:06 -070040 info.fPaint);
bsalomonf2703d82014-10-28 14:33:06 -070041 GrSurfaceDesc desc;
42 desc.fFlags = kRenderTarget_GrSurfaceFlag;
robertphillips3aac6e02014-10-20 08:52:40 -070043 desc.fWidth = layerRect.width();
44 desc.fHeight = layerRect.height();
robertphillipscbe80ca2014-10-09 15:36:06 -070045 desc.fConfig = kSkia8888_GrPixelConfig;
robertphillipsa63f32e2014-11-10 08:10:42 -080046 desc.fSampleCnt = numSamples;
robertphillipscbe80ca2014-10-09 15:36:06 -070047
robertphillipsfd61ed02014-10-28 07:21:44 -070048 bool locked, needsRendering;
49 if (attemptToAtlas) {
50 locked = layerCache->tryToAtlas(layer, desc, &needsRendering);
51 } else {
52 locked = layerCache->lock(layer, desc, &needsRendering);
53 }
54 if (!locked) {
robertphillipscbe80ca2014-10-09 15:36:06 -070055 // GPU resources could not be secured for the hoisting of this layer
56 return;
57 }
58
robertphillipsfd61ed02014-10-28 07:21:44 -070059 if (attemptToAtlas) {
60 SkASSERT(layer->isAtlased());
61 }
62
robertphillipscbe80ca2014-10-09 15:36:06 -070063 GrHoistedLayer* hl;
64
65 if (needsRendering) {
robertphillipsfd61ed02014-10-28 07:21:44 -070066 if (!attemptToAtlas) {
67 SkASSERT(!layer->isAtlased());
robertphillipscbe80ca2014-10-09 15:36:06 -070068 }
robertphillipsfd61ed02014-10-28 07:21:44 -070069 hl = needRendering->append();
robertphillipscbe80ca2014-10-09 15:36:06 -070070 } else {
71 hl = recycled->append();
72 }
73
robertphillips7bb9ed72014-10-10 11:38:29 -070074 layerCache->addUse(layer);
robertphillipscbe80ca2014-10-09 15:36:06 -070075 hl->fLayer = layer;
76 hl->fPicture = pict;
robertphillips9e6835d2014-10-22 05:33:52 -070077 hl->fLocalMat = info.fLocalMat;
robertphillips01d6e5f2014-12-01 09:09:27 -080078 hl->fInitialMat = initialMat;
79 hl->fPreMat = initialMat;
robertphillips30d78412014-11-24 09:49:17 -080080 hl->fPreMat.preConcat(info.fPreMat);
robertphillipscbe80ca2014-10-09 15:36:06 -070081}
82
robertphillipsfd61ed02014-10-28 07:21:44 -070083// Atlased layers must be small enough to fit in the atlas, not have a
84// paint with an image filter and be neither nested nor nesting.
85// TODO: allow leaf nested layers to appear in the atlas.
86void GrLayerHoister::FindLayersToAtlas(GrContext* context,
robertphillipsd61ef012014-10-08 05:17:02 -070087 const SkPicture* topLevelPicture,
robertphillips30d78412014-11-24 09:49:17 -080088 const SkMatrix& initialMat,
robertphillips98d709b2014-09-02 10:20:50 -070089 const SkRect& query,
robertphillipsd61ef012014-10-08 05:17:02 -070090 SkTDArray<GrHoistedLayer>* atlased,
robertphillipsa63f32e2014-11-10 08:10:42 -080091 SkTDArray<GrHoistedLayer>* recycled,
92 int numSamples) {
93 if (0 != numSamples) {
94 // MSAA layers are currently never atlased
95 return;
96 }
97
robertphillipsd61ef012014-10-08 05:17:02 -070098 GrLayerCache* layerCache = context->getLayerCache();
99
100 layerCache->processDeletedPictures();
101
robertphillips82365912014-11-12 09:32:34 -0800102 SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
robertphillips30d2cc62014-09-24 08:52:18 -0700103
104 const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key);
robertphillipscbe80ca2014-10-09 15:36:06 -0700105 if (!topLevelData) {
robertphillipsfd61ed02014-10-28 07:21:44 -0700106 return;
robertphillips30d2cc62014-09-24 08:52:18 -0700107 }
108
robertphillips82365912014-11-12 09:32:34 -0800109 const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData);
110 if (0 == topLevelGPUData->numBlocks()) {
robertphillipsfd61ed02014-10-28 07:21:44 -0700111 return;
robertphillips30d2cc62014-09-24 08:52:18 -0700112 }
113
robertphillips82365912014-11-12 09:32:34 -0800114 atlased->setReserve(atlased->count() + topLevelGPUData->numBlocks());
robertphillipscbe80ca2014-10-09 15:36:06 -0700115
robertphillips82365912014-11-12 09:32:34 -0800116 for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) {
117 const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i);
robertphillips98d709b2014-09-02 10:20:50 -0700118
robertphillipsfd61ed02014-10-28 07:21:44 -0700119 // TODO: ignore perspective projected layers here?
120 bool disallowAtlasing = info.fHasNestedLayers || info.fIsNested ||
121 (info.fPaint && info.fPaint->getImageFilter());
122
123 if (disallowAtlasing) {
124 continue;
125 }
126
robertphillips30d78412014-11-24 09:49:17 -0800127 SkRect layerRect;
128 initialMat.mapRect(&layerRect, info.fBounds);
robertphillips3aac6e02014-10-20 08:52:40 -0700129 if (!layerRect.intersect(query)) {
robertphillips2ed8a752014-09-03 13:46:02 -0700130 continue;
robertphillips98d709b2014-09-02 10:20:50 -0700131 }
robertphillips98d709b2014-09-02 10:20:50 -0700132
robertphillips30d78412014-11-24 09:49:17 -0800133 const SkIRect ir = layerRect.roundOut();
robertphillips3aac6e02014-10-20 08:52:40 -0700134
robertphillipsfd61ed02014-10-28 07:21:44 -0700135 if (!GrLayerCache::PlausiblyAtlasable(ir.width(), ir.height())) {
robertphillips2ed8a752014-09-03 13:46:02 -0700136 continue;
robertphillips98d709b2014-09-02 10:20:50 -0700137 }
robertphillips2ed8a752014-09-03 13:46:02 -0700138
robertphillips30d78412014-11-24 09:49:17 -0800139 prepare_for_hoisting(layerCache, topLevelPicture, initialMat,
140 info, ir, atlased, recycled, true, 0);
robertphillips98d709b2014-09-02 10:20:50 -0700141 }
142
robertphillipsfd61ed02014-10-28 07:21:44 -0700143}
144
145void GrLayerHoister::FindLayersToHoist(GrContext* context,
146 const SkPicture* topLevelPicture,
robertphillips30d78412014-11-24 09:49:17 -0800147 const SkMatrix& initialMat,
robertphillipsfd61ed02014-10-28 07:21:44 -0700148 const SkRect& query,
149 SkTDArray<GrHoistedLayer>* needRendering,
robertphillipsa63f32e2014-11-10 08:10:42 -0800150 SkTDArray<GrHoistedLayer>* recycled,
151 int numSamples) {
robertphillipsfd61ed02014-10-28 07:21:44 -0700152 GrLayerCache* layerCache = context->getLayerCache();
153
154 layerCache->processDeletedPictures();
155
robertphillips82365912014-11-12 09:32:34 -0800156 SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
robertphillipsfd61ed02014-10-28 07:21:44 -0700157
158 const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key);
159 if (!topLevelData) {
160 return;
161 }
162
robertphillips82365912014-11-12 09:32:34 -0800163 const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData);
164 if (0 == topLevelGPUData->numBlocks()) {
robertphillipsfd61ed02014-10-28 07:21:44 -0700165 return;
166 }
167
168 // Find and prepare for hoisting all the layers that intersect the query rect
robertphillips82365912014-11-12 09:32:34 -0800169 for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) {
170 const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i);
robertphillipsfd61ed02014-10-28 07:21:44 -0700171 if (info.fIsNested) {
172 // Parent layers are currently hoisted while nested layers are not.
173 continue;
174 }
175
robertphillips30d78412014-11-24 09:49:17 -0800176 SkRect layerRect;
177 initialMat.mapRect(&layerRect, info.fBounds);
robertphillipsfd61ed02014-10-28 07:21:44 -0700178 if (!layerRect.intersect(query)) {
179 continue;
180 }
181
robertphillips30d78412014-11-24 09:49:17 -0800182 const SkIRect ir = layerRect.roundOut();
robertphillipsfd61ed02014-10-28 07:21:44 -0700183
robertphillips30d78412014-11-24 09:49:17 -0800184 prepare_for_hoisting(layerCache, topLevelPicture, initialMat, info, ir,
robertphillipsa63f32e2014-11-10 08:10:42 -0800185 needRendering, recycled, false, numSamples);
robertphillipsfd61ed02014-10-28 07:21:44 -0700186 }
robertphillips98d709b2014-09-02 10:20:50 -0700187}
188
robertphillipsfd61ed02014-10-28 07:21:44 -0700189void GrLayerHoister::DrawLayersToAtlas(GrContext* context,
190 const SkTDArray<GrHoistedLayer>& atlased) {
robertphillips98d709b2014-09-02 10:20:50 -0700191 if (atlased.count() > 0) {
192 // All the atlased layers are rendered into the same GrTexture
193 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
robertphillips30d2cc62014-09-24 08:52:18 -0700194 atlased[0].fLayer->texture()->asRenderTarget(), NULL));
robertphillips98d709b2014-09-02 10:20:50 -0700195
196 SkCanvas* atlasCanvas = surface->getCanvas();
197
robertphillips98d709b2014-09-02 10:20:50 -0700198 for (int i = 0; i < atlased.count(); ++i) {
robertphillips9e6835d2014-10-22 05:33:52 -0700199 const GrCachedLayer* layer = atlased[i].fLayer;
robertphillips30d2cc62014-09-24 08:52:18 -0700200 const SkPicture* pict = atlased[i].fPicture;
robertphillipse99d4992014-12-03 07:33:57 -0800201 const SkIPoint offset = SkIPoint::Make(layer->bound().fLeft, layer->bound().fTop);
robertphillips9e6835d2014-10-22 05:33:52 -0700202 SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();)
203
204 SkASSERT(!layerPaint || !layerPaint->getImageFilter());
robertphillips7b9e8a42014-12-11 08:20:31 -0800205 SkASSERT(!layer->filter());
robertphillips98d709b2014-09-02 10:20:50 -0700206
207 atlasCanvas->save();
208
209 // Add a rect clip to make sure the rendering doesn't
210 // extend beyond the boundaries of the atlased sub-rect
robertphillipse99d4992014-12-03 07:33:57 -0800211 const SkRect bound = SkRect::Make(layer->rect());
robertphillips98d709b2014-09-02 10:20:50 -0700212 atlasCanvas->clipRect(bound);
reed8eddfb52014-12-04 07:50:14 -0800213 atlasCanvas->clear(0);
robertphillips98d709b2014-09-02 10:20:50 -0700214
robertphillipsfd61ed02014-10-28 07:21:44 -0700215 // '-offset' maps the layer's top/left to the origin.
robertphillips98d709b2014-09-02 10:20:50 -0700216 // Since this layer is atlased, the top/left corner needs
217 // to be offset to the correct location in the backing texture.
robertphillips4815fe52014-09-16 10:32:43 -0700218 SkMatrix initialCTM;
robertphillipsfd61ed02014-10-28 07:21:44 -0700219 initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY));
220 initialCTM.preTranslate(bound.fLeft, bound.fTop);
221 initialCTM.preConcat(atlased[i].fPreMat);
robertphillips9e6835d2014-10-22 05:33:52 -0700222
robertphillipsfd61ed02014-10-28 07:21:44 -0700223 atlasCanvas->setMatrix(initialCTM);
robertphillips9e6835d2014-10-22 05:33:52 -0700224 atlasCanvas->concat(atlased[i].fLocalMat);
robertphillips98d709b2014-09-02 10:20:50 -0700225
reed6be2aa92014-11-18 11:08:05 -0800226 SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas,
227 pict->drawablePicts(), pict->drawableCount(),
reed8eddfb52014-12-04 07:50:14 -0800228 layer->start() + 1, layer->stop(), initialCTM);
robertphillips98d709b2014-09-02 10:20:50 -0700229
230 atlasCanvas->restore();
231 }
232
233 atlasCanvas->flush();
234 }
robertphillipsfd61ed02014-10-28 07:21:44 -0700235}
robertphillips98d709b2014-09-02 10:20:50 -0700236
robertphillips7b9e8a42014-12-11 08:20:31 -0800237void GrLayerHoister::FilterLayer(GrContext* context, SkGpuDevice* device, GrCachedLayer* layer) {
238 SkASSERT(layer->filter());
239
240 static const int kDefaultCacheSize = 32 * 1024 * 1024;
241
242 if (layer->filter()->canFilterImageGPU()) {
243 SkBitmap filteredBitmap;
244 SkIPoint offset = SkIPoint::Make(0, 0);
245
246 SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop);
247 SkIRect clipBounds = layer->rect();
248
249 // This cache is transient, and is freed (along with all its contained
250 // textures) when it goes out of scope.
251 SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(kDefaultCacheSize));
252 SkImageFilter::Context filterContext(SkMatrix::I(), clipBounds, cache);
253
254 if (!device->filterTexture(context, layer->texture(), layer->filter(),
255 filterContext, &filteredBitmap, &offset)) {
256 // Filtering failed. Press on with the unfiltered version
257 return;
258 }
259
260 // TODO: need to fix up offset
261 SkASSERT(0 == offset.fX && 0 == offset.fY);
262
263 SkIRect newRect = SkIRect::MakeWH(filteredBitmap.width(), filteredBitmap.height());
264 layer->setTexture(filteredBitmap.getTexture(), newRect);
265 }
266}
267
robertphillipsfd61ed02014-10-28 07:21:44 -0700268void GrLayerHoister::DrawLayers(GrContext* context, const SkTDArray<GrHoistedLayer>& layers) {
269 for (int i = 0; i < layers.count(); ++i) {
270 GrCachedLayer* layer = layers[i].fLayer;
271 const SkPicture* pict = layers[i].fPicture;
robertphillipse99d4992014-12-03 07:33:57 -0800272 const SkIPoint offset = SkIPoint::Make(layer->bound().fLeft, layer->bound().fTop);
robertphillips98d709b2014-09-02 10:20:50 -0700273
274 // Each non-atlased layer has its own GrTexture
275 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
reed4a8126e2014-09-22 07:29:03 -0700276 layer->texture()->asRenderTarget(), NULL));
robertphillips98d709b2014-09-02 10:20:50 -0700277
278 SkCanvas* layerCanvas = surface->getCanvas();
279
robertphillips9e6835d2014-10-22 05:33:52 -0700280 SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop);
281
robertphillips98d709b2014-09-02 10:20:50 -0700282 // Add a rect clip to make sure the rendering doesn't
robertphillipsfd61ed02014-10-28 07:21:44 -0700283 // extend beyond the boundaries of the layer
robertphillipse99d4992014-12-03 07:33:57 -0800284 const SkRect bound = SkRect::Make(layer->rect());
robertphillipsfd61ed02014-10-28 07:21:44 -0700285 layerCanvas->clipRect(bound);
robertphillips98d709b2014-09-02 10:20:50 -0700286 layerCanvas->clear(SK_ColorTRANSPARENT);
287
robertphillips4815fe52014-09-16 10:32:43 -0700288 SkMatrix initialCTM;
robertphillips9e6835d2014-10-22 05:33:52 -0700289 initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY));
robertphillipsfd61ed02014-10-28 07:21:44 -0700290 initialCTM.preConcat(layers[i].fPreMat);
robertphillips4815fe52014-09-16 10:32:43 -0700291
robertphillipsfd61ed02014-10-28 07:21:44 -0700292 layerCanvas->setMatrix(initialCTM);
293 layerCanvas->concat(layers[i].fLocalMat);
robertphillips98d709b2014-09-02 10:20:50 -0700294
reed6be2aa92014-11-18 11:08:05 -0800295 SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas,
296 pict->drawablePicts(), pict->drawableCount(),
reed8eddfb52014-12-04 07:50:14 -0800297 layer->start()+1, layer->stop(), initialCTM);
robertphillips98d709b2014-09-02 10:20:50 -0700298
299 layerCanvas->flush();
robertphillips7b9e8a42014-12-11 08:20:31 -0800300
301 if (layer->filter()) {
302 SkSurface_Gpu* gpuSurf = static_cast<SkSurface_Gpu*>(surface.get());
303
304 FilterLayer(context, gpuSurf->getDevice(), layer);
305 }
robertphillips98d709b2014-09-02 10:20:50 -0700306 }
307}
308
robertphillipsd61ef012014-10-08 05:17:02 -0700309void GrLayerHoister::UnlockLayers(GrContext* context,
robertphillipsfd61ed02014-10-28 07:21:44 -0700310 const SkTDArray<GrHoistedLayer>& layers) {
robertphillipsd61ef012014-10-08 05:17:02 -0700311 GrLayerCache* layerCache = context->getLayerCache();
robertphillips30d2cc62014-09-24 08:52:18 -0700312
robertphillipsfd61ed02014-10-28 07:21:44 -0700313 for (int i = 0; i < layers.count(); ++i) {
314 layerCache->removeUse(layers[i].fLayer);
robertphillipsb5a97152014-09-30 11:33:02 -0700315 }
316
robertphillips4ab5a902014-10-29 13:56:02 -0700317 SkDEBUGCODE(layerCache->validate();)
318}
319
320void GrLayerHoister::PurgeCache(GrContext* context) {
321#if !GR_CACHE_HOISTED_LAYERS
322 GrLayerCache* layerCache = context->getLayerCache();
323
robertphillips30d2cc62014-09-24 08:52:18 -0700324 // This code completely clears out the atlas. It is required when
325 // caching is disabled so the atlas doesn't fill up and force more
326 // free floating layers
robertphillips98d709b2014-09-02 10:20:50 -0700327 layerCache->purgeAll();
328#endif
robertphillips98d709b2014-09-02 10:20:50 -0700329}