blob: b53c1b80cdda6be05f85d3e544abeb6572cd51e0 [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,
robertphillips82365912014-11-12 09:32:34 -080022 const SkLayerInfo::BlockInfo& info,
robertphillips3aac6e02014-10-20 08:52:40 -070023 const SkIRect& layerRect,
robertphillipsfd61ed02014-10-28 07:21:44 -070024 SkTDArray<GrHoistedLayer>* needRendering,
25 SkTDArray<GrHoistedLayer>* recycled,
robertphillipsa63f32e2014-11-10 08:10:42 -080026 bool attemptToAtlas,
27 int numSamples) {
robertphillipscbe80ca2014-10-09 15:36:06 -070028 const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture;
29
robertphillips9e6835d2014-10-22 05:33:52 -070030 SkMatrix combined = SkMatrix::Concat(info.fPreMat, info.fLocalMat);
31
robertphillipscbe80ca2014-10-09 15:36:06 -070032 GrCachedLayer* layer = layerCache->findLayerOrCreate(pict->uniqueID(),
33 info.fSaveLayerOpID,
34 info.fRestoreOpID,
robertphillips3aac6e02014-10-20 08:52:40 -070035 layerRect,
robertphillips9e6835d2014-10-22 05:33:52 -070036 combined,
robertphillipscbe80ca2014-10-09 15:36:06 -070037 info.fPaint);
bsalomonf2703d82014-10-28 14:33:06 -070038 GrSurfaceDesc desc;
39 desc.fFlags = kRenderTarget_GrSurfaceFlag;
robertphillips3aac6e02014-10-20 08:52:40 -070040 desc.fWidth = layerRect.width();
41 desc.fHeight = layerRect.height();
robertphillipscbe80ca2014-10-09 15:36:06 -070042 desc.fConfig = kSkia8888_GrPixelConfig;
robertphillipsa63f32e2014-11-10 08:10:42 -080043 desc.fSampleCnt = numSamples;
robertphillipscbe80ca2014-10-09 15:36:06 -070044
robertphillipsfd61ed02014-10-28 07:21:44 -070045 bool locked, needsRendering;
46 if (attemptToAtlas) {
47 locked = layerCache->tryToAtlas(layer, desc, &needsRendering);
48 } else {
49 locked = layerCache->lock(layer, desc, &needsRendering);
50 }
51 if (!locked) {
robertphillipscbe80ca2014-10-09 15:36:06 -070052 // GPU resources could not be secured for the hoisting of this layer
53 return;
54 }
55
robertphillipsfd61ed02014-10-28 07:21:44 -070056 if (attemptToAtlas) {
57 SkASSERT(layer->isAtlased());
58 }
59
robertphillipscbe80ca2014-10-09 15:36:06 -070060 GrHoistedLayer* hl;
61
62 if (needsRendering) {
robertphillipsfd61ed02014-10-28 07:21:44 -070063 if (!attemptToAtlas) {
64 SkASSERT(!layer->isAtlased());
robertphillipscbe80ca2014-10-09 15:36:06 -070065 }
robertphillipsfd61ed02014-10-28 07:21:44 -070066 hl = needRendering->append();
robertphillipscbe80ca2014-10-09 15:36:06 -070067 } else {
68 hl = recycled->append();
69 }
70
robertphillips7bb9ed72014-10-10 11:38:29 -070071 layerCache->addUse(layer);
robertphillipscbe80ca2014-10-09 15:36:06 -070072 hl->fLayer = layer;
73 hl->fPicture = pict;
robertphillips3aac6e02014-10-20 08:52:40 -070074 hl->fOffset = SkIPoint::Make(layerRect.fLeft, layerRect.fTop);
robertphillips9e6835d2014-10-22 05:33:52 -070075 hl->fLocalMat = info.fLocalMat;
76 hl->fPreMat = info.fPreMat;
robertphillipscbe80ca2014-10-09 15:36:06 -070077}
78
robertphillipsfd61ed02014-10-28 07:21:44 -070079// Atlased layers must be small enough to fit in the atlas, not have a
80// paint with an image filter and be neither nested nor nesting.
81// TODO: allow leaf nested layers to appear in the atlas.
82void GrLayerHoister::FindLayersToAtlas(GrContext* context,
robertphillipsd61ef012014-10-08 05:17:02 -070083 const SkPicture* topLevelPicture,
robertphillips98d709b2014-09-02 10:20:50 -070084 const SkRect& query,
robertphillipsd61ef012014-10-08 05:17:02 -070085 SkTDArray<GrHoistedLayer>* atlased,
robertphillipsa63f32e2014-11-10 08:10:42 -080086 SkTDArray<GrHoistedLayer>* recycled,
87 int numSamples) {
88 if (0 != numSamples) {
89 // MSAA layers are currently never atlased
90 return;
91 }
92
robertphillipsd61ef012014-10-08 05:17:02 -070093 GrLayerCache* layerCache = context->getLayerCache();
94
95 layerCache->processDeletedPictures();
96
robertphillips82365912014-11-12 09:32:34 -080097 SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
robertphillips30d2cc62014-09-24 08:52:18 -070098
99 const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key);
robertphillipscbe80ca2014-10-09 15:36:06 -0700100 if (!topLevelData) {
robertphillipsfd61ed02014-10-28 07:21:44 -0700101 return;
robertphillips30d2cc62014-09-24 08:52:18 -0700102 }
103
robertphillips82365912014-11-12 09:32:34 -0800104 const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData);
105 if (0 == topLevelGPUData->numBlocks()) {
robertphillipsfd61ed02014-10-28 07:21:44 -0700106 return;
robertphillips30d2cc62014-09-24 08:52:18 -0700107 }
108
robertphillips82365912014-11-12 09:32:34 -0800109 atlased->setReserve(atlased->count() + topLevelGPUData->numBlocks());
robertphillipscbe80ca2014-10-09 15:36:06 -0700110
robertphillips82365912014-11-12 09:32:34 -0800111 for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) {
112 const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i);
robertphillips98d709b2014-09-02 10:20:50 -0700113
robertphillipsfd61ed02014-10-28 07:21:44 -0700114 // TODO: ignore perspective projected layers here?
115 bool disallowAtlasing = info.fHasNestedLayers || info.fIsNested ||
116 (info.fPaint && info.fPaint->getImageFilter());
117
118 if (disallowAtlasing) {
119 continue;
120 }
121
robertphillipsd8aa7b72014-10-30 16:45:02 -0700122 SkRect layerRect = info.fBounds;
robertphillips3aac6e02014-10-20 08:52:40 -0700123 if (!layerRect.intersect(query)) {
robertphillips2ed8a752014-09-03 13:46:02 -0700124 continue;
robertphillips98d709b2014-09-02 10:20:50 -0700125 }
robertphillips98d709b2014-09-02 10:20:50 -0700126
robertphillips3aac6e02014-10-20 08:52:40 -0700127 SkIRect ir;
128 layerRect.roundOut(&ir);
129
robertphillipsfd61ed02014-10-28 07:21:44 -0700130 if (!GrLayerCache::PlausiblyAtlasable(ir.width(), ir.height())) {
robertphillips2ed8a752014-09-03 13:46:02 -0700131 continue;
robertphillips98d709b2014-09-02 10:20:50 -0700132 }
robertphillips2ed8a752014-09-03 13:46:02 -0700133
robertphillipsa63f32e2014-11-10 08:10:42 -0800134 prepare_for_hoisting(layerCache, topLevelPicture, info, ir, atlased, recycled, true, 0);
robertphillips98d709b2014-09-02 10:20:50 -0700135 }
136
robertphillipsfd61ed02014-10-28 07:21:44 -0700137}
138
139void GrLayerHoister::FindLayersToHoist(GrContext* context,
140 const SkPicture* topLevelPicture,
141 const SkRect& query,
142 SkTDArray<GrHoistedLayer>* needRendering,
robertphillipsa63f32e2014-11-10 08:10:42 -0800143 SkTDArray<GrHoistedLayer>* recycled,
144 int numSamples) {
robertphillipsfd61ed02014-10-28 07:21:44 -0700145 GrLayerCache* layerCache = context->getLayerCache();
146
147 layerCache->processDeletedPictures();
148
robertphillips82365912014-11-12 09:32:34 -0800149 SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
robertphillipsfd61ed02014-10-28 07:21:44 -0700150
151 const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key);
152 if (!topLevelData) {
153 return;
154 }
155
robertphillips82365912014-11-12 09:32:34 -0800156 const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData);
157 if (0 == topLevelGPUData->numBlocks()) {
robertphillipsfd61ed02014-10-28 07:21:44 -0700158 return;
159 }
160
161 // Find and prepare for hoisting all the layers that intersect the query rect
robertphillips82365912014-11-12 09:32:34 -0800162 for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) {
163 const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i);
robertphillipsfd61ed02014-10-28 07:21:44 -0700164 if (info.fIsNested) {
165 // Parent layers are currently hoisted while nested layers are not.
166 continue;
167 }
168
robertphillipsd8aa7b72014-10-30 16:45:02 -0700169 SkRect layerRect = info.fBounds;
robertphillipsfd61ed02014-10-28 07:21:44 -0700170 if (!layerRect.intersect(query)) {
171 continue;
172 }
173
174 SkIRect ir;
175 layerRect.roundOut(&ir);
176
177 prepare_for_hoisting(layerCache, topLevelPicture, info, ir,
robertphillipsa63f32e2014-11-10 08:10:42 -0800178 needRendering, recycled, false, numSamples);
robertphillipsfd61ed02014-10-28 07:21:44 -0700179 }
robertphillips98d709b2014-09-02 10:20:50 -0700180}
181
robertphillips1c4c5282014-09-18 12:03:15 -0700182static void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* result) {
183 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
184 result->setInfo(info);
185 result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
186}
187
robertphillipsfd61ed02014-10-28 07:21:44 -0700188void GrLayerHoister::ConvertLayersToReplacements(const SkTDArray<GrHoistedLayer>& layers,
189 GrReplacements* replacements) {
robertphillips1c4c5282014-09-18 12:03:15 -0700190 // TODO: just replace GrReplacements::ReplacementInfo with GrCachedLayer?
191 for (int i = 0; i < layers.count(); ++i) {
robertphillipsed420592014-09-29 11:39:38 -0700192 GrCachedLayer* layer = layers[i].fLayer;
robertphillips68cd2aa2014-10-01 09:24:06 -0700193 const SkPicture* picture = layers[i].fPicture;
robertphillipsed420592014-09-29 11:39:38 -0700194
robertphillips9e6835d2014-10-22 05:33:52 -0700195 SkMatrix combined = SkMatrix::Concat(layers[i].fPreMat, layers[i].fLocalMat);
196
robertphillips68cd2aa2014-10-01 09:24:06 -0700197 GrReplacements::ReplacementInfo* layerInfo =
198 replacements->newReplacement(picture->uniqueID(),
199 layer->start(),
robertphillips9e6835d2014-10-22 05:33:52 -0700200 combined);
robertphillipsed420592014-09-29 11:39:38 -0700201 layerInfo->fStop = layer->stop();
202 layerInfo->fPos = layers[i].fOffset;
robertphillips1c4c5282014-09-18 12:03:15 -0700203
204 SkBitmap bm;
robertphillips30d2cc62014-09-24 08:52:18 -0700205 wrap_texture(layers[i].fLayer->texture(),
206 !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().width()
207 : layers[i].fLayer->texture()->width(),
208 !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().height()
209 : layers[i].fLayer->texture()->height(),
robertphillips1c4c5282014-09-18 12:03:15 -0700210 &bm);
211 layerInfo->fImage = SkImage::NewTexture(bm);
212
robertphillips30d2cc62014-09-24 08:52:18 -0700213 layerInfo->fPaint = layers[i].fLayer->paint()
214 ? SkNEW_ARGS(SkPaint, (*layers[i].fLayer->paint()))
215 : NULL;
robertphillips1c4c5282014-09-18 12:03:15 -0700216
robertphillips30d2cc62014-09-24 08:52:18 -0700217 layerInfo->fSrcRect = SkIRect::MakeXYWH(layers[i].fLayer->rect().fLeft,
218 layers[i].fLayer->rect().fTop,
219 layers[i].fLayer->rect().width(),
220 layers[i].fLayer->rect().height());
robertphillips1c4c5282014-09-18 12:03:15 -0700221 }
222}
223
robertphillipsfd61ed02014-10-28 07:21:44 -0700224void GrLayerHoister::DrawLayersToAtlas(GrContext* context,
225 const SkTDArray<GrHoistedLayer>& atlased) {
robertphillips98d709b2014-09-02 10:20:50 -0700226 if (atlased.count() > 0) {
227 // All the atlased layers are rendered into the same GrTexture
228 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
robertphillips30d2cc62014-09-24 08:52:18 -0700229 atlased[0].fLayer->texture()->asRenderTarget(), NULL));
robertphillips98d709b2014-09-02 10:20:50 -0700230
231 SkCanvas* atlasCanvas = surface->getCanvas();
232
robertphillips9e6835d2014-10-22 05:33:52 -0700233 SkPaint clearPaint;
234 clearPaint.setColor(SK_ColorTRANSPARENT);
235 clearPaint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref();
robertphillips98d709b2014-09-02 10:20:50 -0700236
237 for (int i = 0; i < atlased.count(); ++i) {
robertphillips9e6835d2014-10-22 05:33:52 -0700238 const GrCachedLayer* layer = atlased[i].fLayer;
robertphillips30d2cc62014-09-24 08:52:18 -0700239 const SkPicture* pict = atlased[i].fPicture;
robertphillipsed420592014-09-29 11:39:38 -0700240 const SkIPoint offset = atlased[i].fOffset;
robertphillips9e6835d2014-10-22 05:33:52 -0700241 SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();)
242
243 SkASSERT(!layerPaint || !layerPaint->getImageFilter());
robertphillips98d709b2014-09-02 10:20:50 -0700244
245 atlasCanvas->save();
246
247 // Add a rect clip to make sure the rendering doesn't
248 // extend beyond the boundaries of the atlased sub-rect
249 SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft),
250 SkIntToScalar(layer->rect().fTop),
251 SkIntToScalar(layer->rect().width()),
252 SkIntToScalar(layer->rect().height()));
253 atlasCanvas->clipRect(bound);
254
255 // Since 'clear' doesn't respect the clip we need to draw a rect
robertphillips9e6835d2014-10-22 05:33:52 -0700256 atlasCanvas->drawRect(bound, clearPaint);
robertphillips98d709b2014-09-02 10:20:50 -0700257
robertphillipsfd61ed02014-10-28 07:21:44 -0700258 // '-offset' maps the layer's top/left to the origin.
robertphillips98d709b2014-09-02 10:20:50 -0700259 // Since this layer is atlased, the top/left corner needs
260 // to be offset to the correct location in the backing texture.
robertphillips4815fe52014-09-16 10:32:43 -0700261 SkMatrix initialCTM;
robertphillipsfd61ed02014-10-28 07:21:44 -0700262 initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY));
263 initialCTM.preTranslate(bound.fLeft, bound.fTop);
264 initialCTM.preConcat(atlased[i].fPreMat);
robertphillips9e6835d2014-10-22 05:33:52 -0700265
robertphillipsfd61ed02014-10-28 07:21:44 -0700266 atlasCanvas->setMatrix(initialCTM);
robertphillips9e6835d2014-10-22 05:33:52 -0700267 atlasCanvas->concat(atlased[i].fLocalMat);
robertphillips98d709b2014-09-02 10:20:50 -0700268
reed6be2aa92014-11-18 11:08:05 -0800269 SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas,
270 pict->drawablePicts(), pict->drawableCount(),
271 bound, layer->start() + 1, layer->stop(), initialCTM);
robertphillips98d709b2014-09-02 10:20:50 -0700272
273 atlasCanvas->restore();
274 }
275
276 atlasCanvas->flush();
277 }
robertphillipsfd61ed02014-10-28 07:21:44 -0700278}
robertphillips98d709b2014-09-02 10:20:50 -0700279
robertphillipsfd61ed02014-10-28 07:21:44 -0700280void GrLayerHoister::DrawLayers(GrContext* context, const SkTDArray<GrHoistedLayer>& layers) {
281 for (int i = 0; i < layers.count(); ++i) {
282 GrCachedLayer* layer = layers[i].fLayer;
283 const SkPicture* pict = layers[i].fPicture;
284 const SkIPoint& offset = layers[i].fOffset;
robertphillips98d709b2014-09-02 10:20:50 -0700285
286 // Each non-atlased layer has its own GrTexture
287 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
reed4a8126e2014-09-22 07:29:03 -0700288 layer->texture()->asRenderTarget(), NULL));
robertphillips98d709b2014-09-02 10:20:50 -0700289
290 SkCanvas* layerCanvas = surface->getCanvas();
291
robertphillips9e6835d2014-10-22 05:33:52 -0700292 SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop);
293
robertphillips98d709b2014-09-02 10:20:50 -0700294 // Add a rect clip to make sure the rendering doesn't
robertphillipsfd61ed02014-10-28 07:21:44 -0700295 // extend beyond the boundaries of the layer
robertphillips98d709b2014-09-02 10:20:50 -0700296 SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft),
297 SkIntToScalar(layer->rect().fTop),
298 SkIntToScalar(layer->rect().width()),
299 SkIntToScalar(layer->rect().height()));
300
robertphillipsfd61ed02014-10-28 07:21:44 -0700301 layerCanvas->clipRect(bound);
robertphillips98d709b2014-09-02 10:20:50 -0700302
303 layerCanvas->clear(SK_ColorTRANSPARENT);
304
robertphillips4815fe52014-09-16 10:32:43 -0700305 SkMatrix initialCTM;
robertphillips9e6835d2014-10-22 05:33:52 -0700306 initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY));
robertphillipsfd61ed02014-10-28 07:21:44 -0700307 initialCTM.preConcat(layers[i].fPreMat);
robertphillips4815fe52014-09-16 10:32:43 -0700308
robertphillipsfd61ed02014-10-28 07:21:44 -0700309 layerCanvas->setMatrix(initialCTM);
310 layerCanvas->concat(layers[i].fLocalMat);
robertphillips98d709b2014-09-02 10:20:50 -0700311
reed6be2aa92014-11-18 11:08:05 -0800312 SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas,
313 pict->drawablePicts(), pict->drawableCount(),
314 bound, layer->start()+1, layer->stop(), initialCTM);
robertphillips98d709b2014-09-02 10:20:50 -0700315
316 layerCanvas->flush();
317 }
318}
319
robertphillipsd61ef012014-10-08 05:17:02 -0700320void GrLayerHoister::UnlockLayers(GrContext* context,
robertphillipsfd61ed02014-10-28 07:21:44 -0700321 const SkTDArray<GrHoistedLayer>& layers) {
robertphillipsd61ef012014-10-08 05:17:02 -0700322 GrLayerCache* layerCache = context->getLayerCache();
robertphillips30d2cc62014-09-24 08:52:18 -0700323
robertphillipsfd61ed02014-10-28 07:21:44 -0700324 for (int i = 0; i < layers.count(); ++i) {
325 layerCache->removeUse(layers[i].fLayer);
robertphillipsb5a97152014-09-30 11:33:02 -0700326 }
327
robertphillips4ab5a902014-10-29 13:56:02 -0700328 SkDEBUGCODE(layerCache->validate();)
329}
330
331void GrLayerHoister::PurgeCache(GrContext* context) {
332#if !GR_CACHE_HOISTED_LAYERS
333 GrLayerCache* layerCache = context->getLayerCache();
334
robertphillips30d2cc62014-09-24 08:52:18 -0700335 // This code completely clears out the atlas. It is required when
336 // caching is disabled so the atlas doesn't fill up and force more
337 // free floating layers
robertphillips98d709b2014-09-02 10:20:50 -0700338 layerCache->purgeAll();
339#endif
robertphillips98d709b2014-09-02 10:20:50 -0700340}