OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrLayerCache.h" | 8 #include "GrLayerCache.h" |
9 #include "GrLayerHoister.h" | 9 #include "GrLayerHoister.h" |
10 #include "GrRecordReplaceDraw.h" | 10 #include "GrRecordReplaceDraw.h" |
11 | 11 |
12 #include "SkCanvas.h" | 12 #include "SkCanvas.h" |
13 #include "SkGrPixelRef.h" | 13 #include "SkGrPixelRef.h" |
14 #include "SkRecordDraw.h" | 14 #include "SkRecordDraw.h" |
15 #include "SkSurface.h" | 15 #include "SkSurface.h" |
16 | 16 |
17 // Create the layer information for the hoisted layer and secure the | 17 // Create the layer information for the hoisted layer and secure the |
18 // required texture/render target resources. | 18 // required texture/render target resources. |
19 static void prepare_for_hoisting(GrLayerCache* layerCache, | 19 static void prepare_for_hoisting(GrLayerCache* layerCache, |
20 const SkPicture* topLevelPicture, | 20 const SkPicture* topLevelPicture, |
21 const GrAccelData::SaveLayerInfo& info, | 21 const GrAccelData::SaveLayerInfo& info, |
22 const SkIRect& layerRect, | 22 const SkIRect& layerRect, |
23 SkTDArray<GrHoistedLayer>* atlased, | 23 SkTDArray<GrHoistedLayer>* atlased, |
24 SkTDArray<GrHoistedLayer>* nonAtlased, | 24 SkTDArray<GrHoistedLayer>* nonAtlased, |
25 SkTDArray<GrHoistedLayer>* recycled) { | 25 SkTDArray<GrHoistedLayer>* recycled) { |
26 const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture; | 26 const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture; |
27 | 27 |
| 28 SkMatrix combined = SkMatrix::Concat(info.fPreMat, info.fLocalMat); |
| 29 |
28 GrCachedLayer* layer = layerCache->findLayerOrCreate(pict->uniqueID(), | 30 GrCachedLayer* layer = layerCache->findLayerOrCreate(pict->uniqueID(), |
29 info.fSaveLayerOpID, | 31 info.fSaveLayerOpID, |
30 info.fRestoreOpID, | 32 info.fRestoreOpID, |
31 layerRect, | 33 layerRect, |
32 info.fOriginXform, | 34 combined, |
33 info.fPaint); | 35 info.fPaint); |
34 | |
35 GrTextureDesc desc; | 36 GrTextureDesc desc; |
36 desc.fFlags = kRenderTarget_GrTextureFlagBit; | 37 desc.fFlags = kRenderTarget_GrTextureFlagBit; |
37 desc.fWidth = layerRect.width(); | 38 desc.fWidth = layerRect.width(); |
38 desc.fHeight = layerRect.height(); | 39 desc.fHeight = layerRect.height(); |
39 desc.fConfig = kSkia8888_GrPixelConfig; | 40 desc.fConfig = kSkia8888_GrPixelConfig; |
40 // TODO: need to deal with sample count | 41 // TODO: need to deal with sample count |
41 | 42 |
42 | 43 |
43 bool disallowAtlasing = info.fHasNestedLayers || info.fIsNested || | 44 bool disallowAtlasing = info.fHasNestedLayers || info.fIsNested || |
44 (layer->paint() && layer->paint()->getImageFilter())
; | 45 (layer->paint() && layer->paint()->getImageFilter())
; |
(...skipping 13 matching lines...) Expand all Loading... |
58 hl = nonAtlased->append(); | 59 hl = nonAtlased->append(); |
59 } | 60 } |
60 } else { | 61 } else { |
61 hl = recycled->append(); | 62 hl = recycled->append(); |
62 } | 63 } |
63 | 64 |
64 layerCache->addUse(layer); | 65 layerCache->addUse(layer); |
65 hl->fLayer = layer; | 66 hl->fLayer = layer; |
66 hl->fPicture = pict; | 67 hl->fPicture = pict; |
67 hl->fOffset = SkIPoint::Make(layerRect.fLeft, layerRect.fTop); | 68 hl->fOffset = SkIPoint::Make(layerRect.fLeft, layerRect.fTop); |
68 hl->fCTM = info.fOriginXform; | 69 hl->fLocalMat = info.fLocalMat; |
| 70 hl->fPreMat = info.fPreMat; |
69 } | 71 } |
70 | 72 |
71 // Return true if any layers are suitable for hoisting | 73 // Return true if any layers are suitable for hoisting |
72 bool GrLayerHoister::FindLayersToHoist(GrContext* context, | 74 bool GrLayerHoister::FindLayersToHoist(GrContext* context, |
73 const SkPicture* topLevelPicture, | 75 const SkPicture* topLevelPicture, |
74 const SkRect& query, | 76 const SkRect& query, |
75 SkTDArray<GrHoistedLayer>* atlased, | 77 SkTDArray<GrHoistedLayer>* atlased, |
76 SkTDArray<GrHoistedLayer>* nonAtlased, | 78 SkTDArray<GrHoistedLayer>* nonAtlased, |
77 SkTDArray<GrHoistedLayer>* recycled) { | 79 SkTDArray<GrHoistedLayer>* recycled) { |
78 GrLayerCache* layerCache = context->getLayerCache(); | 80 GrLayerCache* layerCache = context->getLayerCache(); |
(...skipping 27 matching lines...) Expand all Loading... |
106 // Find and prepare for hoisting all the layers that intersect the query rec
t | 108 // Find and prepare for hoisting all the layers that intersect the query rec
t |
107 for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) { | 109 for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) { |
108 | 110 |
109 const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(
i); | 111 const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(
i); |
110 | 112 |
111 SkRect layerRect = SkRect::Make(info.fBounds); | 113 SkRect layerRect = SkRect::Make(info.fBounds); |
112 if (!layerRect.intersect(query)) { | 114 if (!layerRect.intersect(query)) { |
113 continue; | 115 continue; |
114 } | 116 } |
115 | 117 |
116 | |
117 SkIRect ir; | 118 SkIRect ir; |
118 layerRect.roundOut(&ir); | 119 layerRect.roundOut(&ir); |
119 | 120 |
120 // TODO: ignore perspective projected layers here! | 121 // TODO: ignore perspective projected layers here! |
121 // TODO: once this code is more stable unsuitable layers can | 122 // TODO: once this code is more stable unsuitable layers can |
122 // just be omitted during the optimization stage | 123 // just be omitted during the optimization stage |
123 if (info.fIsNested) { | 124 if (info.fIsNested) { |
124 continue; | 125 continue; |
125 } | 126 } |
126 | 127 |
(...skipping 10 matching lines...) Expand all Loading... |
137 result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref(); | 138 result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref(); |
138 } | 139 } |
139 | 140 |
140 static void convert_layers_to_replacements(const SkTDArray<GrHoistedLayer>& laye
rs, | 141 static void convert_layers_to_replacements(const SkTDArray<GrHoistedLayer>& laye
rs, |
141 GrReplacements* replacements) { | 142 GrReplacements* replacements) { |
142 // TODO: just replace GrReplacements::ReplacementInfo with GrCachedLayer? | 143 // TODO: just replace GrReplacements::ReplacementInfo with GrCachedLayer? |
143 for (int i = 0; i < layers.count(); ++i) { | 144 for (int i = 0; i < layers.count(); ++i) { |
144 GrCachedLayer* layer = layers[i].fLayer; | 145 GrCachedLayer* layer = layers[i].fLayer; |
145 const SkPicture* picture = layers[i].fPicture; | 146 const SkPicture* picture = layers[i].fPicture; |
146 | 147 |
| 148 SkMatrix combined = SkMatrix::Concat(layers[i].fPreMat, layers[i].fLocal
Mat); |
| 149 |
147 GrReplacements::ReplacementInfo* layerInfo = | 150 GrReplacements::ReplacementInfo* layerInfo = |
148 replacements->newReplacement(picture->uniqueID(), | 151 replacements->newReplacement(picture->uniqueID(), |
149 layer->start(), | 152 layer->start(), |
150 layers[i].fCTM); | 153 combined); |
151 layerInfo->fStop = layer->stop(); | 154 layerInfo->fStop = layer->stop(); |
152 layerInfo->fPos = layers[i].fOffset; | 155 layerInfo->fPos = layers[i].fOffset; |
153 | 156 |
154 SkBitmap bm; | 157 SkBitmap bm; |
155 wrap_texture(layers[i].fLayer->texture(), | 158 wrap_texture(layers[i].fLayer->texture(), |
156 !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().w
idth() | 159 !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().w
idth() |
157 : layers[i].fLayer->texture(
)->width(), | 160 : layers[i].fLayer->texture(
)->width(), |
158 !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().h
eight() | 161 !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().h
eight() |
159 : layers[i].fLayer->texture(
)->height(), | 162 : layers[i].fLayer->texture(
)->height(), |
160 &bm); | 163 &bm); |
161 layerInfo->fImage = SkImage::NewTexture(bm); | 164 layerInfo->fImage = SkImage::NewTexture(bm); |
162 | 165 |
163 layerInfo->fPaint = layers[i].fLayer->paint() | 166 layerInfo->fPaint = layers[i].fLayer->paint() |
164 ? SkNEW_ARGS(SkPaint, (*layers[i].fLayer->paint(
))) | 167 ? SkNEW_ARGS(SkPaint, (*layers[i].fLayer->paint(
))) |
165 : NULL; | 168 : NULL; |
166 | 169 |
167 layerInfo->fSrcRect = SkIRect::MakeXYWH(layers[i].fLayer->rect().fLeft, | 170 layerInfo->fSrcRect = SkIRect::MakeXYWH(layers[i].fLayer->rect().fLeft, |
168 layers[i].fLayer->rect().fTop, | 171 layers[i].fLayer->rect().fTop, |
169 layers[i].fLayer->rect().width()
, | 172 layers[i].fLayer->rect().width()
, |
170 layers[i].fLayer->rect().height(
)); | 173 layers[i].fLayer->rect().height(
)); |
171 } | 174 } |
172 } | 175 } |
173 | 176 |
174 void GrLayerHoister::DrawLayers(const SkTDArray<GrHoistedLayer>& atlased, | 177 void GrLayerHoister::DrawLayers(GrContext* context, |
| 178 const SkTDArray<GrHoistedLayer>& atlased, |
175 const SkTDArray<GrHoistedLayer>& nonAtlased, | 179 const SkTDArray<GrHoistedLayer>& nonAtlased, |
176 const SkTDArray<GrHoistedLayer>& recycled, | 180 const SkTDArray<GrHoistedLayer>& recycled, |
177 GrReplacements* replacements) { | 181 GrReplacements* replacements) { |
178 // Render the atlased layers that require it | 182 // Render the atlased layers that require it |
179 if (atlased.count() > 0) { | 183 if (atlased.count() > 0) { |
180 // All the atlased layers are rendered into the same GrTexture | 184 // All the atlased layers are rendered into the same GrTexture |
181 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( | 185 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( |
182 atlased[0].fLayer->texture()->asRenderTa
rget(), NULL)); | 186 atlased[0].fLayer->texture()->asRenderTa
rget(), NULL)); |
183 | 187 |
184 SkCanvas* atlasCanvas = surface->getCanvas(); | 188 SkCanvas* atlasCanvas = surface->getCanvas(); |
185 | 189 |
186 SkPaint paint; | 190 SkPaint clearPaint; |
187 paint.setColor(SK_ColorTRANSPARENT); | 191 clearPaint.setColor(SK_ColorTRANSPARENT); |
188 paint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref(); | 192 clearPaint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref
(); |
189 | 193 |
190 for (int i = 0; i < atlased.count(); ++i) { | 194 for (int i = 0; i < atlased.count(); ++i) { |
191 GrCachedLayer* layer = atlased[i].fLayer; | 195 const GrCachedLayer* layer = atlased[i].fLayer; |
192 const SkPicture* pict = atlased[i].fPicture; | 196 const SkPicture* pict = atlased[i].fPicture; |
193 const SkIPoint offset = atlased[i].fOffset; | 197 const SkIPoint offset = atlased[i].fOffset; |
| 198 SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();) |
| 199 |
| 200 SkASSERT(!layerPaint || !layerPaint->getImageFilter()); |
194 | 201 |
195 atlasCanvas->save(); | 202 atlasCanvas->save(); |
196 | 203 |
197 // Add a rect clip to make sure the rendering doesn't | 204 // Add a rect clip to make sure the rendering doesn't |
198 // extend beyond the boundaries of the atlased sub-rect | 205 // extend beyond the boundaries of the atlased sub-rect |
199 SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft), | 206 SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft), |
200 SkIntToScalar(layer->rect().fTop), | 207 SkIntToScalar(layer->rect().fTop), |
201 SkIntToScalar(layer->rect().width())
, | 208 SkIntToScalar(layer->rect().width())
, |
202 SkIntToScalar(layer->rect().height()
)); | 209 SkIntToScalar(layer->rect().height()
)); |
203 atlasCanvas->clipRect(bound); | 210 atlasCanvas->clipRect(bound); |
204 | 211 |
205 // Since 'clear' doesn't respect the clip we need to draw a rect | 212 // Since 'clear' doesn't respect the clip we need to draw a rect |
206 // TODO: ensure none of the atlased layers contain a clear call! | 213 // TODO: ensure none of the atlased layers contain a clear call! |
207 atlasCanvas->drawRect(bound, paint); | 214 atlasCanvas->drawRect(bound, clearPaint); |
208 | 215 |
209 // info.fCTM maps the layer's top/left to the origin. | 216 // info.fCTM maps the layer's top/left to the origin. |
210 // Since this layer is atlased, the top/left corner needs | 217 // Since this layer is atlased, the top/left corner needs |
211 // to be offset to the correct location in the backing texture. | 218 // to be offset to the correct location in the backing texture. |
212 SkMatrix initialCTM; | 219 SkMatrix initialCTM; |
213 initialCTM.setTranslate(SkIntToScalar(-offset.fX), | 220 initialCTM.setTranslate(SkIntToScalar(-offset.fX), |
214 SkIntToScalar(-offset.fY)); | 221 SkIntToScalar(-offset.fY)); |
215 initialCTM.postTranslate(bound.fLeft, bound.fTop); | 222 initialCTM.postTranslate(bound.fLeft, bound.fTop); |
216 | 223 initialCTM.postConcat(atlased[i].fPreMat); |
| 224 |
217 atlasCanvas->translate(SkIntToScalar(-offset.fX), | 225 atlasCanvas->translate(SkIntToScalar(-offset.fX), |
218 SkIntToScalar(-offset.fY)); | 226 SkIntToScalar(-offset.fY)); |
219 atlasCanvas->translate(bound.fLeft, bound.fTop); | 227 atlasCanvas->translate(bound.fLeft, bound.fTop); |
220 atlasCanvas->concat(atlased[i].fCTM); | 228 atlasCanvas->concat(atlased[i].fPreMat); |
| 229 atlasCanvas->concat(atlased[i].fLocalMat); |
221 | 230 |
222 SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas, bound, | 231 SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas, bound, |
223 layer->start()+1, layer->stop(), initialCTM); | 232 layer->start()+1, layer->stop(), initialCTM); |
224 | 233 |
225 atlasCanvas->restore(); | 234 atlasCanvas->restore(); |
226 } | 235 } |
227 | 236 |
228 atlasCanvas->flush(); | 237 atlasCanvas->flush(); |
229 } | 238 } |
230 | 239 |
231 // Render the non-atlased layers that require it | 240 // Render the non-atlased layers that require it |
232 for (int i = 0; i < nonAtlased.count(); ++i) { | 241 for (int i = 0; i < nonAtlased.count(); ++i) { |
233 GrCachedLayer* layer = nonAtlased[i].fLayer; | 242 GrCachedLayer* layer = nonAtlased[i].fLayer; |
234 const SkPicture* pict = nonAtlased[i].fPicture; | 243 const SkPicture* pict = nonAtlased[i].fPicture; |
235 const SkIPoint offset = nonAtlased[i].fOffset; | 244 const SkIPoint& offset = nonAtlased[i].fOffset; |
236 | 245 |
237 // Each non-atlased layer has its own GrTexture | 246 // Each non-atlased layer has its own GrTexture |
238 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( | 247 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( |
239 layer->texture()->asRenderTarget(), NULL
)); | 248 layer->texture()->asRenderTarget(), NULL
)); |
240 | 249 |
241 SkCanvas* layerCanvas = surface->getCanvas(); | 250 SkCanvas* layerCanvas = surface->getCanvas(); |
242 | 251 |
| 252 SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop); |
| 253 |
243 // Add a rect clip to make sure the rendering doesn't | 254 // Add a rect clip to make sure the rendering doesn't |
244 // extend beyond the boundaries of the atlased sub-rect | 255 // extend beyond the boundaries of the atlased sub-rect |
245 SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft), | 256 SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft), |
246 SkIntToScalar(layer->rect().fTop), | 257 SkIntToScalar(layer->rect().fTop), |
247 SkIntToScalar(layer->rect().width()), | 258 SkIntToScalar(layer->rect().width()), |
248 SkIntToScalar(layer->rect().height())); | 259 SkIntToScalar(layer->rect().height())); |
249 | 260 |
250 layerCanvas->clipRect(bound); // TODO: still useful? | 261 layerCanvas->clipRect(bound); // TODO: still useful? |
251 | 262 |
252 layerCanvas->clear(SK_ColorTRANSPARENT); | 263 layerCanvas->clear(SK_ColorTRANSPARENT); |
253 | 264 |
254 SkMatrix initialCTM; | 265 SkMatrix initialCTM; |
255 initialCTM.setTranslate(SkIntToScalar(-offset.fX), | 266 initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset
.fY)); |
256 SkIntToScalar(-offset.fY)); | 267 initialCTM.postConcat(nonAtlased[i].fPreMat); |
257 | 268 |
258 layerCanvas->translate(SkIntToScalar(-offset.fX), | 269 layerCanvas->translate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.
fY)); |
259 SkIntToScalar(-offset.fY)); | 270 layerCanvas->concat(nonAtlased[i].fPreMat); |
260 layerCanvas->concat(nonAtlased[i].fCTM); | 271 layerCanvas->concat(nonAtlased[i].fLocalMat); |
261 | 272 |
262 SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas, bound, | 273 SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas, bound, |
263 layer->start()+1, layer->stop(), initialCTM); | 274 layer->start()+1, layer->stop(), initialCTM); |
264 | 275 |
265 layerCanvas->flush(); | 276 layerCanvas->flush(); |
266 } | 277 } |
267 | 278 |
268 convert_layers_to_replacements(atlased, replacements); | 279 convert_layers_to_replacements(atlased, replacements); |
269 convert_layers_to_replacements(nonAtlased, replacements); | 280 convert_layers_to_replacements(nonAtlased, replacements); |
270 convert_layers_to_replacements(recycled, replacements); | 281 convert_layers_to_replacements(recycled, replacements); |
(...skipping 20 matching lines...) Expand all Loading... |
291 #if DISABLE_CACHING | 302 #if DISABLE_CACHING |
292 // This code completely clears out the atlas. It is required when | 303 // This code completely clears out the atlas. It is required when |
293 // caching is disabled so the atlas doesn't fill up and force more | 304 // caching is disabled so the atlas doesn't fill up and force more |
294 // free floating layers | 305 // free floating layers |
295 layerCache->purgeAll(); | 306 layerCache->purgeAll(); |
296 #endif | 307 #endif |
297 | 308 |
298 SkDEBUGCODE(layerCache->validate();) | 309 SkDEBUGCODE(layerCache->validate();) |
299 } | 310 } |
300 | 311 |
OLD | NEW |