Make GrRectBlurEffect be analytical rather than use a texture LUT.
The math isn't that complex and the existing code has intergralization of
the profile size that makes getting the texture coords correct tricky
(and currently wrong).
Bug: skia:9319
Change-Id: Ic928737ce4c40d28ee0696c3628e914f35ffe371
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/233985
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/effects/generated/GrRectBlurEffect.cpp b/src/gpu/effects/generated/GrRectBlurEffect.cpp
index 97daa7e..1dfd304 100644
--- a/src/gpu/effects/generated/GrRectBlurEffect.cpp
+++ b/src/gpu/effects/generated/GrRectBlurEffect.cpp
@@ -27,136 +27,102 @@
(void)rect;
auto sigma = _outer.sigma;
(void)sigma;
- highPrecision = ((((abs(rect.left()) > 16000.0 || abs(rect.top()) > 16000.0) ||
- abs(rect.right()) > 16000.0) ||
- abs(rect.bottom()) > 16000.0) ||
- abs(rect.right() - rect.left()) > 16000.0) ||
- abs(rect.bottom() - rect.top()) > 16000.0;
- rectVar =
- args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType, "rect");
- if (!highPrecision) {
- proxyRectHalfVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
- kHalf4_GrSLType, "proxyRectHalf");
+ highp = ((abs(rect.left()) > 16000.0 || abs(rect.top()) > 16000.0) ||
+ abs(rect.right()) > 16000.0) ||
+ abs(rect.bottom()) > 16000.0;
+ if (highp) {
+ rectFVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType,
+ "rectF");
}
- if (highPrecision) {
- proxyRectFloatVar = args.fUniformHandler->addUniform(
- kFragment_GrShaderFlag, kFloat4_GrSLType, "proxyRectFloat");
+ if (!highp) {
+ rectHVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
+ "rectH");
}
- profileSizeVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
- "profileSize");
+ sigmaVar =
+ args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "sigma");
fragBuilder->codeAppendf(
- "/* key */ bool highPrecision = %s;\n@if (highPrecision) {\n float2 "
- "translatedPos = sk_FragCoord.xy - %s.xy;\n float width = %s.z - %s.x;\n "
- "float height = %s.w - %s.y;\n float2 smallDims = float2(width - float(%s), "
- "height - float(%s));\n float center = float(2.0 * floor(%s / 2.0 + 0.25) - "
- "1.0);\n float2 wh = smallDims - float2(center, center);\n half hcoord = "
- "half((abs(translatedPos.x - 0.5 * width) - 0.5 * wh.x) / float(%s));\n half "
- "hlookup = sample(%s, float2(float(hcoord), 0.5)).%s",
- (highPrecision ? "true" : "false"), args.fUniformHandler->getUniformCStr(rectVar),
- args.fUniformHandler->getUniformCStr(rectVar),
- args.fUniformHandler->getUniformCStr(rectVar),
- args.fUniformHandler->getUniformCStr(rectVar),
- args.fUniformHandler->getUniformCStr(rectVar),
- args.fUniformHandler->getUniformCStr(profileSizeVar),
- args.fUniformHandler->getUniformCStr(profileSizeVar),
- args.fUniformHandler->getUniformCStr(profileSizeVar),
- args.fUniformHandler->getUniformCStr(profileSizeVar),
- fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
- fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str());
+ "/* key */ bool highp = %s;\nhalf invr = 1.0 / (2.0 * %s);\nhalf x;\n@if (highp) "
+ "{\n float lDiff = %s.x - sk_FragCoord.x;\n float rDiff = sk_FragCoord.x - "
+ "%s.z;\n x = half(max(lDiff, rDiff) * float(invr));\n} else {\n half lDiff = "
+ "half(float(%s.x) - sk_FragCoord.x);\n half rDiff = half(sk_FragCoord.x - "
+ "float(%s.z));\n x = max(lDiff, rDiff) * invr;\n}\nhalf xCoverage;\nif (x > "
+ "1.5) {\n xCoverage = 0.0;\n} else if (x < -1.5) {\n xCoverage = 1.0;\n} "
+ "else {\n half x2 = x * x;\n half",
+ (highp ? "true" : "false"), args.fUniformHandler->getUniformCStr(sigmaVar),
+ 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)");
fragBuilder->codeAppendf(
- ".w;\n half vcoord = half((abs(translatedPos.y - 0.5 * height) - 0.5 * wh.y) / "
- "float(%s));\n half vlookup = sample(%s, float2(float(vcoord), 0.5)).%s.w;\n "
- "%s = (%s * hlookup) * vlookup;\n} else {\n half2 translatedPos = "
- "half2(sk_FragCoord.xy - %s.xy);\n half width = half(%s.z - %s.x);\n half "
- "height = half(%s.w - %s.y);\n half2 smallDims = half2(width - %s, height - "
- "%s);\n half center = 2.0 * floor(%s / 2.0 + 0.25) - 1.0;\n half2 wh = "
- "smallDims - half2(center, center);\n half hco",
- args.fUniformHandler->getUniformCStr(profileSizeVar),
- fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
- fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(),
- args.fOutputColor, args.fInputColor, args.fUniformHandler->getUniformCStr(rectVar),
- args.fUniformHandler->getUniformCStr(rectVar),
- args.fUniformHandler->getUniformCStr(rectVar),
- args.fUniformHandler->getUniformCStr(rectVar),
- args.fUniformHandler->getUniformCStr(rectVar),
- args.fUniformHandler->getUniformCStr(profileSizeVar),
- args.fUniformHandler->getUniformCStr(profileSizeVar),
- args.fUniformHandler->getUniformCStr(profileSizeVar));
+ " x3 = x2 * x;\n if (x > 0.5) {\n xCoverage = 0.5625 - ((x3 / 6.0 - (3.0 "
+ "* x2) * 0.25) + 1.125 * x);\n } else if (x > -0.5) {\n xCoverage = 0.5 "
+ "- (0.75 * x - x3 / 3.0);\n } else {\n xCoverage = 0.4375 + ((-x3 / 6.0 "
+ "- (3.0 * x2) * 0.25) - 1.125 * x);\n }\n}\nhalf y;\n@if (highp) {\n float "
+ "tDiff = %s.y - sk_FragCoord.y;\n float bDiff = sk_FragCoord.y - %s.w;\n y = "
+ "half(max(tDiff, bDiff) * float(invr));\n} else {\n half tDiff = "
+ "half(float(%s.y) - sk_FragCoord.y);\n ",
+ rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
+ rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
+ rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)");
fragBuilder->codeAppendf(
- "ord = (abs(translatedPos.x - 0.5 * width) - 0.5 * wh.x) / %s;\n half hlookup = "
- "sample(%s, float2(float(hcoord), 0.5)).%s.w;\n half vcoord = "
- "(abs(translatedPos.y - 0.5 * height) - 0.5 * wh.y) / %s;\n half vlookup = "
- "sample(%s, float2(float(vcoord), 0.5)).%s.w;\n %s = (%s * hlookup) * "
- "vlookup;\n}\n",
- args.fUniformHandler->getUniformCStr(profileSizeVar),
- fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
- fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(),
- args.fUniformHandler->getUniformCStr(profileSizeVar),
- fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
- fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(),
- args.fOutputColor, args.fInputColor);
+ " half bDiff = half(sk_FragCoord.y - float(%s.w));\n y = max(tDiff, bDiff) * "
+ "invr;\n}\nhalf yCoverage;\nif (y > 1.5) {\n yCoverage = 0.0;\n} else if (y < "
+ "-1.5) {\n yCoverage = 1.0;\n} else {\n half y2 = y * y;\n half y3 = y2 * "
+ "y;\n if (y > 0.5) {\n yCoverage = 0.5625 - ((y3 / 6.0 - (3.0 * y2) * "
+ "0.25) + 1.125 * y);\n } else if (y > -0.5) {\n yCoverage = 0.5 - (0.75 "
+ "* y - y3 / 3.0);\n } else {\n yCoverage = 0.4375 + ((-y3 / 6.0 - (3.0 * "
+ "y2) * 0.25) - 1.125 * y);\n ",
+ rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)");
+ fragBuilder->codeAppendf(" }\n}\n%s = (%s * xCoverage) * yCoverage;\n", args.fOutputColor,
+ args.fInputColor);
}
private:
void onSetData(const GrGLSLProgramDataManager& pdman,
const GrFragmentProcessor& _proc) override {
const GrRectBlurEffect& _outer = _proc.cast<GrRectBlurEffect>();
- { pdman.set4fv(rectVar, 1, reinterpret_cast<const float*>(&(_outer.rect))); }
- UniformHandle& rect = rectVar;
+ { pdman.set1f(sigmaVar, (_outer.sigma)); }
+ auto rect = _outer.rect;
(void)rect;
- auto sigma = _outer.sigma;
+ UniformHandle& rectF = rectFVar;
+ (void)rectF;
+ UniformHandle& rectH = rectHVar;
+ (void)rectH;
+ UniformHandle& sigma = sigmaVar;
(void)sigma;
- GrSurfaceProxy& blurProfileProxy = *_outer.textureSampler(0).proxy();
- GrTexture& blurProfile = *blurProfileProxy.peekTexture();
- (void)blurProfile;
- UniformHandle& proxyRectHalf = proxyRectHalfVar;
- (void)proxyRectHalf;
- UniformHandle& proxyRectFloat = proxyRectFloatVar;
- (void)proxyRectFloat;
- UniformHandle& profileSize = profileSizeVar;
- (void)profileSize;
- pdman.set1f(profileSize, SkScalarCeilToScalar(6 * sigma));
+ float r[]{rect.fLeft, rect.fTop, rect.fRight, rect.fBottom};
+ pdman.set4fv(highp ? rectF : rectH, 1, r);
}
- bool highPrecision = false;
- UniformHandle proxyRectHalfVar;
- UniformHandle proxyRectFloatVar;
- UniformHandle profileSizeVar;
- UniformHandle rectVar;
+ bool highp = false;
+ UniformHandle rectFVar;
+ UniformHandle rectHVar;
+ UniformHandle sigmaVar;
};
GrGLSLFragmentProcessor* GrRectBlurEffect::onCreateGLSLInstance() const {
return new GrGLSLRectBlurEffect();
}
void GrRectBlurEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
GrProcessorKeyBuilder* b) const {
- bool highPrecision = ((((abs(rect.left()) > 16000.0 || abs(rect.top()) > 16000.0) ||
- abs(rect.right()) > 16000.0) ||
- abs(rect.bottom()) > 16000.0) ||
- abs(rect.right() - rect.left()) > 16000.0) ||
- abs(rect.bottom() - rect.top()) > 16000.0;
- b->add32((int32_t)highPrecision);
+ bool highp = ((abs(rect.left()) > 16000.0 || abs(rect.top()) > 16000.0) ||
+ abs(rect.right()) > 16000.0) ||
+ abs(rect.bottom()) > 16000.0;
+ b->add32((int32_t)highp);
}
bool GrRectBlurEffect::onIsEqual(const GrFragmentProcessor& other) const {
const GrRectBlurEffect& that = other.cast<GrRectBlurEffect>();
(void)that;
if (rect != that.rect) return false;
if (sigma != that.sigma) return false;
- if (blurProfile != that.blurProfile) return false;
return true;
}
GrRectBlurEffect::GrRectBlurEffect(const GrRectBlurEffect& src)
: INHERITED(kGrRectBlurEffect_ClassID, src.optimizationFlags())
, rect(src.rect)
- , sigma(src.sigma)
- , blurProfile(src.blurProfile) {
- this->setTextureSamplerCnt(1);
-}
+ , sigma(src.sigma) {}
std::unique_ptr<GrFragmentProcessor> GrRectBlurEffect::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect(*this));
}
-const GrFragmentProcessor::TextureSampler& GrRectBlurEffect::onTextureSampler(int index) const {
- return IthTextureSampler(index, blurProfile);
-}
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRectBlurEffect);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrRectBlurEffect::TestCreate(GrProcessorTestData* data) {