From 7938bae14af94c1d48d122a2d686e123b66411a7 Mon Sep 17 00:00:00 2001 From: "senorblanco@chromium.org" Date: Fri, 18 Oct 2013 20:08:14 +0000 Subject: Implement crop rect support for SkMatrixConvolutionImageFilter. R=bsalomon@google.com Review URL: https://codereview.chromium.org/27471002 git-svn-id: http://skia.googlecode.com/svn/trunk@11863 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/core/SkImageFilter.cpp | 6 +- src/effects/SkLightingImageFilter.cpp | 8 +- src/effects/SkMagnifierImageFilter.cpp | 2 +- src/effects/SkMatrixConvolutionImageFilter.cpp | 171 +++++++++++++++++-------- 4 files changed, 125 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp index 46d9ee4b9b..6ec982bbfb 100644 --- a/src/core/SkImageFilter.cpp +++ b/src/core/SkImageFilter.cpp @@ -106,7 +106,7 @@ bool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&, } bool SkImageFilter::canFilterImageGPU() const { - return this->asNewEffect(NULL, NULL, SkMatrix::I()); + return this->asNewEffect(NULL, NULL, SkMatrix::I(), SkIRect()); } bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, @@ -141,7 +141,7 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMa GrEffectRef* effect; SkMatrix matrix(ctm); matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top())); - this->asNewEffect(&effect, srcTexture, matrix); + this->asNewEffect(&effect, srcTexture, matrix, bounds); SkASSERT(effect); SkAutoUnref effectRef(effect); GrPaint paint; @@ -178,7 +178,7 @@ bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, return true; } -bool SkImageFilter::asNewEffect(GrEffectRef**, GrTexture*, const SkMatrix&) const { +bool SkImageFilter::asNewEffect(GrEffectRef**, GrTexture*, const SkMatrix&, const SkIRect&) const { return false; } diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp index d34bd7a5d7..f81cc1c914 100644 --- a/src/effects/SkLightingImageFilter.cpp +++ b/src/effects/SkLightingImageFilter.cpp @@ -270,7 +270,7 @@ protected: virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, SkBitmap* result, SkIPoint* offset) SK_OVERRIDE; #if SK_SUPPORT_GPU - virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkMatrix& matrix) const SK_OVERRIDE; + virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkMatrix& matrix, const SkIRect& bounds) const SK_OVERRIDE; #endif private: @@ -292,7 +292,7 @@ protected: virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, SkBitmap* result, SkIPoint* offset) SK_OVERRIDE; #if SK_SUPPORT_GPU - virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkMatrix& matrix) const SK_OVERRIDE; + virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkMatrix& matrix, const SkIRect& bounds) const SK_OVERRIDE; #endif private: @@ -957,7 +957,7 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy*, } #if SK_SUPPORT_GPU -bool SkDiffuseLightingImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkMatrix& matrix) const { +bool SkDiffuseLightingImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkMatrix& matrix, const SkIRect&) const { if (effect) { SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255)); *effect = GrDiffuseLightingEffect::Create(texture, light(), scale, matrix, kd()); @@ -1033,7 +1033,7 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy*, } #if SK_SUPPORT_GPU -bool SkSpecularLightingImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkMatrix& matrix) const { +bool SkSpecularLightingImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkMatrix& matrix, const SkIRect&) const { if (effect) { SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255)); *effect = GrSpecularLightingEffect::Create(texture, light(), scale, matrix, ks(), shininess()); diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp index bef1e8da81..d0d62c03f1 100644 --- a/src/effects/SkMagnifierImageFilter.cpp +++ b/src/effects/SkMagnifierImageFilter.cpp @@ -247,7 +247,7 @@ SkMagnifierImageFilter::SkMagnifierImageFilter(SkRect srcRect, SkScalar inset) } #if SK_SUPPORT_GPU -bool SkMagnifierImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkMatrix&) const { +bool SkMagnifierImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkMatrix&, const SkIRect&) const { if (effect) { *effect = GrMagnifierEffect::Create(texture, fSrcRect.x() / texture->width(), diff --git a/src/effects/SkMatrixConvolutionImageFilter.cpp b/src/effects/SkMatrixConvolutionImageFilter.cpp index d73f6335d7..04326c6514 100644 --- a/src/effects/SkMatrixConvolutionImageFilter.cpp +++ b/src/effects/SkMatrixConvolutionImageFilter.cpp @@ -18,11 +18,19 @@ #include "GrTBackendEffectFactory.h" #include "GrTexture.h" #include "SkMatrix.h" - #endif -SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(const SkISize& kernelSize, const SkScalar* kernel, SkScalar gain, SkScalar bias, const SkIPoint& target, TileMode tileMode, bool convolveAlpha, SkImageFilter* input) - : INHERITED(input), +SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter( + const SkISize& kernelSize, + const SkScalar* kernel, + SkScalar gain, + SkScalar bias, + const SkIPoint& target, + TileMode tileMode, + bool convolveAlpha, + SkImageFilter* input, + const CropRect* cropRect) + : INHERITED(input, cropRect), fKernelSize(kernelSize), fGain(gain), fBias(bias), @@ -37,7 +45,8 @@ SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(const SkISize& ke SkASSERT(target.fY >= 0 && target.fY < kernelSize.fHeight); } -SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { +SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(SkFlattenableReadBuffer& buffer) + : INHERITED(buffer) { fKernelSize.fWidth = buffer.readInt(); fKernelSize.fHeight = buffer.readInt(); uint32_t size = fKernelSize.fWidth * fKernelSize.fHeight; @@ -71,30 +80,30 @@ SkMatrixConvolutionImageFilter::~SkMatrixConvolutionImageFilter() { class UncheckedPixelFetcher { public: - static inline SkPMColor fetch(const SkBitmap& src, int x, int y) { + static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRect& bounds) { return *src.getAddr32(x, y); } }; class ClampPixelFetcher { public: - static inline SkPMColor fetch(const SkBitmap& src, int x, int y) { - x = SkClampMax(x, src.width() - 1); - y = SkClampMax(y, src.height() - 1); + static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRect& bounds) { + x = SkPin32(x, bounds.fLeft, bounds.fRight - 1); + y = SkPin32(y, bounds.fTop, bounds.fBottom - 1); return *src.getAddr32(x, y); } }; class RepeatPixelFetcher { public: - static inline SkPMColor fetch(const SkBitmap& src, int x, int y) { - x %= src.width(); - y %= src.height(); - if (x < 0) { - x += src.width(); + static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRect& bounds) { + x = (x - bounds.left()) % bounds.width() + bounds.left(); + y = (y - bounds.top()) % bounds.height() + bounds.top(); + if (x < bounds.left()) { + x += bounds.width(); } - if (y < 0) { - y += src.height(); + if (y < bounds.top()) { + y += bounds.height(); } return *src.getAddr32(x, y); } @@ -102,8 +111,8 @@ public: class ClampToBlackPixelFetcher { public: - static inline SkPMColor fetch(const SkBitmap& src, int x, int y) { - if (x < 0 || x >= src.width() || y < 0 || y >= src.height()) { + static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRect& bounds) { + if (x < bounds.fLeft || x >= bounds.fRight || y < bounds.fTop || y >= bounds.fBottom) { return 0; } else { return *src.getAddr32(x, y); @@ -112,14 +121,20 @@ public: }; template -void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect) { +void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, + SkBitmap* result, + const SkIRect& rect, + const SkIRect& bounds) { for (int y = rect.fTop; y < rect.fBottom; ++y) { - SkPMColor* dptr = result->getAddr32(rect.fLeft, y); + SkPMColor* dptr = result->getAddr32(rect.fLeft - bounds.fLeft, y - bounds.fTop); for (int x = rect.fLeft; x < rect.fRight; ++x) { SkScalar sumA = 0, sumR = 0, sumG = 0, sumB = 0; for (int cy = 0; cy < fKernelSize.fHeight; cy++) { for (int cx = 0; cx < fKernelSize.fWidth; cx++) { - SkPMColor s = PixelFetcher::fetch(src, x + cx - fTarget.fX, y + cy - fTarget.fY); + SkPMColor s = PixelFetcher::fetch(src, + x + cx - fTarget.fX, + y + cy - fTarget.fY, + bounds); SkScalar k = fKernel[cy * fKernelSize.fWidth + cx]; if (convolveAlpha) { sumA += SkScalarMul(SkIntToScalar(SkGetPackedA32(s)), k); @@ -136,7 +151,7 @@ void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, SkBitmap* int g = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumG, fGain) + fBias), a); int b = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumB, fGain) + fBias), a); if (!convolveAlpha) { - a = SkGetPackedA32(PixelFetcher::fetch(src, x, y)); + a = SkGetPackedA32(PixelFetcher::fetch(src, x, y, bounds)); *dptr++ = SkPreMultiplyARGB(a, r, g, b); } else { *dptr++ = SkPackARGB32(a, r, g, b); @@ -146,28 +161,37 @@ void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, SkBitmap* } template -void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect) { +void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, + SkBitmap* result, + const SkIRect& rect, + const SkIRect& bounds) { if (fConvolveAlpha) { - filterPixels(src, result, rect); + filterPixels(src, result, rect, bounds); } else { - filterPixels(src, result, rect); + filterPixels(src, result, rect, bounds); } } -void SkMatrixConvolutionImageFilter::filterInteriorPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect) { - filterPixels(src, result, rect); +void SkMatrixConvolutionImageFilter::filterInteriorPixels(const SkBitmap& src, + SkBitmap* result, + const SkIRect& rect, + const SkIRect& bounds) { + filterPixels(src, result, rect, bounds); } -void SkMatrixConvolutionImageFilter::filterBorderPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect) { +void SkMatrixConvolutionImageFilter::filterBorderPixels(const SkBitmap& src, + SkBitmap* result, + const SkIRect& rect, + const SkIRect& bounds) { switch (fTileMode) { case kClamp_TileMode: - filterPixels(src, result, rect); + filterPixels(src, result, rect, bounds); break; case kRepeat_TileMode: - filterPixels(src, result, rect); + filterPixels(src, result, rect, bounds); break; case kClampToBlack_TileMode: - filterPixels(src, result, rect); + filterPixels(src, result, rect, bounds); break; } } @@ -211,6 +235,12 @@ bool SkMatrixConvolutionImageFilter::onFilterImage(Proxy* proxy, return false; } + SkIRect bounds; + src.getBounds(&bounds); + if (!this->applyCropRect(&bounds, matrix)) { + return false; + } + if (!fConvolveAlpha && !src.isOpaque()) { src = unpremultiplyBitmap(src); } @@ -220,24 +250,27 @@ bool SkMatrixConvolutionImageFilter::onFilterImage(Proxy* proxy, return false; } - result->setConfig(src.config(), src.width(), src.height()); + result->setConfig(src.config(), bounds.width(), bounds.height()); result->allocPixels(); - SkIRect interior = SkIRect::MakeXYWH(fTarget.fX, fTarget.fY, - src.width() - fKernelSize.fWidth + 1, - src.height() - fKernelSize.fHeight + 1); - SkIRect top = SkIRect::MakeWH(src.width(), fTarget.fY); - SkIRect bottom = SkIRect::MakeLTRB(0, interior.bottom(), - src.width(), src.height()); - SkIRect left = SkIRect::MakeXYWH(0, interior.top(), - fTarget.fX, interior.height()); + SkIRect interior = SkIRect::MakeXYWH(bounds.left() + fTarget.fX, + bounds.top() + fTarget.fY, + bounds.width() - fKernelSize.fWidth + 1, + bounds.height() - fKernelSize.fHeight + 1); + SkIRect top = SkIRect::MakeLTRB(bounds.left(), bounds.top(), bounds.right(), interior.top()); + SkIRect bottom = SkIRect::MakeLTRB(bounds.left(), interior.bottom(), + bounds.right(), bounds.bottom()); + SkIRect left = SkIRect::MakeLTRB(bounds.left(), interior.top(), + interior.left(), interior.bottom()); SkIRect right = SkIRect::MakeLTRB(interior.right(), interior.top(), - src.width(), interior.bottom()); - filterBorderPixels(src, result, top); - filterBorderPixels(src, result, left); - filterInteriorPixels(src, result, interior); - filterBorderPixels(src, result, right); - filterBorderPixels(src, result, bottom); + bounds.right(), interior.bottom()); + filterBorderPixels(src, result, top, bounds); + filterBorderPixels(src, result, left, bounds); + filterInteriorPixels(src, result, interior, bounds); + filterBorderPixels(src, result, right, bounds); + filterBorderPixels(src, result, bottom, bounds); + loc->fX += bounds.fLeft; + loc->fY += bounds.fTop; return true; } @@ -251,6 +284,7 @@ class GrMatrixConvolutionEffect : public GrSingleTextureEffect { public: typedef SkMatrixConvolutionImageFilter::TileMode TileMode; static GrEffectRef* Create(GrTexture* texture, + const SkIRect& bounds, const SkISize& kernelSize, const SkScalar* kernel, SkScalar gain, @@ -259,6 +293,7 @@ public: TileMode tileMode, bool convolveAlpha) { AutoEffectUnref effect(SkNEW_ARGS(GrMatrixConvolutionEffect, (texture, + bounds, kernelSize, kernel, gain, @@ -277,6 +312,7 @@ public: } static const char* Name() { return "MatrixConvolution"; } + const SkIRect& bounds() const { return fBounds; } const SkISize& kernelSize() const { return fKernelSize; } const float* target() const { return fTarget; } const float* kernel() const { return fKernel; } @@ -291,6 +327,7 @@ public: private: GrMatrixConvolutionEffect(GrTexture*, + const SkIRect& bounds, const SkISize& kernelSize, const SkScalar* kernel, SkScalar gain, @@ -301,6 +338,7 @@ private: virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; + SkIRect fBounds; SkISize fKernelSize; float *fKernel; float fGain; @@ -337,6 +375,7 @@ private: TileMode fTileMode; bool fConvolveAlpha; + UniformHandle fBoundsUni; UniformHandle fKernelUni; UniformHandle fImageIncrementUni; UniformHandle fTargetUni; @@ -358,19 +397,20 @@ GrGLMatrixConvolutionEffect::GrGLMatrixConvolutionEffect(const GrBackendEffectFa static void appendTextureLookup(GrGLShaderBuilder* builder, const GrGLShaderBuilder::TextureSampler& sampler, const char* coord, + const char* bounds, SkMatrixConvolutionImageFilter::TileMode tileMode) { SkString clampedCoord; switch (tileMode) { case SkMatrixConvolutionImageFilter::kClamp_TileMode: - clampedCoord.printf("clamp(%s, 0.0, 1.0)", coord); + clampedCoord.printf("clamp(%s, %s.xy, %s.zw)", coord, bounds, bounds); coord = clampedCoord.c_str(); break; case SkMatrixConvolutionImageFilter::kRepeat_TileMode: - clampedCoord.printf("fract(%s)", coord); + clampedCoord.printf("mod(%s - %s.xy, %s.zw - %s.xy) + %s.xy", coord, bounds, bounds, bounds, bounds); coord = clampedCoord.c_str(); break; case SkMatrixConvolutionImageFilter::kClampToBlack_TileMode: - builder->fsCodeAppendf("clamp(%s, 0.0, 1.0) != %s ? vec4(0, 0, 0, 0) : ", coord, coord); + builder->fsCodeAppendf("clamp(%s, %s.xy, %s.zw) != %s ? vec4(0, 0, 0, 0) : ", coord, bounds, bounds, coord); break; } builder->fsAppendTextureLookup(sampler, coord); @@ -384,10 +424,14 @@ void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) { SkString coords2D = builder->ensureFSCoords2D(coords, 0); + fBoundsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, + kVec4f_GrSLType, "Bounds"); fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec2f_GrSLType, "ImageIncrement"); fKernelUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility, - kFloat_GrSLType, "Kernel", fKernelSize.width() * fKernelSize.height()); + kFloat_GrSLType, + "Kernel", + fKernelSize.width() * fKernelSize.height()); fTargetUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec2f_GrSLType, "Target"); fGainUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, @@ -395,6 +439,7 @@ void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder, fBiasUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, kFloat_GrSLType, "Bias"); + const char* bounds = builder->getUniformCStr(fBoundsUni); const char* target = builder->getUniformCStr(fTargetUni); const char* imgInc = builder->getUniformCStr(fImageIncrementUni); const char* kernel = builder->getUniformCStr(fKernelUni); @@ -410,7 +455,7 @@ void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder, builder->fsCodeAppendf("\t\t\t\tfloat k = %s[y * %d + x];\n", kernel, kWidth); builder->fsCodeAppendf("\t\t\t\tvec2 coord2 = coord + vec2(x, y) * %s;\n", imgInc); builder->fsCodeAppend("\t\t\t\tvec4 c = "); - appendTextureLookup(builder, samplers[0], "coord2", fTileMode); + appendTextureLookup(builder, samplers[0], "coord2", bounds, fTileMode); builder->fsCodeAppend(";\n"); if (!fConvolveAlpha) { builder->fsCodeAppend("\t\t\t\tc.rgb /= c.a;\n"); @@ -420,10 +465,11 @@ void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder, builder->fsCodeAppend("\t\t}\n"); if (fConvolveAlpha) { builder->fsCodeAppendf("\t\t%s = sum * %s + %s;\n", outputColor, gain, bias); - builder->fsCodeAppendf("\t\t%s.rgb = clamp(%s.rgb, 0.0, %s.a);\n", outputColor, outputColor, outputColor); + builder->fsCodeAppendf("\t\t%s.rgb = clamp(%s.rgb, 0.0, %s.a);\n", + outputColor, outputColor, outputColor); } else { builder->fsCodeAppend("\t\tvec4 c = "); - appendTextureLookup(builder, samplers[0], coords2D.c_str(), fTileMode); + appendTextureLookup(builder, samplers[0], coords2D.c_str(), bounds, fTileMode); builder->fsCodeAppend(";\n"); builder->fsCodeAppendf("\t\t%s.a = c.a;\n", outputColor); builder->fsCodeAppendf("\t\t%s.rgb = sum.rgb * %s + %s;\n", outputColor, gain, bias); @@ -468,9 +514,16 @@ void GrGLMatrixConvolutionEffect::setData(const GrGLUniformManager& uman, uman.set1fv(fKernelUni, 0, fKernelSize.width() * fKernelSize.height(), conv.kernel()); uman.set1f(fGainUni, conv.gain()); uman.set1f(fBiasUni, conv.bias()); + const SkIRect& bounds = conv.bounds(); + uman.set4f(fBoundsUni, + (float) bounds.left() / texture.width(), + (float) bounds.top() / texture.height(), + (float) bounds.right() / texture.width(), + (float) bounds.bottom() / texture.height()); } GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(GrTexture* texture, + const SkIRect& bounds, const SkISize& kernelSize, const SkScalar* kernel, SkScalar gain, @@ -479,6 +532,7 @@ GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(GrTexture* texture, TileMode tileMode, bool convolveAlpha) : INHERITED(texture, MakeDivByTextureWHMatrix(texture)), + fBounds(bounds), fKernelSize(kernelSize), fGain(SkScalarToFloat(gain)), fBias(SkScalarToFloat(bias) / 255.0f), @@ -504,7 +558,8 @@ bool GrMatrixConvolutionEffect::onIsEqual(const GrEffect& sBase) const { const GrMatrixConvolutionEffect& s = CastEffect(sBase); return this->texture(0) == s.texture(0) && fKernelSize == s.kernelSize() && - !memcmp(fKernel, s.kernel(), fKernelSize.width() * fKernelSize.height() * sizeof(float)) && + !memcmp(fKernel, s.kernel(), + fKernelSize.width() * fKernelSize.height() * sizeof(float)) && fGain == s.gain() && fBias == s.bias() && fTarget == s.target() && @@ -535,9 +590,14 @@ GrEffectRef* GrMatrixConvolutionEffect::TestCreate(SkRandom* random, SkScalar bias = random->nextSScalar1(); SkIPoint target = SkIPoint::Make(random->nextRangeU(0, kernelSize.width()), random->nextRangeU(0, kernelSize.height())); + SkIRect bounds = SkIRect::MakeXYWH(random->nextRangeU(0, textures[texIdx]->width()), + random->nextRangeU(0, textures[texIdx]->height()), + random->nextRangeU(0, textures[texIdx]->width()), + random->nextRangeU(0, textures[texIdx]->height())); TileMode tileMode = static_cast(random->nextRangeU(0, 2)); bool convolveAlpha = random->nextBool(); return GrMatrixConvolutionEffect::Create(textures[texIdx], + bounds, kernelSize, kernel.get(), gain, @@ -549,12 +609,15 @@ GrEffectRef* GrMatrixConvolutionEffect::TestCreate(SkRandom* random, bool SkMatrixConvolutionImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* texture, - const SkMatrix&) const { + const SkMatrix&, + const SkIRect& bounds + ) const { if (!effect) { return fKernelSize.width() * fKernelSize.height() <= MAX_KERNEL_SIZE; } SkASSERT(fKernelSize.width() * fKernelSize.height() <= MAX_KERNEL_SIZE); *effect = GrMatrixConvolutionEffect::Create(texture, + bounds, fKernelSize, fKernel, fGain, -- cgit v1.2.3