blob: b7653ee295705fd2be324fde08a23dc016caf7ae [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"
robertphillips1c4c5282014-09-18 12:03:15 -070013#include "SkGrPixelRef.h"
robertphillips82365912014-11-12 09:32:34 -080014#include "SkLayerInfo.h"
robertphillips3aac6e02014-10-20 08:52:40 -070015#include "SkRecordDraw.h"
robertphillips98d709b2014-09-02 10:20:50 -070016#include "SkSurface.h"
17
robertphillipscbe80ca2014-10-09 15:36:06 -070018// Create the layer information for the hoisted layer and secure the
19// required texture/render target resources.
20static void prepare_for_hoisting(GrLayerCache* layerCache,
robertphillips232f6b02014-10-09 16:43:42 -070021 const SkPicture* topLevelPicture,
robertphillips30d78412014-11-24 09:49:17 -080022 const SkMatrix& matrix,
robertphillips82365912014-11-12 09:32:34 -080023 const SkLayerInfo::BlockInfo& info,
robertphillips3aac6e02014-10-20 08:52:40 -070024 const SkIRect& layerRect,
robertphillipsfd61ed02014-10-28 07:21:44 -070025 SkTDArray<GrHoistedLayer>* needRendering,
26 SkTDArray<GrHoistedLayer>* recycled,
robertphillipsa63f32e2014-11-10 08:10:42 -080027 bool attemptToAtlas,
28 int numSamples) {
robertphillipscbe80ca2014-10-09 15:36:06 -070029 const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture;
30
robertphillips30d78412014-11-24 09:49:17 -080031 SkMatrix combined = matrix;
32 combined.preConcat(info.fPreMat);
33 combined.preConcat(info.fLocalMat);
robertphillips9e6835d2014-10-22 05:33:52 -070034
robertphillipscbe80ca2014-10-09 15:36:06 -070035 GrCachedLayer* layer = layerCache->findLayerOrCreate(pict->uniqueID(),
36 info.fSaveLayerOpID,
37 info.fRestoreOpID,
robertphillips3aac6e02014-10-20 08:52:40 -070038 layerRect,
robertphillips9e6835d2014-10-22 05:33:52 -070039 combined,
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;
robertphillips3aac6e02014-10-20 08:52:40 -070077 hl->fOffset = SkIPoint::Make(layerRect.fLeft, layerRect.fTop);
robertphillips9e6835d2014-10-22 05:33:52 -070078 hl->fLocalMat = info.fLocalMat;
robertphillips30d78412014-11-24 09:49:17 -080079 hl->fPreMat = matrix;
80 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
robertphillips1c4c5282014-09-18 12:03:15 -0700189static void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* result) {
190 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
191 result->setInfo(info);
192 result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
193}
194
robertphillipsfd61ed02014-10-28 07:21:44 -0700195void GrLayerHoister::ConvertLayersToReplacements(const SkTDArray<GrHoistedLayer>& layers,
196 GrReplacements* replacements) {
robertphillips1c4c5282014-09-18 12:03:15 -0700197 // TODO: just replace GrReplacements::ReplacementInfo with GrCachedLayer?
198 for (int i = 0; i < layers.count(); ++i) {
robertphillipsed420592014-09-29 11:39:38 -0700199 GrCachedLayer* layer = layers[i].fLayer;
robertphillips68cd2aa2014-10-01 09:24:06 -0700200 const SkPicture* picture = layers[i].fPicture;
robertphillipsed420592014-09-29 11:39:38 -0700201
robertphillips9e6835d2014-10-22 05:33:52 -0700202 SkMatrix combined = SkMatrix::Concat(layers[i].fPreMat, layers[i].fLocalMat);
203
robertphillips68cd2aa2014-10-01 09:24:06 -0700204 GrReplacements::ReplacementInfo* layerInfo =
205 replacements->newReplacement(picture->uniqueID(),
206 layer->start(),
robertphillips9e6835d2014-10-22 05:33:52 -0700207 combined);
robertphillipsed420592014-09-29 11:39:38 -0700208 layerInfo->fStop = layer->stop();
209 layerInfo->fPos = layers[i].fOffset;
robertphillips1c4c5282014-09-18 12:03:15 -0700210
211 SkBitmap bm;
robertphillips30d2cc62014-09-24 08:52:18 -0700212 wrap_texture(layers[i].fLayer->texture(),
213 !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().width()
214 : layers[i].fLayer->texture()->width(),
215 !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().height()
216 : layers[i].fLayer->texture()->height(),
robertphillips1c4c5282014-09-18 12:03:15 -0700217 &bm);
218 layerInfo->fImage = SkImage::NewTexture(bm);
219
robertphillips30d2cc62014-09-24 08:52:18 -0700220 layerInfo->fPaint = layers[i].fLayer->paint()
221 ? SkNEW_ARGS(SkPaint, (*layers[i].fLayer->paint()))
222 : NULL;
robertphillips1c4c5282014-09-18 12:03:15 -0700223
robertphillips30d2cc62014-09-24 08:52:18 -0700224 layerInfo->fSrcRect = SkIRect::MakeXYWH(layers[i].fLayer->rect().fLeft,
225 layers[i].fLayer->rect().fTop,
226 layers[i].fLayer->rect().width(),
227 layers[i].fLayer->rect().height());
robertphillips1c4c5282014-09-18 12:03:15 -0700228 }
229}
230
robertphillipsfd61ed02014-10-28 07:21:44 -0700231void GrLayerHoister::DrawLayersToAtlas(GrContext* context,
232 const SkTDArray<GrHoistedLayer>& atlased) {
robertphillips98d709b2014-09-02 10:20:50 -0700233 if (atlased.count() > 0) {
234 // All the atlased layers are rendered into the same GrTexture
235 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
robertphillips30d2cc62014-09-24 08:52:18 -0700236 atlased[0].fLayer->texture()->asRenderTarget(), NULL));
robertphillips98d709b2014-09-02 10:20:50 -0700237
238 SkCanvas* atlasCanvas = surface->getCanvas();
239
robertphillips9e6835d2014-10-22 05:33:52 -0700240 SkPaint clearPaint;
241 clearPaint.setColor(SK_ColorTRANSPARENT);
242 clearPaint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref();
robertphillips98d709b2014-09-02 10:20:50 -0700243
244 for (int i = 0; i < atlased.count(); ++i) {
robertphillips9e6835d2014-10-22 05:33:52 -0700245 const GrCachedLayer* layer = atlased[i].fLayer;
robertphillips30d2cc62014-09-24 08:52:18 -0700246 const SkPicture* pict = atlased[i].fPicture;
robertphillipsed420592014-09-29 11:39:38 -0700247 const SkIPoint offset = atlased[i].fOffset;
robertphillips9e6835d2014-10-22 05:33:52 -0700248 SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();)
249
250 SkASSERT(!layerPaint || !layerPaint->getImageFilter());
robertphillips98d709b2014-09-02 10:20:50 -0700251
252 atlasCanvas->save();
253
254 // Add a rect clip to make sure the rendering doesn't
255 // extend beyond the boundaries of the atlased sub-rect
256 SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft),
257 SkIntToScalar(layer->rect().fTop),
258 SkIntToScalar(layer->rect().width()),
259 SkIntToScalar(layer->rect().height()));
260 atlasCanvas->clipRect(bound);
261
262 // Since 'clear' doesn't respect the clip we need to draw a rect
robertphillips9e6835d2014-10-22 05:33:52 -0700263 atlasCanvas->drawRect(bound, clearPaint);
robertphillips98d709b2014-09-02 10:20:50 -0700264
robertphillipsfd61ed02014-10-28 07:21:44 -0700265 // '-offset' maps the layer's top/left to the origin.
robertphillips98d709b2014-09-02 10:20:50 -0700266 // Since this layer is atlased, the top/left corner needs
267 // to be offset to the correct location in the backing texture.
robertphillips4815fe52014-09-16 10:32:43 -0700268 SkMatrix initialCTM;
robertphillipsfd61ed02014-10-28 07:21:44 -0700269 initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY));
270 initialCTM.preTranslate(bound.fLeft, bound.fTop);
271 initialCTM.preConcat(atlased[i].fPreMat);
robertphillips9e6835d2014-10-22 05:33:52 -0700272
robertphillipsfd61ed02014-10-28 07:21:44 -0700273 atlasCanvas->setMatrix(initialCTM);
robertphillips9e6835d2014-10-22 05:33:52 -0700274 atlasCanvas->concat(atlased[i].fLocalMat);
robertphillips98d709b2014-09-02 10:20:50 -0700275
reed6be2aa92014-11-18 11:08:05 -0800276 SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas,
277 pict->drawablePicts(), pict->drawableCount(),
278 bound, layer->start() + 1, layer->stop(), initialCTM);
robertphillips98d709b2014-09-02 10:20:50 -0700279
280 atlasCanvas->restore();
281 }
282
283 atlasCanvas->flush();
284 }
robertphillipsfd61ed02014-10-28 07:21:44 -0700285}
robertphillips98d709b2014-09-02 10:20:50 -0700286
robertphillipsfd61ed02014-10-28 07:21:44 -0700287void GrLayerHoister::DrawLayers(GrContext* context, const SkTDArray<GrHoistedLayer>& layers) {
288 for (int i = 0; i < layers.count(); ++i) {
289 GrCachedLayer* layer = layers[i].fLayer;
290 const SkPicture* pict = layers[i].fPicture;
291 const SkIPoint& offset = layers[i].fOffset;
robertphillips98d709b2014-09-02 10:20:50 -0700292
293 // Each non-atlased layer has its own GrTexture
294 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
reed4a8126e2014-09-22 07:29:03 -0700295 layer->texture()->asRenderTarget(), NULL));
robertphillips98d709b2014-09-02 10:20:50 -0700296
297 SkCanvas* layerCanvas = surface->getCanvas();
298
robertphillips9e6835d2014-10-22 05:33:52 -0700299 SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop);
300
robertphillips98d709b2014-09-02 10:20:50 -0700301 // Add a rect clip to make sure the rendering doesn't
robertphillipsfd61ed02014-10-28 07:21:44 -0700302 // extend beyond the boundaries of the layer
robertphillips98d709b2014-09-02 10:20:50 -0700303 SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft),
304 SkIntToScalar(layer->rect().fTop),
305 SkIntToScalar(layer->rect().width()),
306 SkIntToScalar(layer->rect().height()));
307
robertphillipsfd61ed02014-10-28 07:21:44 -0700308 layerCanvas->clipRect(bound);
robertphillips98d709b2014-09-02 10:20:50 -0700309
310 layerCanvas->clear(SK_ColorTRANSPARENT);
311
robertphillips4815fe52014-09-16 10:32:43 -0700312 SkMatrix initialCTM;
robertphillips9e6835d2014-10-22 05:33:52 -0700313 initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY));
robertphillipsfd61ed02014-10-28 07:21:44 -0700314 initialCTM.preConcat(layers[i].fPreMat);
robertphillips4815fe52014-09-16 10:32:43 -0700315
robertphillipsfd61ed02014-10-28 07:21:44 -0700316 layerCanvas->setMatrix(initialCTM);
317 layerCanvas->concat(layers[i].fLocalMat);
robertphillips98d709b2014-09-02 10:20:50 -0700318
reed6be2aa92014-11-18 11:08:05 -0800319 SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas,
320 pict->drawablePicts(), pict->drawableCount(),
321 bound, layer->start()+1, layer->stop(), initialCTM);
robertphillips98d709b2014-09-02 10:20:50 -0700322
323 layerCanvas->flush();
324 }
325}
326
robertphillipsd61ef012014-10-08 05:17:02 -0700327void GrLayerHoister::UnlockLayers(GrContext* context,
robertphillipsfd61ed02014-10-28 07:21:44 -0700328 const SkTDArray<GrHoistedLayer>& layers) {
robertphillipsd61ef012014-10-08 05:17:02 -0700329 GrLayerCache* layerCache = context->getLayerCache();
robertphillips30d2cc62014-09-24 08:52:18 -0700330
robertphillipsfd61ed02014-10-28 07:21:44 -0700331 for (int i = 0; i < layers.count(); ++i) {
332 layerCache->removeUse(layers[i].fLayer);
robertphillipsb5a97152014-09-30 11:33:02 -0700333 }
334
robertphillips4ab5a902014-10-29 13:56:02 -0700335 SkDEBUGCODE(layerCache->validate();)
336}
337
338void GrLayerHoister::PurgeCache(GrContext* context) {
339#if !GR_CACHE_HOISTED_LAYERS
340 GrLayerCache* layerCache = context->getLayerCache();
341
robertphillips30d2cc62014-09-24 08:52:18 -0700342 // This code completely clears out the atlas. It is required when
343 // caching is disabled so the atlas doesn't fill up and force more
344 // free floating layers
robertphillips98d709b2014-09-02 10:20:50 -0700345 layerCache->purgeAll();
346#endif
robertphillips98d709b2014-09-02 10:20:50 -0700347}