Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: src/gpu/GrLayerHoister.cpp

Issue 803183003: Fix layer hoisting image filter corner cases (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix unit test Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrLayerHoister.h ('k') | src/gpu/GrRecordReplaceDraw.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "SkGpuDevice.h" 13 #include "SkGpuDevice.h"
14 #include "SkGrPixelRef.h" 14 #include "SkGrPixelRef.h"
15 #include "SkLayerInfo.h" 15 #include "SkLayerInfo.h"
16 #include "SkRecordDraw.h" 16 #include "SkRecordDraw.h"
17 #include "SkSurface.h" 17 #include "SkSurface.h"
18 #include "SkSurface_Gpu.h" 18 #include "SkSurface_Gpu.h"
19 19
20 // Create the layer information for the hoisted layer and secure the 20 // Create the layer information for the hoisted layer and secure the
21 // required texture/render target resources. 21 // required texture/render target resources.
22 static void prepare_for_hoisting(GrLayerCache* layerCache, 22 static void prepare_for_hoisting(GrLayerCache* layerCache,
23 const SkPicture* topLevelPicture, 23 const SkPicture* topLevelPicture,
24 const SkMatrix& initialMat, 24 const SkMatrix& initialMat,
25 const SkLayerInfo::BlockInfo& info, 25 const SkLayerInfo::BlockInfo& info,
26 const SkIRect& layerRect, 26 const SkIRect& srcIR,
27 const SkIRect& dstIR,
27 SkTDArray<GrHoistedLayer>* needRendering, 28 SkTDArray<GrHoistedLayer>* needRendering,
28 SkTDArray<GrHoistedLayer>* recycled, 29 SkTDArray<GrHoistedLayer>* recycled,
29 bool attemptToAtlas, 30 bool attemptToAtlas,
30 int numSamples) { 31 int numSamples) {
31 const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture; 32 const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture;
32 33
33 GrCachedLayer* layer = layerCache->findLayerOrCreate(topLevelPicture->unique ID(), 34 GrCachedLayer* layer = layerCache->findLayerOrCreate(topLevelPicture->unique ID(),
34 SkToInt(info.fSaveLayer OpID), 35 SkToInt(info.fSaveLayer OpID),
35 SkToInt(info.fRestoreOp ID), 36 SkToInt(info.fRestoreOp ID),
36 layerRect, 37 srcIR,
38 dstIR,
37 initialMat, 39 initialMat,
38 info.fKey, 40 info.fKey,
39 info.fKeySize, 41 info.fKeySize,
40 info.fPaint); 42 info.fPaint);
41 GrSurfaceDesc desc; 43 GrSurfaceDesc desc;
42 desc.fFlags = kRenderTarget_GrSurfaceFlag; 44 desc.fFlags = kRenderTarget_GrSurfaceFlag;
43 desc.fWidth = layerRect.width(); 45 desc.fWidth = srcIR.width();
44 desc.fHeight = layerRect.height(); 46 desc.fHeight = srcIR.height();
45 desc.fConfig = kSkia8888_GrPixelConfig; 47 desc.fConfig = kSkia8888_GrPixelConfig;
46 desc.fSampleCnt = numSamples; 48 desc.fSampleCnt = numSamples;
47 49
48 bool locked, needsRendering; 50 bool locked, needsRendering;
49 if (attemptToAtlas) { 51 if (attemptToAtlas) {
50 locked = layerCache->tryToAtlas(layer, desc, &needsRendering); 52 locked = layerCache->tryToAtlas(layer, desc, &needsRendering);
51 } else { 53 } else {
52 locked = layerCache->lock(layer, desc, &needsRendering); 54 locked = layerCache->lock(layer, desc, &needsRendering);
53 } 55 }
54 if (!locked) { 56 if (!locked) {
(...skipping 18 matching lines...) Expand all
73 75
74 layerCache->addUse(layer); 76 layerCache->addUse(layer);
75 hl->fLayer = layer; 77 hl->fLayer = layer;
76 hl->fPicture = pict; 78 hl->fPicture = pict;
77 hl->fLocalMat = info.fLocalMat; 79 hl->fLocalMat = info.fLocalMat;
78 hl->fInitialMat = initialMat; 80 hl->fInitialMat = initialMat;
79 hl->fPreMat = initialMat; 81 hl->fPreMat = initialMat;
80 hl->fPreMat.preConcat(info.fPreMat); 82 hl->fPreMat.preConcat(info.fPreMat);
81 } 83 }
82 84
85 // Compute the source rect if possible and return false if further processing
86 // on the layer should be abandoned based on its source rect.
87 static bool compute_source_rect(const SkLayerInfo::BlockInfo& info, const SkMatr ix& initialMat,
88 const SkIRect& dstIR, SkIRect* srcIR) {
89 SkIRect clipBounds = dstIR;
90
91 SkMatrix totMat = initialMat;
92 totMat.preConcat(info.fPreMat);
93 totMat.preConcat(info.fLocalMat);
94
95 if (info.fPaint && info.fPaint->getImageFilter()) {
96 info.fPaint->getImageFilter()->filterBounds(clipBounds, totMat, &clipBou nds);
97 }
98
99 if (!info.fSrcBounds.isEmpty()) {
100 SkRect r;
101
102 totMat.mapRect(&r, info.fSrcBounds);
103 r.roundOut(srcIR);
104
105 if (!srcIR->intersect(clipBounds)) {
106 return false;
107 }
108 } else {
109 *srcIR = clipBounds;
110 }
111
112 if (!GrLayerCache::PlausiblyAtlasable(srcIR->width(), srcIR->height())) {
113 return false;
114 }
115
116 return true;
117 }
118
83 // Atlased layers must be small enough to fit in the atlas, not have a 119 // 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. 120 // paint with an image filter and be neither nested nor nesting.
85 // TODO: allow leaf nested layers to appear in the atlas. 121 // TODO: allow leaf nested layers to appear in the atlas.
86 void GrLayerHoister::FindLayersToAtlas(GrContext* context, 122 void GrLayerHoister::FindLayersToAtlas(GrContext* context,
87 const SkPicture* topLevelPicture, 123 const SkPicture* topLevelPicture,
88 const SkMatrix& initialMat, 124 const SkMatrix& initialMat,
89 const SkRect& query, 125 const SkRect& query,
90 SkTDArray<GrHoistedLayer>* atlased, 126 SkTDArray<GrHoistedLayer>* atlased,
91 SkTDArray<GrHoistedLayer>* recycled, 127 SkTDArray<GrHoistedLayer>* recycled,
92 int numSamples) { 128 int numSamples) {
(...skipping 30 matching lines...) Expand all
123 if (disallowAtlasing) { 159 if (disallowAtlasing) {
124 continue; 160 continue;
125 } 161 }
126 162
127 SkRect layerRect; 163 SkRect layerRect;
128 initialMat.mapRect(&layerRect, info.fBounds); 164 initialMat.mapRect(&layerRect, info.fBounds);
129 if (!layerRect.intersect(query)) { 165 if (!layerRect.intersect(query)) {
130 continue; 166 continue;
131 } 167 }
132 168
133 const SkIRect ir = layerRect.roundOut(); 169 const SkIRect dstIR = layerRect.roundOut();
134 170
135 if (!GrLayerCache::PlausiblyAtlasable(ir.width(), ir.height())) { 171 SkIRect srcIR;
172
173 if (!compute_source_rect(info, initialMat, dstIR, &srcIR)) {
136 continue; 174 continue;
137 } 175 }
138 176
139 prepare_for_hoisting(layerCache, topLevelPicture, initialMat, 177 prepare_for_hoisting(layerCache, topLevelPicture, initialMat,
140 info, ir, atlased, recycled, true, 0); 178 info, srcIR, dstIR, atlased, recycled, true, 0);
141 } 179 }
142 180
143 } 181 }
144 182
145 void GrLayerHoister::FindLayersToHoist(GrContext* context, 183 void GrLayerHoister::FindLayersToHoist(GrContext* context,
146 const SkPicture* topLevelPicture, 184 const SkPicture* topLevelPicture,
147 const SkMatrix& initialMat, 185 const SkMatrix& initialMat,
148 const SkRect& query, 186 const SkRect& query,
149 SkTDArray<GrHoistedLayer>* needRendering, 187 SkTDArray<GrHoistedLayer>* needRendering,
150 SkTDArray<GrHoistedLayer>* recycled, 188 SkTDArray<GrHoistedLayer>* recycled,
(...skipping 21 matching lines...) Expand all
172 // Parent layers are currently hoisted while nested layers are not. 210 // Parent layers are currently hoisted while nested layers are not.
173 continue; 211 continue;
174 } 212 }
175 213
176 SkRect layerRect; 214 SkRect layerRect;
177 initialMat.mapRect(&layerRect, info.fBounds); 215 initialMat.mapRect(&layerRect, info.fBounds);
178 if (!layerRect.intersect(query)) { 216 if (!layerRect.intersect(query)) {
179 continue; 217 continue;
180 } 218 }
181 219
182 const SkIRect ir = layerRect.roundOut(); 220 const SkIRect dstIR = layerRect.roundOut();
183 221
184 prepare_for_hoisting(layerCache, topLevelPicture, initialMat, info, ir, 222 SkIRect srcIR;
223 if (!compute_source_rect(info, initialMat, dstIR, &srcIR)) {
224 continue;
225 }
226
227 prepare_for_hoisting(layerCache, topLevelPicture, initialMat, info, srcI R, dstIR,
185 needRendering, recycled, false, numSamples); 228 needRendering, recycled, false, numSamples);
186 } 229 }
187 } 230 }
188 231
189 void GrLayerHoister::DrawLayersToAtlas(GrContext* context, 232 void GrLayerHoister::DrawLayersToAtlas(GrContext* context,
190 const SkTDArray<GrHoistedLayer>& atlased) { 233 const SkTDArray<GrHoistedLayer>& atlased) {
191 if (atlased.count() > 0) { 234 if (atlased.count() > 0) {
192 // All the atlased layers are rendered into the same GrTexture 235 // All the atlased layers are rendered into the same GrTexture
193 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( 236 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
194 atlased[0].fLayer->texture()->asRenderTa rget(), NULL)); 237 atlased[0].fLayer->texture()->asRenderTa rget(), NULL));
195 238
196 SkCanvas* atlasCanvas = surface->getCanvas(); 239 SkCanvas* atlasCanvas = surface->getCanvas();
197 240
198 for (int i = 0; i < atlased.count(); ++i) { 241 for (int i = 0; i < atlased.count(); ++i) {
199 const GrCachedLayer* layer = atlased[i].fLayer; 242 const GrCachedLayer* layer = atlased[i].fLayer;
200 const SkPicture* pict = atlased[i].fPicture; 243 const SkPicture* pict = atlased[i].fPicture;
201 const SkIPoint offset = SkIPoint::Make(layer->bound().fLeft, layer-> bound().fTop); 244 const SkIPoint offset = SkIPoint::Make(layer->srcIR().fLeft, layer-> srcIR().fTop);
202 SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();) 245 SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();)
203 246
204 SkASSERT(!layerPaint || !layerPaint->getImageFilter()); 247 SkASSERT(!layerPaint || !layerPaint->getImageFilter());
205 SkASSERT(!layer->filter()); 248 SkASSERT(!layer->filter());
206 249
207 atlasCanvas->save(); 250 atlasCanvas->save();
208 251
209 // Add a rect clip to make sure the rendering doesn't 252 // Add a rect clip to make sure the rendering doesn't
210 // extend beyond the boundaries of the atlased sub-rect 253 // extend beyond the boundaries of the atlased sub-rect
211 const SkRect bound = SkRect::Make(layer->rect()); 254 const SkRect bound = SkRect::Make(layer->rect());
(...skipping 15 matching lines...) Expand all
227 pict->drawablePicts(), pict->drawableCount(), 270 pict->drawablePicts(), pict->drawableCount(),
228 layer->start() + 1, layer->stop(), initialCTM); 271 layer->start() + 1, layer->stop(), initialCTM);
229 272
230 atlasCanvas->restore(); 273 atlasCanvas->restore();
231 } 274 }
232 275
233 atlasCanvas->flush(); 276 atlasCanvas->flush();
234 } 277 }
235 } 278 }
236 279
237 void GrLayerHoister::FilterLayer(GrContext* context, SkGpuDevice* device, GrCach edLayer* layer) { 280 void GrLayerHoister::FilterLayer(GrContext* context,
281 SkGpuDevice* device,
282 const GrHoistedLayer& info) {
283 GrCachedLayer* layer = info.fLayer;
284
238 SkASSERT(layer->filter()); 285 SkASSERT(layer->filter());
286 SkASSERT(layer->filter()->canFilterImageGPU());
239 287
240 static const int kDefaultCacheSize = 32 * 1024 * 1024; 288 static const int kDefaultCacheSize = 32 * 1024 * 1024;
241 289
242 if (layer->filter()->canFilterImageGPU()) { 290 SkBitmap filteredBitmap;
243 SkBitmap filteredBitmap; 291 SkIPoint offset = SkIPoint::Make(0, 0);
244 SkIPoint offset = SkIPoint::Make(0, 0);
245 292
246 SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop); 293 const SkIPoint filterOffset = SkIPoint::Make(layer->srcIR().fLeft, layer->sr cIR().fTop);
247 SkIRect clipBounds = layer->rect();
248 294
249 // This cache is transient, and is freed (along with all its contained 295 SkMatrix totMat = SkMatrix::I();
250 // textures) when it goes out of scope. 296 totMat.preConcat(info.fPreMat);
251 SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(kD efaultCacheSize)); 297 totMat.preConcat(info.fLocalMat);
252 SkImageFilter::Context filterContext(SkMatrix::I(), clipBounds, cache); 298 totMat.postTranslate(-SkIntToScalar(filterOffset.fX), -SkIntToScalar(filterO ffset.fY));
253 299
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 300
260 // TODO: need to fix up offset 301 SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop);
261 SkASSERT(0 == offset.fX && 0 == offset.fY); 302 SkIRect clipBounds = layer->rect();
262 303
263 SkIRect newRect = SkIRect::MakeWH(filteredBitmap.width(), filteredBitmap .height()); 304 // This cache is transient, and is freed (along with all its contained
264 layer->setTexture(filteredBitmap.getTexture(), newRect); 305 // textures) when it goes out of scope.
306 SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(kDefau ltCacheSize));
307 SkImageFilter::Context filterContext(totMat, clipBounds, cache);
308
309 if (!device->filterTexture(context, layer->texture(), layer->filter(),
310 filterContext, &filteredBitmap, &offset)) {
311 // Filtering failed. Press on with the unfiltered version
312 return;
265 } 313 }
314
315 SkIRect newRect = SkIRect::MakeWH(filteredBitmap.width(), filteredBitmap.hei ght());
316 layer->setTexture(filteredBitmap.getTexture(), newRect);
317 layer->setOffset(offset);
266 } 318 }
267 319
268 void GrLayerHoister::DrawLayers(GrContext* context, const SkTDArray<GrHoistedLay er>& layers) { 320 void GrLayerHoister::DrawLayers(GrContext* context, const SkTDArray<GrHoistedLay er>& layers) {
269 for (int i = 0; i < layers.count(); ++i) { 321 for (int i = 0; i < layers.count(); ++i) {
270 GrCachedLayer* layer = layers[i].fLayer; 322 GrCachedLayer* layer = layers[i].fLayer;
271 const SkPicture* pict = layers[i].fPicture; 323 const SkPicture* pict = layers[i].fPicture;
272 const SkIPoint offset = SkIPoint::Make(layer->bound().fLeft, layer->boun d().fTop); 324 const SkIPoint offset = SkIPoint::Make(layer->srcIR().fLeft, layer->srcI R().fTop);
273 325
274 // Each non-atlased layer has its own GrTexture 326 // Each non-atlased layer has its own GrTexture
275 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( 327 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
276 layer->texture()->asRenderTarget(), NULL )); 328 layer->texture()->asRenderTarget(), NULL ));
277 329
278 SkCanvas* layerCanvas = surface->getCanvas(); 330 SkCanvas* layerCanvas = surface->getCanvas();
279 331
280 SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop); 332 SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop);
281 333
282 // Add a rect clip to make sure the rendering doesn't 334 // Add a rect clip to make sure the rendering doesn't
(...skipping 11 matching lines...) Expand all
294 346
295 SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas, 347 SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas,
296 pict->drawablePicts(), pict->drawableCount(), 348 pict->drawablePicts(), pict->drawableCount(),
297 layer->start()+1, layer->stop(), initialCTM); 349 layer->start()+1, layer->stop(), initialCTM);
298 350
299 layerCanvas->flush(); 351 layerCanvas->flush();
300 352
301 if (layer->filter()) { 353 if (layer->filter()) {
302 SkSurface_Gpu* gpuSurf = static_cast<SkSurface_Gpu*>(surface.get()); 354 SkSurface_Gpu* gpuSurf = static_cast<SkSurface_Gpu*>(surface.get());
303 355
304 FilterLayer(context, gpuSurf->getDevice(), layer); 356 FilterLayer(context, gpuSurf->getDevice(), layers[i]);
305 } 357 }
306 } 358 }
307 } 359 }
308 360
309 void GrLayerHoister::UnlockLayers(GrContext* context, 361 void GrLayerHoister::UnlockLayers(GrContext* context,
310 const SkTDArray<GrHoistedLayer>& layers) { 362 const SkTDArray<GrHoistedLayer>& layers) {
311 GrLayerCache* layerCache = context->getLayerCache(); 363 GrLayerCache* layerCache = context->getLayerCache();
312 364
313 for (int i = 0; i < layers.count(); ++i) { 365 for (int i = 0; i < layers.count(); ++i) {
314 layerCache->removeUse(layers[i].fLayer); 366 layerCache->removeUse(layers[i].fLayer);
315 } 367 }
316 368
317 SkDEBUGCODE(layerCache->validate();) 369 SkDEBUGCODE(layerCache->validate();)
318 } 370 }
319 371
320 void GrLayerHoister::PurgeCache(GrContext* context) { 372 void GrLayerHoister::PurgeCache(GrContext* context) {
321 #if !GR_CACHE_HOISTED_LAYERS 373 #if !GR_CACHE_HOISTED_LAYERS
322 GrLayerCache* layerCache = context->getLayerCache(); 374 GrLayerCache* layerCache = context->getLayerCache();
323 375
324 // This code completely clears out the atlas. It is required when 376 // 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 377 // caching is disabled so the atlas doesn't fill up and force more
326 // free floating layers 378 // free floating layers
327 layerCache->purgeAll(); 379 layerCache->purgeAll();
328 #endif 380 #endif
329 } 381 }
OLDNEW
« no previous file with comments | « src/gpu/GrLayerHoister.h ('k') | src/gpu/GrRecordReplaceDraw.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698