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
This commit is contained in:
senorblanco 2016-01-26 08:41:02 -08:00 committed by Commit bot
parent 978d08a4a9
commit eae84c2e0e
2 changed files with 39 additions and 6 deletions

View 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,

View 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);