Image filters: fix srcOffset handling in asFragmentProcessor() path.
authorStephen White <senorblanco@chromium.org>
Fri, 29 Jan 2016 14:08:44 +0000 (09:08 -0500)
committerStephen White <senorblanco@chromium.org>
Fri, 29 Jan 2016 14:08:44 +0000 (09:08 -0500)
[Cherry-pick of eae84c2e0e2126374cd488a1c8a3e18169145635 to M49 branch.]

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,581389
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1637443003

NOTREECHECKS=true
NOTRY=true
NOPRESUBMIT=true
TBR=robertphillips@google.com

Review URL: https://codereview.chromium.org/1650433004 .

gm/imagefiltersgraph.cpp
src/core/SkImageFilter.cpp

index 14752dbab55738a21c19d828a1be02e15bd0ebfd..e7837891243cce6a89c782e699495f3f277dd7ab 100644 (file)
@@ -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(
@@ -181,6 +182,40 @@ protected:
             DrawClippedImage(canvas, fImage, paint);
             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<SkImageFilter> dilate(SkDilateImageFilter::Create(5, 5));
+
+            SkAutoTUnref<SkXfermode> 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<SkImageFilter> 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<SkColorFilter> cf1(SkColorFilter::CreateModeFilter(SK_ColorBLUE,
index 489a52bf8751363b7313016f92b5cc25dd7dff82..6fd098d2f7d8b42c6a3e32580450c48eb07f3a0c 100644 (file)
@@ -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<GrDrawContext> 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);