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

Side by Side Diff: src/effects/SkGpuBlurUtils.cpp

Issue 1961953002: Reland of Simplify SkGpuBlurUtils::GaussianBlur method (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 7 months 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/effects/SkGpuBlurUtils.h ('k') | src/gpu/GrContext.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 2013 Google Inc. 2 * Copyright 2013 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 "SkGpuBlurUtils.h" 8 #include "SkGpuBlurUtils.h"
9 9
10 #include "SkRect.h" 10 #include "SkRect.h"
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 direction, radius, sigma, true, bounds); 158 direction, radius, sigma, true, bounds);
159 convolve_gaussian_1d(drawContext, clip, rightRect, srcOffset, texture, 159 convolve_gaussian_1d(drawContext, clip, rightRect, srcOffset, texture,
160 direction, radius, sigma, true, bounds); 160 direction, radius, sigma, true, bounds);
161 convolve_gaussian_1d(drawContext, clip, midRect, srcOffset, texture, 161 convolve_gaussian_1d(drawContext, clip, midRect, srcOffset, texture,
162 direction, radius, sigma, false, bounds); 162 direction, radius, sigma, false, bounds);
163 } 163 }
164 } 164 }
165 165
166 GrTexture* GaussianBlur(GrContext* context, 166 GrTexture* GaussianBlur(GrContext* context,
167 GrTexture* srcTexture, 167 GrTexture* srcTexture,
168 bool canClobberSrc,
169 bool gammaCorrect, 168 bool gammaCorrect,
170 const SkRect& dstBounds, 169 const SkRect& dstBounds,
171 const SkRect* srcBounds, 170 const SkRect* srcBounds,
172 float sigmaX, 171 float sigmaX,
173 float sigmaY) { 172 float sigmaY) {
174 SkASSERT(context); 173 SkASSERT(context);
175 SkIRect clearRect; 174 SkIRect clearRect;
176 int scaleFactorX, radiusX; 175 int scaleFactorX, radiusX;
177 int scaleFactorY, radiusY; 176 int scaleFactorY, radiusY;
178 int maxTextureSize = context->caps()->maxTextureSize(); 177 int maxTextureSize = context->caps()->maxTextureSize();
(...skipping 19 matching lines...) Expand all
198 197
199 // setup new clip 198 // setup new clip
200 GrClip clip(localDstBounds); 199 GrClip clip(localDstBounds);
201 200
202 SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() || 201 SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
203 kRGBA_8888_GrPixelConfig == srcTexture->config() || 202 kRGBA_8888_GrPixelConfig == srcTexture->config() ||
204 kSRGBA_8888_GrPixelConfig == srcTexture->config() || 203 kSRGBA_8888_GrPixelConfig == srcTexture->config() ||
205 kSBGRA_8888_GrPixelConfig == srcTexture->config() || 204 kSBGRA_8888_GrPixelConfig == srcTexture->config() ||
206 kAlpha_8_GrPixelConfig == srcTexture->config()); 205 kAlpha_8_GrPixelConfig == srcTexture->config());
207 206
207 const int width = SkScalarFloorToInt(dstBounds.width());
208 const int height = SkScalarFloorToInt(dstBounds.height());
209 const GrPixelConfig config = srcTexture->config();
210
211 const SkSurfaceProps props(gammaCorrect ? SkSurfaceProps::kGammaCorrect_Flag : 0,
212 SkSurfaceProps::kLegacyFontHost_InitType);
213
214 // For really small blurs (certainly no wider than 5x5 on desktop gpus) it i s faster to just
215 // launch a single non separable kernel vs two launches
216 if (sigmaX > 0.0f && sigmaY > 0.0f &&
217 (2 * radiusX + 1) * (2 * radiusY + 1) <= MAX_KERNEL_SIZE) {
218 // We shouldn't be scaling because this is a small size blur
219 SkASSERT((1 == scaleFactorX) && (1 == scaleFactorY));
220
221 sk_sp<GrDrawContext> dstDrawContext(context->newDrawContext(SkBackingFit ::kApprox,
222 width, heigh t, config,
223 0, kDefault_ GrSurfaceOrigin,
224 &props));
225 if (!dstDrawContext) {
226 return nullptr;
227 }
228 convolve_gaussian_2d(dstDrawContext.get(), clip, localDstBounds, srcOffs et,
229 srcTexture, radiusX, radiusY, sigmaX, sigmaY, srcBo unds);
230
231 return dstDrawContext->asTexture().release();
232 }
233
208 GrSurfaceDesc desc; 234 GrSurfaceDesc desc;
209 desc.fFlags = kRenderTarget_GrSurfaceFlag; 235 desc.fFlags = kRenderTarget_GrSurfaceFlag;
210 desc.fWidth = SkScalarFloorToInt(dstBounds.width()); 236 desc.fWidth = width;
211 desc.fHeight = SkScalarFloorToInt(dstBounds.height()); 237 desc.fHeight = height;
212 desc.fConfig = srcTexture->config(); 238 desc.fConfig = config;
213 239
214 GrTexture* dstTexture; 240 GrTexture* dstTexture;
215 GrTexture* tempTexture; 241 GrTexture* tempTexture;
216 SkAutoTUnref<GrTexture> temp1, temp2; 242 SkAutoTUnref<GrTexture> temp1, temp2;
217 243
218 temp1.reset(context->textureProvider()->createApproxTexture(desc)); 244 temp1.reset(context->textureProvider()->createApproxTexture(desc));
219 dstTexture = temp1.get(); 245 dstTexture = temp1.get();
220 if (canClobberSrc) { 246 temp2.reset(context->textureProvider()->createApproxTexture(desc));
221 tempTexture = srcTexture; 247 tempTexture = temp2.get();
222 } else {
223 temp2.reset(context->textureProvider()->createApproxTexture(desc));
224 tempTexture = temp2.get();
225 }
226 248
227 if (nullptr == dstTexture || nullptr == tempTexture) { 249 if (!dstTexture || !tempTexture) {
228 return nullptr; 250 return nullptr;
229 } 251 }
230 252
231 sk_sp<GrDrawContext> srcDrawContext; 253 sk_sp<GrDrawContext> srcDrawContext;
232 254
233 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) { 255 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
234 GrPaint paint; 256 GrPaint paint;
235 paint.setGammaCorrect(gammaCorrect); 257 paint.setGammaCorrect(gammaCorrect);
236 SkMatrix matrix; 258 SkMatrix matrix;
237 matrix.setIDiv(srcTexture->width(), srcTexture->height()); 259 matrix.setIDiv(srcTexture->width(), srcTexture->height());
238 SkRect dstRect(srcRect); 260 SkRect dstRect(srcRect);
239 if (srcBounds && i == 1) { 261 if (srcBounds && i == 1) {
240 SkRect domain; 262 SkRect domain;
241 matrix.mapRect(&domain, *srcBounds); 263 matrix.mapRect(&domain, *srcBounds);
242 domain.inset((i < scaleFactorX) ? SK_ScalarHalf / srcTexture->width( ) : 0.0f, 264 domain.inset((i < scaleFactorX) ? SK_ScalarHalf / srcTexture->width( ) : 0.0f,
243 (i < scaleFactorY) ? SK_ScalarHalf / srcTexture->height () : 0.0f); 265 (i < scaleFactorY) ? SK_ScalarHalf / srcTexture->height () : 0.0f);
244 SkAutoTUnref<const GrFragmentProcessor> fp(GrTextureDomainEffect::Cr eate( 266 sk_sp<const GrFragmentProcessor> fp(GrTextureDomainEffect::Create(
245 srcTexture, 267 srcTexture,
246 matrix, 268 matrix,
247 domain, 269 domain,
248 GrTextureDomain::kDecal_Mode, 270 GrTextureDomain::kDecal_ Mode,
249 GrTextureParams::kBilerp_FilterMode)); 271 GrTextureParams::kBilerp _FilterMode));
250 paint.addColorFragmentProcessor(fp); 272 paint.addColorFragmentProcessor(fp.get());
251 srcRect.offset(-srcOffset); 273 srcRect.offset(-srcOffset);
252 srcOffset.set(0, 0); 274 srcOffset.set(0, 0);
253 } else { 275 } else {
254 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::k Bilerp_FilterMode); 276 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::k Bilerp_FilterMode);
255 paint.addColorTextureProcessor(srcTexture, matrix, params); 277 paint.addColorTextureProcessor(srcTexture, matrix, params);
256 } 278 }
257 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); 279 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
258 scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f, 280 scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
259 i < scaleFactorY ? 0.5f : 1.0f); 281 i < scaleFactorY ? 0.5f : 1.0f);
260 282
261 sk_sp<GrDrawContext> dstDrawContext( 283 sk_sp<GrDrawContext> dstDrawContext(
262 context->drawContext(sk_ref_sp(dstTexture->as RenderTarget()))); 284 context->drawContext(sk_ref_sp(dstTexture->as RenderTarget())));
263 if (!dstDrawContext) { 285 if (!dstDrawContext) {
264 return nullptr; 286 return nullptr;
265 } 287 }
266 dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcR ect); 288 dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcR ect);
267 289
268 srcDrawContext.swap(dstDrawContext); 290 srcDrawContext.swap(dstDrawContext);
269 srcRect = dstRect; 291 srcRect = dstRect;
270 srcTexture = dstTexture; 292 srcTexture = dstTexture;
271 SkTSwap(dstTexture, tempTexture); 293 SkTSwap(dstTexture, tempTexture);
272 localSrcBounds = srcRect; 294 localSrcBounds = srcRect;
273 } 295 }
274 296
275 SkSurfaceProps props(gammaCorrect ? SkSurfaceProps::kGammaCorrect_Flag : 0, 297 srcRect = localDstBounds;
276 SkSurfaceProps::kLegacyFontHost_InitType);
277 298
278 // For really small blurs (certainly no wider than 5x5 on desktop gpus) it i s faster to just 299 scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
279 // launch a single non separable kernel vs two launches 300 srcRect.roundOut(&srcRect);
280 srcRect = localDstBounds; 301 SkIRect srcIRect = srcRect.roundOut();
281 if (sigmaX > 0.0f && sigmaY > 0.0f && 302 if (sigmaX > 0.0f) {
282 (2 * radiusX + 1) * (2 * radiusY + 1) <= MAX_KERNEL_SIZE) { 303 if (scaleFactorX > 1) {
283 // We shouldn't be scaling because this is a small size blur 304 // TODO: if we pass in the source draw context we don't need this he re
284 SkASSERT((1 == scaleFactorX) && (1 == scaleFactorY)); 305 if (!srcDrawContext) {
306 srcDrawContext = context->drawContext(sk_ref_sp(srcTexture->asRe nderTarget()));
307 if (!srcDrawContext) {
308 return nullptr;
309 }
310 }
311
312 // Clear out a radius to the right of the srcRect to prevent the
313 // X convolution from reading garbage.
314 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
315 radiusX, srcIRect.height());
316 srcDrawContext->clear(&clearRect, 0x0, false);
317 }
285 318
286 sk_sp<GrDrawContext> dstDrawContext( 319 sk_sp<GrDrawContext> dstDrawContext(
287 context->drawContext(sk_ref_sp(dstTexture->asRenderTarget()), &props )); 320 context->drawContext(sk_ref_sp(dstTexture->asRenderTarget()), &props ));
288 if (!dstDrawContext) { 321 if (!dstDrawContext) {
289 return nullptr; 322 return nullptr;
290 } 323 }
291 convolve_gaussian_2d(dstDrawContext.get(), clip, srcRect, srcOffset, 324 convolve_gaussian(dstDrawContext.get(), clip, srcRect,
292 srcTexture, radiusX, radiusY, sigmaX, sigmaY, srcBo unds); 325 srcTexture, Gr1DKernelEffect::kX_Direction, radiusX, s igmaX,
326 srcBounds, srcOffset);
327 srcDrawContext.swap(dstDrawContext);
328 srcTexture = dstTexture;
329 srcRect.offsetTo(0, 0);
330 SkTSwap(dstTexture, tempTexture);
331 localSrcBounds = srcRect;
332 srcOffset.set(0, 0);
333 }
334
335 if (sigmaY > 0.0f) {
336 if (scaleFactorY > 1 || sigmaX > 0.0f) {
337 // TODO: if we pass in the source draw context we don't need this he re
338 if (!srcDrawContext) {
339 srcDrawContext = context->drawContext(sk_ref_sp(srcTexture->asRe nderTarget()));
340 if (!srcDrawContext) {
341 return nullptr;
342 }
343 }
344
345 // Clear out a radius below the srcRect to prevent the Y
346 // convolution from reading garbage.
347 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
348 srcIRect.width(), radiusY);
349 srcDrawContext->clear(&clearRect, 0x0, false);
350 }
351
352 sk_sp<GrDrawContext> dstDrawContext(
353 context->drawContext(sk_ref_sp(dstTexture->asRenderTarget()), &props ));
354 if (!dstDrawContext) {
355 return nullptr;
356 }
357 convolve_gaussian(dstDrawContext.get(), clip, srcRect,
358 srcTexture, Gr1DKernelEffect::kY_Direction, radiusY, s igmaY,
359 srcBounds, srcOffset);
293 360
294 srcDrawContext.swap(dstDrawContext); 361 srcDrawContext.swap(dstDrawContext);
362 srcTexture = dstTexture;
295 srcRect.offsetTo(0, 0); 363 srcRect.offsetTo(0, 0);
296 srcTexture = dstTexture;
297 SkTSwap(dstTexture, tempTexture); 364 SkTSwap(dstTexture, tempTexture);
365 }
298 366
299 } else { 367 srcIRect = srcRect.roundOut();
300 scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
301 srcRect.roundOut(&srcRect);
302 const SkIRect srcIRect = srcRect.roundOut();
303 if (sigmaX > 0.0f) {
304 if (scaleFactorX > 1) {
305 // TODO: if we pass in the source draw context we don't need thi s here
306 if (!srcDrawContext) {
307 srcDrawContext = context->drawContext(sk_ref_sp(srcTexture-> asRenderTarget()));
308 if (!srcDrawContext) {
309 return nullptr;
310 }
311 }
312
313 // Clear out a radius to the right of the srcRect to prevent the
314 // X convolution from reading garbage.
315 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
316 radiusX, srcIRect.height());
317 srcDrawContext->clear(&clearRect, 0x0, false);
318 }
319
320 sk_sp<GrDrawContext> dstDrawContext(
321 context->drawContext(sk_ref_sp(dstTexture->asRenderTarget()), &p rops));
322 if (!dstDrawContext) {
323 return nullptr;
324 }
325 convolve_gaussian(dstDrawContext.get(), clip, srcRect,
326 srcTexture, Gr1DKernelEffect::kX_Direction, radius X, sigmaX,
327 srcBounds, srcOffset);
328 srcDrawContext.swap(dstDrawContext);
329 srcTexture = dstTexture;
330 srcRect.offsetTo(0, 0);
331 SkTSwap(dstTexture, tempTexture);
332 localSrcBounds = srcRect;
333 srcOffset.set(0, 0);
334 }
335
336 if (sigmaY > 0.0f) {
337 if (scaleFactorY > 1 || sigmaX > 0.0f) {
338 // TODO: if we pass in the source draw context we don't need thi s here
339 if (!srcDrawContext) {
340 srcDrawContext = context->drawContext(sk_ref_sp(srcTexture-> asRenderTarget()));
341 if (!srcDrawContext) {
342 return nullptr;
343 }
344 }
345
346 // Clear out a radius below the srcRect to prevent the Y
347 // convolution from reading garbage.
348 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
349 srcIRect.width(), radiusY);
350 srcDrawContext->clear(&clearRect, 0x0, false);
351 }
352
353 sk_sp<GrDrawContext> dstDrawContext(
354 context->drawContext(sk_ref_sp(dstTexture->asRenderTarget()), &p rops));
355 if (!dstDrawContext) {
356 return nullptr;
357 }
358 convolve_gaussian(dstDrawContext.get(), clip, srcRect,
359 srcTexture, Gr1DKernelEffect::kY_Direction, radius Y, sigmaY,
360 srcBounds, srcOffset);
361
362 srcDrawContext.swap(dstDrawContext);
363 srcTexture = dstTexture;
364 srcRect.offsetTo(0, 0);
365 SkTSwap(dstTexture, tempTexture);
366 }
367 }
368 const SkIRect srcIRect = srcRect.roundOut();
369 368
370 if (scaleFactorX > 1 || scaleFactorY > 1) { 369 if (scaleFactorX > 1 || scaleFactorY > 1) {
371 SkASSERT(srcDrawContext); 370 SkASSERT(srcDrawContext);
372 371
373 // Clear one pixel to the right and below, to accommodate bilinear 372 // Clear one pixel to the right and below, to accommodate bilinear
374 // upsampling. 373 // upsampling.
375 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, 374 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
376 srcIRect.width() + 1, 1); 375 srcIRect.width() + 1, 1);
377 srcDrawContext->clear(&clearRect, 0x0, false); 376 srcDrawContext->clear(&clearRect, 0x0, false);
378 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, 377 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
(...skipping 23 matching lines...) Expand all
402 srcRect = dstRect; 401 srcRect = dstRect;
403 srcTexture = dstTexture; 402 srcTexture = dstTexture;
404 SkTSwap(dstTexture, tempTexture); 403 SkTSwap(dstTexture, tempTexture);
405 } 404 }
406 405
407 return SkRef(srcTexture); 406 return SkRef(srcTexture);
408 } 407 }
409 #endif 408 #endif
410 409
411 } 410 }
OLDNEW
« no previous file with comments | « src/effects/SkGpuBlurUtils.h ('k') | src/gpu/GrContext.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698