blob: 4e7836830ca784d723a3ce2a9d63c298614baa58 [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,
robertphillips01d6e5f2014-12-01 09:09:27 -080022 const SkMatrix& initialMat,
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
robertphillips01d6e5f2014-12-01 09:09:27 -080031 GrCachedLayer* layer = layerCache->findLayerOrCreate(topLevelPicture->uniqueID(),
robertphillipscbe80ca2014-10-09 15:36:06 -070032 info.fSaveLayerOpID,
33 info.fRestoreOpID,
robertphillips3aac6e02014-10-20 08:52:40 -070034 layerRect,
robertphillips01d6e5f2014-12-01 09:09:27 -080035 initialMat,
36 info.fKey,
37 info.fKeySize,
robertphillipscbe80ca2014-10-09 15:36:06 -070038 info.fPaint);
bsalomonf2703d82014-10-28 14:33:06 -070039 GrSurfaceDesc desc;
40 desc.fFlags = kRenderTarget_GrSurfaceFlag;
robertphillips3aac6e02014-10-20 08:52:40 -070041 desc.fWidth = layerRect.width();
42 desc.fHeight = layerRect.height();
robertphillipscbe80ca2014-10-09 15:36:06 -070043 desc.fConfig = kSkia8888_GrPixelConfig;
robertphillipsa63f32e2014-11-10 08:10:42 -080044 desc.fSampleCnt = numSamples;
robertphillipscbe80ca2014-10-09 15:36:06 -070045
robertphillipsfd61ed02014-10-28 07:21:44 -070046 bool locked, needsRendering;
47 if (attemptToAtlas) {
48 locked = layerCache->tryToAtlas(layer, desc, &needsRendering);
49 } else {
50 locked = layerCache->lock(layer, desc, &needsRendering);
51 }
52 if (!locked) {
robertphillipscbe80ca2014-10-09 15:36:06 -070053 // GPU resources could not be secured for the hoisting of this layer
54 return;
55 }
56
robertphillipsfd61ed02014-10-28 07:21:44 -070057 if (attemptToAtlas) {
58 SkASSERT(layer->isAtlased());
59 }
60
robertphillipscbe80ca2014-10-09 15:36:06 -070061 GrHoistedLayer* hl;
62
63 if (needsRendering) {
robertphillipsfd61ed02014-10-28 07:21:44 -070064 if (!attemptToAtlas) {
65 SkASSERT(!layer->isAtlased());
robertphillipscbe80ca2014-10-09 15:36:06 -070066 }
robertphillipsfd61ed02014-10-28 07:21:44 -070067 hl = needRendering->append();
robertphillipscbe80ca2014-10-09 15:36:06 -070068 } else {
69 hl = recycled->append();
70 }
71
robertphillips7bb9ed72014-10-10 11:38:29 -070072 layerCache->addUse(layer);
robertphillipscbe80ca2014-10-09 15:36:06 -070073 hl->fLayer = layer;
74 hl->fPicture = pict;
robertphillips3aac6e02014-10-20 08:52:40 -070075 hl->fOffset = SkIPoint::Make(layerRect.fLeft, layerRect.fTop);
robertphillips9e6835d2014-10-22 05:33:52 -070076 hl->fLocalMat = info.fLocalMat;
robertphillips01d6e5f2014-12-01 09:09:27 -080077 hl->fInitialMat = initialMat;
78 hl->fPreMat = initialMat;
robertphillips30d78412014-11-24 09:49:17 -080079 hl->fPreMat.preConcat(info.fPreMat);
robertphillipscbe80ca2014-10-09 15:36:06 -070080}
81
robertphillipsfd61ed02014-10-28 07:21:44 -070082// Atlased layers must be small enough to fit in the atlas, not have a
83// paint with an image filter and be neither nested nor nesting.
84// TODO: allow leaf nested layers to appear in the atlas.
85void GrLayerHoister::FindLayersToAtlas(GrContext* context,
robertphillipsd61ef012014-10-08 05:17:02 -070086 const SkPicture* topLevelPicture,
robertphillips30d78412014-11-24 09:49:17 -080087 const SkMatrix& initialMat,
robertphillips98d709b2014-09-02 10:20:50 -070088 const SkRect& query,
robertphillipsd61ef012014-10-08 05:17:02 -070089 SkTDArray<GrHoistedLayer>* atlased,
robertphillipsa63f32e2014-11-10 08:10:42 -080090 SkTDArray<GrHoistedLayer>* recycled,
91 int numSamples) {
92 if (0 != numSamples) {
93 // MSAA layers are currently never atlased
94 return;
95 }
96
robertphillipsd61ef012014-10-08 05:17:02 -070097 GrLayerCache* layerCache = context->getLayerCache();
98
99 layerCache->processDeletedPictures();
100
robertphillips82365912014-11-12 09:32:34 -0800101 SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
robertphillips30d2cc62014-09-24 08:52:18 -0700102
103 const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key);
robertphillipscbe80ca2014-10-09 15:36:06 -0700104 if (!topLevelData) {
robertphillipsfd61ed02014-10-28 07:21:44 -0700105 return;
robertphillips30d2cc62014-09-24 08:52:18 -0700106 }
107
robertphillips82365912014-11-12 09:32:34 -0800108 const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData);
109 if (0 == topLevelGPUData->numBlocks()) {
robertphillipsfd61ed02014-10-28 07:21:44 -0700110 return;
robertphillips30d2cc62014-09-24 08:52:18 -0700111 }
112
robertphillips82365912014-11-12 09:32:34 -0800113 atlased->setReserve(atlased->count() + topLevelGPUData->numBlocks());
robertphillipscbe80ca2014-10-09 15:36:06 -0700114
robertphillips82365912014-11-12 09:32:34 -0800115 for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) {
116 const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i);
robertphillips98d709b2014-09-02 10:20:50 -0700117
robertphillipsfd61ed02014-10-28 07:21:44 -0700118 // TODO: ignore perspective projected layers here?
119 bool disallowAtlasing = info.fHasNestedLayers || info.fIsNested ||
120 (info.fPaint && info.fPaint->getImageFilter());
121
122 if (disallowAtlasing) {
123 continue;
124 }
125
robertphillips30d78412014-11-24 09:49:17 -0800126 SkRect layerRect;
127 initialMat.mapRect(&layerRect, info.fBounds);
robertphillips3aac6e02014-10-20 08:52:40 -0700128 if (!layerRect.intersect(query)) {
robertphillips2ed8a752014-09-03 13:46:02 -0700129 continue;
robertphillips98d709b2014-09-02 10:20:50 -0700130 }
robertphillips98d709b2014-09-02 10:20:50 -0700131
robertphillips30d78412014-11-24 09:49:17 -0800132 const SkIRect ir = layerRect.roundOut();
robertphillips3aac6e02014-10-20 08:52:40 -0700133
robertphillipsfd61ed02014-10-28 07:21:44 -0700134 if (!GrLayerCache::PlausiblyAtlasable(ir.width(), ir.height())) {
robertphillips2ed8a752014-09-03 13:46:02 -0700135 continue;
robertphillips98d709b2014-09-02 10:20:50 -0700136 }
robertphillips2ed8a752014-09-03 13:46:02 -0700137
robertphillips30d78412014-11-24 09:49:17 -0800138 prepare_for_hoisting(layerCache, topLevelPicture, initialMat,
139 info, ir, atlased, recycled, true, 0);
robertphillips98d709b2014-09-02 10:20:50 -0700140 }
141
robertphillipsfd61ed02014-10-28 07:21:44 -0700142}
143
144void GrLayerHoister::FindLayersToHoist(GrContext* context,
145 const SkPicture* topLevelPicture,
robertphillips30d78412014-11-24 09:49:17 -0800146 const SkMatrix& initialMat,
robertphillipsfd61ed02014-10-28 07:21:44 -0700147 const SkRect& query,
148 SkTDArray<GrHoistedLayer>* needRendering,
robertphillipsa63f32e2014-11-10 08:10:42 -0800149 SkTDArray<GrHoistedLayer>* recycled,
150 int numSamples) {
robertphillipsfd61ed02014-10-28 07:21:44 -0700151 GrLayerCache* layerCache = context->getLayerCache();
152
153 layerCache->processDeletedPictures();
154
robertphillips82365912014-11-12 09:32:34 -0800155 SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
robertphillipsfd61ed02014-10-28 07:21:44 -0700156
157 const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key);
158 if (!topLevelData) {
159 return;
160 }
161
robertphillips82365912014-11-12 09:32:34 -0800162 const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData);
163 if (0 == topLevelGPUData->numBlocks()) {
robertphillipsfd61ed02014-10-28 07:21:44 -0700164 return;
165 }
166
167 // Find and prepare for hoisting all the layers that intersect the query rect
robertphillips82365912014-11-12 09:32:34 -0800168 for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) {
169 const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i);
robertphillipsfd61ed02014-10-28 07:21:44 -0700170 if (info.fIsNested) {
171 // Parent layers are currently hoisted while nested layers are not.
172 continue;
173 }
174
robertphillips30d78412014-11-24 09:49:17 -0800175 SkRect layerRect;
176 initialMat.mapRect(&layerRect, info.fBounds);
robertphillipsfd61ed02014-10-28 07:21:44 -0700177 if (!layerRect.intersect(query)) {
178 continue;
179 }
180
robertphillips30d78412014-11-24 09:49:17 -0800181 const SkIRect ir = layerRect.roundOut();
robertphillipsfd61ed02014-10-28 07:21:44 -0700182
robertphillips30d78412014-11-24 09:49:17 -0800183 prepare_for_hoisting(layerCache, topLevelPicture, initialMat, info, ir,
robertphillipsa63f32e2014-11-10 08:10:42 -0800184 needRendering, recycled, false, numSamples);
robertphillipsfd61ed02014-10-28 07:21:44 -0700185 }
robertphillips98d709b2014-09-02 10:20:50 -0700186}
187
robertphillips1c4c5282014-09-18 12:03:15 -0700188static void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* result) {
189 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
190 result->setInfo(info);
191 result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
192}
193
robertphillips01d6e5f2014-12-01 09:09:27 -0800194void GrLayerHoister::ConvertLayersToReplacements(const SkPicture* topLevelPicture,
195 const SkTDArray<GrHoistedLayer>& layers,
robertphillipsfd61ed02014-10-28 07:21:44 -0700196 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;
robertphillips9e6835d2014-10-22 05:33:52 -0700200
robertphillips68cd2aa2014-10-01 09:24:06 -0700201 GrReplacements::ReplacementInfo* layerInfo =
robertphillips01d6e5f2014-12-01 09:09:27 -0800202 replacements->newReplacement(topLevelPicture->uniqueID(),
203 layers[i].fInitialMat,
204 layer->key(), layer->keySize());
robertphillipsed420592014-09-29 11:39:38 -0700205 layerInfo->fStop = layer->stop();
206 layerInfo->fPos = layers[i].fOffset;
robertphillips1c4c5282014-09-18 12:03:15 -0700207
208 SkBitmap bm;
robertphillips30d2cc62014-09-24 08:52:18 -0700209 wrap_texture(layers[i].fLayer->texture(),
210 !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().width()
211 : layers[i].fLayer->texture()->width(),
212 !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().height()
213 : layers[i].fLayer->texture()->height(),
robertphillips1c4c5282014-09-18 12:03:15 -0700214 &bm);
215 layerInfo->fImage = SkImage::NewTexture(bm);
216
robertphillips30d2cc62014-09-24 08:52:18 -0700217 layerInfo->fPaint = layers[i].fLayer->paint()
218 ? SkNEW_ARGS(SkPaint, (*layers[i].fLayer->paint()))
219 : NULL;
robertphillips1c4c5282014-09-18 12:03:15 -0700220
robertphillips30d2cc62014-09-24 08:52:18 -0700221 layerInfo->fSrcRect = SkIRect::MakeXYWH(layers[i].fLayer->rect().fLeft,
222 layers[i].fLayer->rect().fTop,
223 layers[i].fLayer->rect().width(),
224 layers[i].fLayer->rect().height());
robertphillips1c4c5282014-09-18 12:03:15 -0700225 }
226}
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
232 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
robertphillips30d2cc62014-09-24 08:52:18 -0700233 atlased[0].fLayer->texture()->asRenderTarget(), NULL));
robertphillips98d709b2014-09-02 10:20:50 -0700234
235 SkCanvas* atlasCanvas = surface->getCanvas();
236
reedaf641a12014-12-02 19:40:18 -0800237 SkPaint clearPaint;
238 clearPaint.setColor(SK_ColorTRANSPARENT);
239 clearPaint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref();
240
robertphillips98d709b2014-09-02 10:20:50 -0700241 for (int i = 0; i < atlased.count(); ++i) {
robertphillips9e6835d2014-10-22 05:33:52 -0700242 const GrCachedLayer* layer = atlased[i].fLayer;
robertphillips30d2cc62014-09-24 08:52:18 -0700243 const SkPicture* pict = atlased[i].fPicture;
robertphillipsed420592014-09-29 11:39:38 -0700244 const SkIPoint offset = atlased[i].fOffset;
robertphillips9e6835d2014-10-22 05:33:52 -0700245 SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();)
246
247 SkASSERT(!layerPaint || !layerPaint->getImageFilter());
robertphillips98d709b2014-09-02 10:20:50 -0700248
249 atlasCanvas->save();
250
251 // Add a rect clip to make sure the rendering doesn't
252 // extend beyond the boundaries of the atlased sub-rect
253 SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft),
254 SkIntToScalar(layer->rect().fTop),
255 SkIntToScalar(layer->rect().width()),
256 SkIntToScalar(layer->rect().height()));
257 atlasCanvas->clipRect(bound);
reedaf641a12014-12-02 19:40:18 -0800258
259 // Since 'clear' doesn't respect the clip we need to draw a rect
260 atlasCanvas->drawRect(bound, clearPaint);
robertphillips98d709b2014-09-02 10:20:50 -0700261
robertphillipsfd61ed02014-10-28 07:21:44 -0700262 // '-offset' maps the layer's top/left to the origin.
robertphillips98d709b2014-09-02 10:20:50 -0700263 // Since this layer is atlased, the top/left corner needs
264 // to be offset to the correct location in the backing texture.
robertphillips4815fe52014-09-16 10:32:43 -0700265 SkMatrix initialCTM;
robertphillipsfd61ed02014-10-28 07:21:44 -0700266 initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY));
267 initialCTM.preTranslate(bound.fLeft, bound.fTop);
268 initialCTM.preConcat(atlased[i].fPreMat);
robertphillips9e6835d2014-10-22 05:33:52 -0700269
robertphillipsfd61ed02014-10-28 07:21:44 -0700270 atlasCanvas->setMatrix(initialCTM);
robertphillips9e6835d2014-10-22 05:33:52 -0700271 atlasCanvas->concat(atlased[i].fLocalMat);
robertphillips98d709b2014-09-02 10:20:50 -0700272
reed6be2aa92014-11-18 11:08:05 -0800273 SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas,
274 pict->drawablePicts(), pict->drawableCount(),
reedaf641a12014-12-02 19:40:18 -0800275 bound, layer->start() + 1, layer->stop(), initialCTM);
robertphillips98d709b2014-09-02 10:20:50 -0700276
277 atlasCanvas->restore();
278 }
279
280 atlasCanvas->flush();
281 }
robertphillipsfd61ed02014-10-28 07:21:44 -0700282}
robertphillips98d709b2014-09-02 10:20:50 -0700283
robertphillipsfd61ed02014-10-28 07:21:44 -0700284void GrLayerHoister::DrawLayers(GrContext* context, const SkTDArray<GrHoistedLayer>& layers) {
285 for (int i = 0; i < layers.count(); ++i) {
286 GrCachedLayer* layer = layers[i].fLayer;
287 const SkPicture* pict = layers[i].fPicture;
288 const SkIPoint& offset = layers[i].fOffset;
robertphillips98d709b2014-09-02 10:20:50 -0700289
290 // Each non-atlased layer has its own GrTexture
291 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
reed4a8126e2014-09-22 07:29:03 -0700292 layer->texture()->asRenderTarget(), NULL));
robertphillips98d709b2014-09-02 10:20:50 -0700293
294 SkCanvas* layerCanvas = surface->getCanvas();
295
robertphillips9e6835d2014-10-22 05:33:52 -0700296 SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop);
297
robertphillips98d709b2014-09-02 10:20:50 -0700298 // Add a rect clip to make sure the rendering doesn't
robertphillipsfd61ed02014-10-28 07:21:44 -0700299 // extend beyond the boundaries of the layer
robertphillips98d709b2014-09-02 10:20:50 -0700300 SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft),
301 SkIntToScalar(layer->rect().fTop),
302 SkIntToScalar(layer->rect().width()),
303 SkIntToScalar(layer->rect().height()));
304
robertphillipsfd61ed02014-10-28 07:21:44 -0700305 layerCanvas->clipRect(bound);
reedaf641a12014-12-02 19:40:18 -0800306
robertphillips98d709b2014-09-02 10:20:50 -0700307 layerCanvas->clear(SK_ColorTRANSPARENT);
308
robertphillips4815fe52014-09-16 10:32:43 -0700309 SkMatrix initialCTM;
robertphillips9e6835d2014-10-22 05:33:52 -0700310 initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY));
robertphillipsfd61ed02014-10-28 07:21:44 -0700311 initialCTM.preConcat(layers[i].fPreMat);
robertphillips4815fe52014-09-16 10:32:43 -0700312
robertphillipsfd61ed02014-10-28 07:21:44 -0700313 layerCanvas->setMatrix(initialCTM);
314 layerCanvas->concat(layers[i].fLocalMat);
robertphillips98d709b2014-09-02 10:20:50 -0700315
reed6be2aa92014-11-18 11:08:05 -0800316 SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas,
317 pict->drawablePicts(), pict->drawableCount(),
reedaf641a12014-12-02 19:40:18 -0800318 bound, layer->start()+1, layer->stop(), initialCTM);
robertphillips98d709b2014-09-02 10:20:50 -0700319
320 layerCanvas->flush();
321 }
322}
323
robertphillipsd61ef012014-10-08 05:17:02 -0700324void GrLayerHoister::UnlockLayers(GrContext* context,
robertphillipsfd61ed02014-10-28 07:21:44 -0700325 const SkTDArray<GrHoistedLayer>& layers) {
robertphillipsd61ef012014-10-08 05:17:02 -0700326 GrLayerCache* layerCache = context->getLayerCache();
robertphillips30d2cc62014-09-24 08:52:18 -0700327
robertphillipsfd61ed02014-10-28 07:21:44 -0700328 for (int i = 0; i < layers.count(); ++i) {
329 layerCache->removeUse(layers[i].fLayer);
robertphillipsb5a97152014-09-30 11:33:02 -0700330 }
331
robertphillips4ab5a902014-10-29 13:56:02 -0700332 SkDEBUGCODE(layerCache->validate();)
333}
334
335void GrLayerHoister::PurgeCache(GrContext* context) {
336#if !GR_CACHE_HOISTED_LAYERS
337 GrLayerCache* layerCache = context->getLayerCache();
338
robertphillips30d2cc62014-09-24 08:52:18 -0700339 // This code completely clears out the atlas. It is required when
340 // caching is disabled so the atlas doesn't fill up and force more
341 // free floating layers
robertphillips98d709b2014-09-02 10:20:50 -0700342 layerCache->purgeAll();
343#endif
robertphillips98d709b2014-09-02 10:20:50 -0700344}