From c834ab178e56009875dee8d2265dba35cf6e1e55 Mon Sep 17 00:00:00 2001 From: senorblanco Date: Thu, 17 Dec 2015 08:10:17 -0800 Subject: [PATCH] Fix gaussian blur for small sigma. I broke this in https://skia.googlesource.com/skia/+/c57e0ded7d535523cfc6bf07c78e5f3479bb8c42. That change added support for cropping during blur, but did not do the correct thing for the small-sigma 2D matrix convolution optimization when blurring from small-to-large textures. The fix is pass the correct dstRect and srcOffset to convolve_gaussian_2d. I also changed convolve_gaussian_1d() and convolve_gaussian_2d() to take the original (non-negated) srcOffset, and to negate them when constructing the local matrix. Test: added a new (blur 0.3 0.3) column to imagefilterscropexpand, so that GM will have to be rebaselined. BUG=skia:4719,569883 GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1529313003 Review URL: https://codereview.chromium.org/1529313003 --- gm/imagefilterscropexpand.cpp | 5 ++++- src/effects/SkGpuBlurUtils.cpp | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/gm/imagefilterscropexpand.cpp b/gm/imagefilterscropexpand.cpp index b173648..4fa9b00 100644 --- a/gm/imagefilterscropexpand.cpp +++ b/gm/imagefilterscropexpand.cpp @@ -35,7 +35,7 @@ protected: return SkString("imagefilterscropexpand"); } - SkISize onISize() override { return SkISize::Make(570, 650); } + SkISize onISize() override { return SkISize::Make(650, 650); } void onDraw(SkCanvas* canvas) override { SkAutoTUnref cf( @@ -78,6 +78,9 @@ protected: cfAlphaTrans, noopCropped.get(), &big_rect)); Draw(canvas, checkerboard, rect, SkBlurImageFilter::Create( + 0.3f, 0.3f, noopCropped.get(), &big_rect)); + + Draw(canvas, checkerboard, rect, SkBlurImageFilter::Create( 8.0f, 8.0f, noopCropped.get(), &big_rect)); Draw(canvas, checkerboard, rect, SkDilateImageFilter::Create( diff --git a/src/effects/SkGpuBlurUtils.cpp b/src/effects/SkGpuBlurUtils.cpp index 8ab05dd..13b6b0a 100644 --- a/src/effects/SkGpuBlurUtils.cpp +++ b/src/effects/SkGpuBlurUtils.cpp @@ -60,21 +60,21 @@ static void convolve_gaussian_1d(GrDrawContext* drawContext, texture, direction, radius, sigma, useBounds, bounds)); paint.addColorFragmentProcessor(conv); paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); - SkMatrix localMatrix = SkMatrix::MakeTrans(srcOffset.x(), srcOffset.y()); + SkMatrix localMatrix = SkMatrix::MakeTrans(-srcOffset.x(), -srcOffset.y()); drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), dstRect, localMatrix); } static void convolve_gaussian_2d(GrDrawContext* drawContext, const GrClip& clip, - const SkRect& srcRect, + const SkRect& dstRect, + const SkPoint& srcOffset, GrTexture* texture, int radiusX, int radiusY, SkScalar sigmaX, SkScalar sigmaY, const SkRect* srcBounds) { - SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); - SkMatrix localMatrix = SkMatrix::MakeTrans(srcRect.x(), srcRect.y()); + SkMatrix localMatrix = SkMatrix::MakeTrans(-srcOffset.x(), -srcOffset.y()); SkISize size = SkISize::Make(2 * radiusX + 1, 2 * radiusY + 1); SkIPoint kernelOffset = SkIPoint::Make(radiusX, radiusY); GrPaint paint; @@ -148,15 +148,15 @@ static void convolve_gaussian(GrDrawContext* drawContext, } if (midRect.isEmpty()) { // Blur radius covers srcBounds; use bounds over entire draw - convolve_gaussian_1d(drawContext, clip, dstRect, -srcOffset, texture, + convolve_gaussian_1d(drawContext, clip, dstRect, srcOffset, texture, direction, radius, sigma, true, bounds); } else { // Draw right and left margins with bounds; middle without. - convolve_gaussian_1d(drawContext, clip, leftRect, -srcOffset, texture, + convolve_gaussian_1d(drawContext, clip, leftRect, srcOffset, texture, direction, radius, sigma, true, bounds); - convolve_gaussian_1d(drawContext, clip, rightRect, -srcOffset, texture, + convolve_gaussian_1d(drawContext, clip, rightRect, srcOffset, texture, direction, radius, sigma, true, bounds); - convolve_gaussian_1d(drawContext, clip, midRect, -srcOffset, texture, + convolve_gaussian_1d(drawContext, clip, midRect, srcOffset, texture, direction, radius, sigma, false, bounds); } } @@ -269,6 +269,7 @@ GrTexture* GaussianBlur(GrContext* context, // For really small blurs (certainly no wider than 5x5 on desktop gpus) it is faster to just // launch a single non separable kernel vs two launches + srcRect = localDstBounds; if (sigmaX > 0.0f && sigmaY > 0.0f && (2 * radiusX + 1) * (2 * radiusY + 1) <= MAX_KERNEL_SIZE) { // We shouldn't be scaling because this is a small size blur @@ -279,7 +280,7 @@ GrTexture* GaussianBlur(GrContext* context, if (!dstDrawContext) { return nullptr; } - convolve_gaussian_2d(dstDrawContext, clip, srcRect, + convolve_gaussian_2d(dstDrawContext, clip, srcRect, srcOffset, srcTexture, radiusX, radiusY, sigmaX, sigmaY, srcBounds); srcDrawContext.swap(dstDrawContext); @@ -288,7 +289,6 @@ GrTexture* GaussianBlur(GrContext* context, SkTSwap(dstTexture, tempTexture); } else { - srcRect = localDstBounds; scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); srcRect.roundOut(&srcRect); const SkIRect srcIRect = srcRect.roundOut(); -- 2.7.4