Revert "Allow rect and circle blur fast cases to be used with rotation matrices."
This reverts commit 2bded27a961b4d301f2d8d88829b164fa35714ef.
Reason for revert: Seems to be blocking the Chrome roll
Original change's description:
> Allow rect and circle blur fast cases to be used with rotation matrices.
>
> For circles this is trivial. The existing shader works as is.
>
> For rects this requires back projecting from device space.
>
> Adds a GM for rotated rect blurs and modifies a circle blur GM to add
> rotation.
>
> Bug: chromium:1087705
>
> Change-Id: I6b969552fbcc9f9997cfa061b3a312a5a71e8841
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/318757
> Reviewed-by: Robert Phillips <robertphillips@google.com>
> Commit-Queue: Brian Salomon <bsalomon@google.com>
TBR=bsalomon@google.com,robertphillips@google.com
Change-Id: Iafb479f3b3561e226678a3020254c6e76d4ce284
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:1087705
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/319186
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/core/SkBlurMF.cpp b/src/core/SkBlurMF.cpp
index 55581ff..177f5b2 100644
--- a/src/core/SkBlurMF.cpp
+++ b/src/core/SkBlurMF.cpp
@@ -695,6 +695,10 @@
return false;
}
+ if (!viewMatrix.isScaleTranslate()) {
+ return false;
+ }
+
// TODO: we could handle blurred stroked circles
if (!shape.style().isSimpleFill()) {
return false;
@@ -711,24 +715,24 @@
return false;
}
+ SkRRect devRRect;
+ if (!srcRRect.transform(viewMatrix, &devRRect)) {
+ return false;
+ }
+
+ if (!SkRRectPriv::AllCornersCircular(devRRect)) {
+ return false;
+ }
+
std::unique_ptr<GrFragmentProcessor> fp;
- bool canBeRect = srcRRect.isRect() && viewMatrix.preservesRightAngles();
- bool canBeCircle = SkRRectPriv::IsCircle(srcRRect) && viewMatrix.isSimilarity();
- if (canBeRect || canBeCircle) {
- if (canBeRect) {
+ if (devRRect.isRect() || SkRRectPriv::IsCircle(devRRect)) {
+ if (devRRect.isRect()) {
fp = GrRectBlurEffect::Make(
/*inputFP=*/nullptr, context, *context->priv().caps()->shaderCaps(),
- srcRRect.rect(), viewMatrix, xformedSigma);
+ devRRect.rect(), xformedSigma);
} else {
- SkPoint center = {srcRRect.getBounds().centerX(), srcRRect.getBounds().centerY()};
- viewMatrix.mapPoints(¢er, 1);
- SkScalar radius = viewMatrix.mapVector(0, srcRRect.width()/2.f).length();
- SkRect devBounds = {center.x() - radius,
- center.y() - radius,
- center.x() + radius,
- center.y() + radius};
- fp = GrCircleBlurFragmentProcessor::Make(/*inputFP=*/nullptr, context, devBounds,
+ fp = GrCircleBlurFragmentProcessor::Make(/*inputFP=*/nullptr, context, devRRect.rect(),
xformedSigma);
}
@@ -738,32 +742,20 @@
paint.setCoverageFragmentProcessor(std::move(fp));
SkRect srcProxyRect = srcRRect.rect();
- // Determine how much to outset the src rect to ensure we hit pixels within three sigma.
- SkScalar outsetX = 3.0f*xformedSigma;
- SkScalar outsetY = 3.0f*xformedSigma;
- if (viewMatrix.isScaleTranslate()) {
+ SkScalar outsetX = 3.0f*fSigma;
+ SkScalar outsetY = 3.0f*fSigma;
+ if (this->ignoreXform()) {
+ // When we're ignoring the CTM the padding added to the source rect also needs to ignore
+ // the CTM. The matrix passed in here is guaranteed to be just scale and translate so we
+ // can just grab the X and Y scales off the matrix and pre-undo the scale.
outsetX /= SkScalarAbs(viewMatrix.getScaleX());
outsetY /= SkScalarAbs(viewMatrix.getScaleY());
- } else {
- SkSize scale;
- if (!viewMatrix.decomposeScale(&scale, nullptr)) {
- return false;
- }
- outsetX /= scale.width();
- outsetY /= scale.height();
}
srcProxyRect.outset(outsetX, outsetY);
renderTargetContext->drawRect(clip, std::move(paint), GrAA::kNo, viewMatrix, srcProxyRect);
return true;
}
- if (!viewMatrix.isScaleTranslate()) {
- return false;
- }
- SkRRect devRRect;
- if (!srcRRect.transform(viewMatrix, &devRRect) || !SkRRectPriv::AllCornersCircular(devRRect)) {
- return false;
- }
fp = GrRRectBlurEffect::Make(/*inputFP=*/nullptr, context, fSigma, xformedSigma,
srcRRect, devRRect);
diff --git a/src/gpu/effects/GrRectBlurEffect.fp b/src/gpu/effects/GrRectBlurEffect.fp
index 9c8b27e..f02de9c 100644
--- a/src/gpu/effects/GrRectBlurEffect.fp
+++ b/src/gpu/effects/GrRectBlurEffect.fp
@@ -29,9 +29,6 @@
layout(when= highp) uniform float4 rectF;
layout(when=!highp) uniform half4 rectH;
-layout(key) in bool applyInvVM;
-layout(when=applyInvVM) in uniform float3x3 invVM;
-
// Effect that is a LUT for integral of normal distribution. The value at x:[0,6*sigma] is the
// integral from -inf to (3*sigma - x). I.e. x is mapped from [0, 6*sigma] to [3*sigma to -3*sigma].
// The flip saves a reversal in the shader.
@@ -46,6 +43,10 @@
kCompatibleWithCoverageAsAlpha_OptimizationFlag
}
+@constructorParams {
+ GrSamplerState samplerParams
+}
+
@samplerParams(integral) {
samplerParams
}
@@ -93,52 +94,19 @@
static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
GrRecordingContext* context,
const GrShaderCaps& caps,
- const SkRect& srcRect,
- const SkMatrix& viewMatrix,
- float transformedSigma) {
- SkASSERT(viewMatrix.preservesRightAngles());
- SkASSERT(srcRect.isSorted());
-
- SkMatrix invM;
- SkRect rect;
- if (viewMatrix.isScaleTranslate()) {
- invM = SkMatrix::I();
- // We can do everything in device space when there is no rotation.
- SkAssertResult(viewMatrix.mapRect(&rect, srcRect));
- } else {
- // The view matrix may scale, perhaps anisotropically. But we want to apply our device
- // space "transformedSigma" to the delta of frag coord from the rect edges. Factor out
- // the scaling to define a space that is purely rotation/translation from device space
- // (and scale from src space) We'll meet in the middle: pre-scale the src rect to be in
- // this space and then apply the inverse of the rotation/translation portion to the
- // frag coord.
- SkMatrix m;
- SkSize scale;
- if (!viewMatrix.decomposeScale(&scale, &m)) {
- return nullptr;
- }
- if (!m.invert(&invM)) {
- return nullptr;
- }
- rect = {srcRect.left() * scale.width(),
- srcRect.top() * scale.height(),
- srcRect.right() * scale.width(),
- srcRect.bottom() * scale.height()};
- }
-
+ const SkRect& rect, float sigma) {
+ SkASSERT(rect.isSorted());
if (!caps.floatIs32Bits()) {
// We promote the math that gets us into the Gaussian space to full float when the rect
// coords are large. If we don't have full float then fail. We could probably clip the
// rect to an outset device bounds instead.
- if (SkScalarAbs(rect.fLeft) > 16000.f ||
- SkScalarAbs(rect.fTop) > 16000.f ||
- SkScalarAbs(rect.fRight) > 16000.f ||
- SkScalarAbs(rect.fBottom) > 16000.f) {
+ if (SkScalarAbs(rect.fLeft) > 16000.f || SkScalarAbs(rect.fTop) > 16000.f ||
+ SkScalarAbs(rect.fRight) > 16000.f || SkScalarAbs(rect.fBottom) > 16000.f) {
return nullptr;
}
}
- const float sixSigma = 6 * transformedSigma;
+ const float sixSigma = 6 * sigma;
std::unique_ptr<GrFragmentProcessor> integral = MakeIntegralFP(context, sixSigma);
if (!integral) {
return nullptr;
@@ -149,32 +117,24 @@
// inset the rect so that the edge of the inset rect corresponds to t = 0 in the texture.
// It actually simplifies things a bit in the !isFast case, too.
float threeSigma = sixSigma / 2;
- SkRect insetRect = {rect.left() + threeSigma,
- rect.top() + threeSigma,
- rect.right() - threeSigma,
- rect.bottom() - threeSigma};
+ SkRect insetRect = {rect.fLeft + threeSigma,
+ rect.fTop + threeSigma,
+ rect.fRight - threeSigma,
+ rect.fBottom - threeSigma};
// In our fast variant we find the nearest horizontal and vertical edges and for each
// do a lookup in the integral texture for each and multiply them. When the rect is
// less than 6 sigma wide then things aren't so simple and we have to consider both the
// left and right edge of the rectangle (and similar in y).
bool isFast = insetRect.isSorted();
- return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect(std::move(inputFP),
- insetRect,
- !invM.isIdentity(),
- invM,
- std::move(integral),
- isFast));
+ return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect(
+ std::move(inputFP), insetRect, std::move(integral),
+ isFast, GrSamplerState::Filter::kLinear));
}
}
void main() {
half xCoverage, yCoverage;
- float2 pos = sk_FragCoord.xy;
- @if (applyInvVM) {
- // It'd be great if we could lift this to the VS.
- pos = (invVM*float3(pos,1)).xy;
- }
@if (isFast) {
// Get the smaller of the signed distance from the frag coord to the left and right
// edges and similar for y.
@@ -183,9 +143,11 @@
// extending outward 6 * sigma from the inset rect.
half2 xy;
@if (highp) {
- xy = max(half2(rectF.LT - pos), half2(pos - rectF.RB));
+ xy = max(half2(rectF.LT - sk_FragCoord.xy),
+ half2(sk_FragCoord.xy - rectF.RB));
} else {
- xy = max(half2(rectH.LT - pos), half2(pos - rectH.RB));
+ xy = max(half2(rectH.LT - sk_FragCoord.xy),
+ half2(sk_FragCoord.xy - rectH.RB));
}
xCoverage = sample(integral, half2(xy.x, 0.5)).a;
yCoverage = sample(integral, half2(xy.y, 0.5)).a;
@@ -207,11 +169,11 @@
// also factored in.
half4 rect;
@if (highp) {
- rect.LT = half2(rectF.LT - pos);
- rect.RB = half2(pos - rectF.RB);
+ rect.LT = half2(rectF.LT - sk_FragCoord.xy);
+ rect.RB = half2(sk_FragCoord.xy - rectF.RB);
} else {
- rect.LT = half2(rectH.LT - pos);
- rect.RB = half2(pos - rectH.RB);
+ rect.LT = half2(rectH.LT - sk_FragCoord.xy);
+ rect.RB = half2(sk_FragCoord.xy - rectH.RB);
}
xCoverage = 1 - sample(integral, half2(rect.L, 0.5)).a
- sample(integral, half2(rect.R, 0.5)).a;
@@ -228,13 +190,9 @@
}
@test(data) {
- float sigma = data->fRandom->nextRangeF(3, 8);
- int x = data->fRandom->nextRangeF(1, 200);
- int y = data->fRandom->nextRangeF(1, 200);
- float width = data->fRandom->nextRangeF(200, 300);
- float height = data->fRandom->nextRangeF(200, 300);
- SkMatrix vm = GrTest::TestMatrixPreservesRightAngles(data->fRandom);
- auto rect = SkRect::MakeXYWH(x, y, width, height);
+ float sigma = data->fRandom->nextRangeF(3,8);
+ float width = data->fRandom->nextRangeF(200,300);
+ float height = data->fRandom->nextRangeF(200,300);
return GrRectBlurEffect::Make(data->inputFP(), data->context(), *data->caps()->shaderCaps(),
- rect, vm, sigma);
+ SkRect::MakeWH(width, height), sigma);
}
diff --git a/src/gpu/effects/generated/GrRectBlurEffect.cpp b/src/gpu/effects/generated/GrRectBlurEffect.cpp
index 887f483..681fe79 100644
--- a/src/gpu/effects/generated/GrRectBlurEffect.cpp
+++ b/src/gpu/effects/generated/GrRectBlurEffect.cpp
@@ -26,10 +26,6 @@
(void)_outer;
auto rect = _outer.rect;
(void)rect;
- auto applyInvVM = _outer.applyInvVM;
- (void)applyInvVM;
- auto invVM = _outer.invVM;
- (void)invVM;
auto isFast = _outer.isFast;
(void)isFast;
highp = ((abs(rect.left()) > 16000.0 || abs(rect.top()) > 16000.0) ||
@@ -43,102 +39,82 @@
rectHVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
kHalf4_GrSLType, "rectH");
}
- if (applyInvVM) {
- invVMVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
- kFloat3x3_GrSLType, "invVM");
- }
fragBuilder->codeAppendf(
R"SkSL(/* key */ bool highp = %s;
half xCoverage, yCoverage;
-float2 pos = sk_FragCoord.xy;
-@if (%s) {
- pos = (%s * float3(pos, 1.0)).xy;
-}
@if (%s) {
half2 xy;
@if (highp) {
- xy = max(half2(%s.xy - pos), half2(pos - %s.zw));
+ xy = max(half2(%s.xy - sk_FragCoord.xy), half2(sk_FragCoord.xy - %s.zw));
} else {
- xy = max(half2(float2(%s.xy) - pos), half2(pos - float2(%s.zw)));
+ xy = max(half2(float2(%s.xy) - sk_FragCoord.xy), half2(sk_FragCoord.xy - float2(%s.zw)));
})SkSL",
- (highp ? "true" : "false"), (_outer.applyInvVM ? "true" : "false"),
- invVMVar.isValid() ? args.fUniformHandler->getUniformCStr(invVMVar) : "float3x3(1)",
- (_outer.isFast ? "true" : "false"),
+ (highp ? "true" : "false"), (_outer.isFast ? "true" : "false"),
rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)",
rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)");
- SkString _coords8314("float2(half2(xy.x, 0.5))");
- SkString _sample8314 = this->invokeChild(1, args, _coords8314.c_str());
+ SkString _coords6340("float2(half2(xy.x, 0.5))");
+ SkString _sample6340 = this->invokeChild(1, args, _coords6340.c_str());
fragBuilder->codeAppendf(
R"SkSL(
xCoverage = %s.w;)SkSL",
- _sample8314.c_str());
- SkString _coords8372("float2(half2(xy.y, 0.5))");
- SkString _sample8372 = this->invokeChild(1, args, _coords8372.c_str());
+ _sample6340.c_str());
+ SkString _coords6398("float2(half2(xy.y, 0.5))");
+ SkString _sample6398 = this->invokeChild(1, args, _coords6398.c_str());
fragBuilder->codeAppendf(
R"SkSL(
yCoverage = %s.w;
} else {
half4 rect;
@if (highp) {
- rect.xy = half2(%s.xy - pos);
- rect.zw = half2(pos - %s.zw);
+ rect.xy = half2(%s.xy - sk_FragCoord.xy);
+ rect.zw = half2(sk_FragCoord.xy - %s.zw);
} else {
- rect.xy = half2(float2(%s.xy) - pos);
- rect.zw = half2(pos - float2(%s.zw));
+ rect.xy = half2(float2(%s.xy) - sk_FragCoord.xy);
+ rect.zw = half2(sk_FragCoord.xy - float2(%s.zw));
})SkSL",
- _sample8372.c_str(),
+ _sample6398.c_str(),
rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)",
rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)");
- SkString _coords9691("float2(half2(rect.x, 0.5))");
- SkString _sample9691 = this->invokeChild(1, args, _coords9691.c_str());
- SkString _coords9754("float2(half2(rect.z, 0.5))");
- SkString _sample9754 = this->invokeChild(1, args, _coords9754.c_str());
+ SkString _coords7765("float2(half2(rect.x, 0.5))");
+ SkString _sample7765 = this->invokeChild(1, args, _coords7765.c_str());
+ SkString _coords7828("float2(half2(rect.z, 0.5))");
+ SkString _sample7828 = this->invokeChild(1, args, _coords7828.c_str());
fragBuilder->codeAppendf(
R"SkSL(
xCoverage = (1.0 - %s.w) - %s.w;)SkSL",
- _sample9691.c_str(), _sample9754.c_str());
- SkString _coords9818("float2(half2(rect.y, 0.5))");
- SkString _sample9818 = this->invokeChild(1, args, _coords9818.c_str());
- SkString _coords9881("float2(half2(rect.w, 0.5))");
- SkString _sample9881 = this->invokeChild(1, args, _coords9881.c_str());
+ _sample7765.c_str(), _sample7828.c_str());
+ SkString _coords7892("float2(half2(rect.y, 0.5))");
+ SkString _sample7892 = this->invokeChild(1, args, _coords7892.c_str());
+ SkString _coords7955("float2(half2(rect.w, 0.5))");
+ SkString _sample7955 = this->invokeChild(1, args, _coords7955.c_str());
fragBuilder->codeAppendf(
R"SkSL(
yCoverage = (1.0 - %s.w) - %s.w;
})SkSL",
- _sample9818.c_str(), _sample9881.c_str());
- SkString _sample9950 = this->invokeChild(0, args);
+ _sample7892.c_str(), _sample7955.c_str());
+ SkString _sample8024 = this->invokeChild(0, args);
fragBuilder->codeAppendf(
R"SkSL(
half4 inputColor = %s;
%s = (inputColor * xCoverage) * yCoverage;
)SkSL",
- _sample9950.c_str(), args.fOutputColor);
+ _sample8024.c_str(), args.fOutputColor);
}
private:
void onSetData(const GrGLSLProgramDataManager& pdman,
const GrFragmentProcessor& _proc) override {
const GrRectBlurEffect& _outer = _proc.cast<GrRectBlurEffect>();
- {
- if (invVMVar.isValid()) {
- static_assert(1 == 1);
- pdman.setSkMatrix(invVMVar, (_outer.invVM));
- }
- }
auto rect = _outer.rect;
(void)rect;
UniformHandle& rectF = rectFVar;
(void)rectF;
UniformHandle& rectH = rectHVar;
(void)rectH;
- auto applyInvVM = _outer.applyInvVM;
- (void)applyInvVM;
- UniformHandle& invVM = invVMVar;
- (void)invVM;
auto isFast = _outer.isFast;
(void)isFast;
@@ -148,7 +124,6 @@
bool highp = false;
UniformHandle rectFVar;
UniformHandle rectHVar;
- UniformHandle invVMVar;
};
GrGLSLFragmentProcessor* GrRectBlurEffect::onCreateGLSLInstance() const {
return new GrGLSLRectBlurEffect();
@@ -159,15 +134,12 @@
abs(rect.right()) > 16000.0) ||
abs(rect.bottom()) > 16000.0;
b->add32((uint32_t)highp);
- b->add32((uint32_t)applyInvVM);
b->add32((uint32_t)isFast);
}
bool GrRectBlurEffect::onIsEqual(const GrFragmentProcessor& other) const {
const GrRectBlurEffect& that = other.cast<GrRectBlurEffect>();
(void)that;
if (rect != that.rect) return false;
- if (applyInvVM != that.applyInvVM) return false;
- if (invVM != that.invVM) return false;
if (isFast != that.isFast) return false;
return true;
}
@@ -175,8 +147,6 @@
GrRectBlurEffect::GrRectBlurEffect(const GrRectBlurEffect& src)
: INHERITED(kGrRectBlurEffect_ClassID, src.optimizationFlags())
, rect(src.rect)
- , applyInvVM(src.applyInvVM)
- , invVM(src.invVM)
, isFast(src.isFast) {
this->cloneAndRegisterAllChildProcessors(src);
}
@@ -185,26 +155,17 @@
}
#if GR_TEST_UTILS
SkString GrRectBlurEffect::onDumpInfo() const {
- return SkStringPrintf(
- "(rect=float4(%f, %f, %f, %f), applyInvVM=%s, invVM=float3x3(%f, %f, %f, %f, %f, %f, "
- "%f, %f, %f), isFast=%s)",
- rect.left(), rect.top(), rect.right(), rect.bottom(), (applyInvVM ? "true" : "false"),
- invVM.rc(0, 0), invVM.rc(1, 0), invVM.rc(2, 0), invVM.rc(0, 1), invVM.rc(1, 1),
- invVM.rc(2, 1), invVM.rc(0, 2), invVM.rc(1, 2), invVM.rc(2, 2),
- (isFast ? "true" : "false"));
+ return SkStringPrintf("(rect=float4(%f, %f, %f, %f), isFast=%s)", rect.left(), rect.top(),
+ rect.right(), rect.bottom(), (isFast ? "true" : "false"));
}
#endif
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRectBlurEffect);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrRectBlurEffect::TestCreate(GrProcessorTestData* data) {
float sigma = data->fRandom->nextRangeF(3, 8);
- int x = data->fRandom->nextRangeF(1, 200);
- int y = data->fRandom->nextRangeF(1, 200);
float width = data->fRandom->nextRangeF(200, 300);
float height = data->fRandom->nextRangeF(200, 300);
- SkMatrix vm = GrTest::TestMatrixPreservesRightAngles(data->fRandom);
- auto rect = SkRect::MakeXYWH(x, y, width, height);
return GrRectBlurEffect::Make(data->inputFP(), data->context(), *data->caps()->shaderCaps(),
- rect, vm, sigma);
+ SkRect::MakeWH(width, height), sigma);
}
#endif
diff --git a/src/gpu/effects/generated/GrRectBlurEffect.h b/src/gpu/effects/generated/GrRectBlurEffect.h
index 3c480f8..b02527a 100644
--- a/src/gpu/effects/generated/GrRectBlurEffect.h
+++ b/src/gpu/effects/generated/GrRectBlurEffect.h
@@ -71,37 +71,9 @@
static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
GrRecordingContext* context,
const GrShaderCaps& caps,
- const SkRect& srcRect,
- const SkMatrix& viewMatrix,
- float transformedSigma) {
- SkASSERT(viewMatrix.preservesRightAngles());
- SkASSERT(srcRect.isSorted());
-
- SkMatrix invM;
- SkRect rect;
- if (viewMatrix.isScaleTranslate()) {
- invM = SkMatrix::I();
- // We can do everything in device space when there is no rotation.
- SkAssertResult(viewMatrix.mapRect(&rect, srcRect));
- } else {
- // The view matrix may scale, perhaps anisotropically. But we want to apply our device
- // space "transformedSigma" to the delta of frag coord from the rect edges. Factor out
- // the scaling to define a space that is purely rotation/translation from device space
- // (and scale from src space) We'll meet in the middle: pre-scale the src rect to be in
- // this space and then apply the inverse of the rotation/translation portion to the
- // frag coord.
- SkMatrix m;
- SkSize scale;
- if (!viewMatrix.decomposeScale(&scale, &m)) {
- return nullptr;
- }
- if (!m.invert(&invM)) {
- return nullptr;
- }
- rect = {srcRect.left() * scale.width(), srcRect.top() * scale.height(),
- srcRect.right() * scale.width(), srcRect.bottom() * scale.height()};
- }
-
+ const SkRect& rect,
+ float sigma) {
+ SkASSERT(rect.isSorted());
if (!caps.floatIs32Bits()) {
// We promote the math that gets us into the Gaussian space to full float when the rect
// coords are large. If we don't have full float then fail. We could probably clip the
@@ -112,7 +84,7 @@
}
}
- const float sixSigma = 6 * transformedSigma;
+ const float sixSigma = 6 * sigma;
std::unique_ptr<GrFragmentProcessor> integral = MakeIntegralFP(context, sixSigma);
if (!integral) {
return nullptr;
@@ -123,44 +95,36 @@
// inset the rect so that the edge of the inset rect corresponds to t = 0 in the texture.
// It actually simplifies things a bit in the !isFast case, too.
float threeSigma = sixSigma / 2;
- SkRect insetRect = {rect.left() + threeSigma, rect.top() + threeSigma,
- rect.right() - threeSigma, rect.bottom() - threeSigma};
+ SkRect insetRect = {rect.fLeft + threeSigma, rect.fTop + threeSigma,
+ rect.fRight - threeSigma, rect.fBottom - threeSigma};
// In our fast variant we find the nearest horizontal and vertical edges and for each
// do a lookup in the integral texture for each and multiply them. When the rect is
// less than 6 sigma wide then things aren't so simple and we have to consider both the
// left and right edge of the rectangle (and similar in y).
bool isFast = insetRect.isSorted();
- return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect(std::move(inputFP),
- insetRect,
- !invM.isIdentity(),
- invM,
- std::move(integral),
- isFast));
+ return std::unique_ptr<GrFragmentProcessor>(
+ new GrRectBlurEffect(std::move(inputFP), insetRect, std::move(integral), isFast,
+ GrSamplerState::Filter::kLinear));
}
GrRectBlurEffect(const GrRectBlurEffect& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "RectBlurEffect"; }
bool usesExplicitReturn() const override;
SkRect rect;
- bool applyInvVM;
- SkMatrix invVM;
bool isFast;
private:
GrRectBlurEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
SkRect rect,
- bool applyInvVM,
- SkMatrix invVM,
std::unique_ptr<GrFragmentProcessor> integral,
- bool isFast)
+ bool isFast,
+ GrSamplerState samplerParams)
: INHERITED(kGrRectBlurEffect_ClassID,
(OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
: kAll_OptimizationFlags) &
kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, rect(rect)
- , applyInvVM(applyInvVM)
- , invVM(invVM)
, isFast(isFast) {
this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
SkASSERT(integral);