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
This commit is contained in:
senorblanco 2015-12-17 08:10:17 -08:00 committed by Commit bot
parent 70509762c8
commit c834ab178e
2 changed files with 14 additions and 11 deletions

View File

@ -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<SkColorFilter> cf(
@ -77,6 +77,9 @@ protected:
Draw(canvas, checkerboard, rect, SkColorFilterImageFilter::Create(
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));

View File

@ -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();