From eae84c2e0e2126374cd488a1c8a3e18169145635 Mon Sep 17 00:00:00 2001 From: senorblanco Date: Tue, 26 Jan 2016 08:41:02 -0800 Subject: [PATCH] Image filters: fix srcOffset handling in asFragmentProcessor() path. Filters such as SkMatrixConvolutionImageFilter which use the asFragmentProcessor() path were not correctly handling srcOffset. It is correctly applied to the bounds, but the srcRect and dstRect were computed from the pre-offset bounds. The fix is to move them to just above where they're used in drawing. Note: this change adds a new test case to the imagefiltersgraph GM, so it will have to be rebaselined post-landing. BUG=skia:4855 GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1637443003 Review URL: https://codereview.chromium.org/1637443003 --- gm/imagefiltersgraph.cpp | 37 ++++++++++++++++++++++++++++++++++++- src/core/SkImageFilter.cpp | 8 +++----- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/gm/imagefiltersgraph.cpp b/gm/imagefiltersgraph.cpp index 14752db..e783789 100644 --- a/gm/imagefiltersgraph.cpp +++ b/gm/imagefiltersgraph.cpp @@ -15,6 +15,7 @@ #include "SkColorMatrixFilter.h" #include "SkImage.h" #include "SkImageSource.h" +#include "SkMatrixConvolutionImageFilter.h" #include "SkReadBuffer.h" #include "SkWriteBuffer.h" #include "SkMergeImageFilter.h" @@ -107,7 +108,7 @@ protected: return SkString("imagefiltersgraph"); } - SkISize onISize() override { return SkISize::Make(500, 150); } + SkISize onISize() override { return SkISize::Make(600, 150); } void onOnceBeforeDraw() override { fImage.reset(SkImage::NewFromBitmap( @@ -182,6 +183,40 @@ protected: canvas->translate(SkIntToScalar(100), 0); } { + // Dilate -> matrix convolution. + // This tests that a filter using asFragmentProcessor (matrix + // convolution) correctly handles a non-zero source offset + // (supplied by the dilate). + SkAutoTUnref dilate(SkDilateImageFilter::Create(5, 5)); + + SkAutoTUnref mode(SkXfermode::Create(SkXfermode::kSrcIn_Mode)); + + SkScalar kernel[9] = { + SkIntToScalar(-1), SkIntToScalar( -1 ), SkIntToScalar(-1), + SkIntToScalar(-1), SkIntToScalar( 7 ), SkIntToScalar(-1), + SkIntToScalar(-1), SkIntToScalar( -1 ), SkIntToScalar(-1), + }; + SkISize kernelSize = SkISize::Make(3, 3); + SkScalar gain = 1.0f, bias = SkIntToScalar(0); + SkIPoint kernelOffset = SkIPoint::Make(1, 1); + auto tileMode = SkMatrixConvolutionImageFilter::kClamp_TileMode; + bool convolveAlpha = false; + SkAutoTUnref convolve( + SkMatrixConvolutionImageFilter::Create(kernelSize, + kernel, + gain, + bias, + kernelOffset, + tileMode, + convolveAlpha, + dilate)); + + SkPaint paint; + paint.setImageFilter(convolve); + DrawClippedImage(canvas, fImage, paint); + canvas->translate(SkIntToScalar(100), 0); + } + { // Test that crop offsets are absolute, not relative to the parent's crop rect. SkAutoTUnref cf1(SkColorFilter::CreateModeFilter(SK_ColorBLUE, SkXfermode::kSrcIn_Mode)); diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp index 141d2e0..821edc0 100644 --- a/src/core/SkImageFilter.cpp +++ b/src/core/SkImageFilter.cpp @@ -334,8 +334,6 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Cont if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) { return false; } - SkRect srcRect = SkRect::Make(bounds); - SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); GrContext* context = srcTexture->getContext(); GrSurfaceDesc desc; @@ -349,9 +347,6 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Cont return false; } - // setup new clip - GrClip clip(dstRect); - GrFragmentProcessor* fp; offset->fX = bounds.left(); offset->fY = bounds.top(); @@ -366,6 +361,9 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Cont SkAutoTUnref drawContext(context->drawContext(dst->asRenderTarget())); if (drawContext) { + SkRect srcRect = SkRect::Make(bounds); + SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); + GrClip clip(dstRect); drawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect); GrWrapTextureInBitmap(dst, bounds.width(), bounds.height(), false, result); -- 2.7.4