Relocate gradient negative fract() workaround to GLSLCodeGenerator
Change-Id: If5aba5b266f86f677b6e63b0f79792f1d3213336
Reviewed-on: https://skia-review.googlesource.com/32202
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
diff --git a/src/shaders/gradients/SkGradientShader.cpp b/src/shaders/gradients/SkGradientShader.cpp
index 186f683..767955a 100644
--- a/src/shaders/gradients/SkGradientShader.cpp
+++ b/src/shaders/gradients/SkGradientShader.cpp
@@ -1557,14 +1557,7 @@
fragBuilder->codeAppendf("float clamp_t = clamp(%s, 0.0, 1.0);", t);
break;
case SkShader::kRepeat_TileMode:
- if (shaderCaps->canUseFractForNegativeValues()) {
- fragBuilder->codeAppendf("float clamp_t = fract(%s);", t);
- } else {
- // Tegra3 fract() sometimes yields undefined results when the arg is negative.
- // TODO: relocate this workaround to GLSLCodeGenerator.
- fragBuilder->codeAppendf("float clamp_t = 0.5 - sign(%s) * (0.5 - fract(abs(%s)));",
- t, t);
- }
+ fragBuilder->codeAppendf("float clamp_t = fract(%s);", t);
break;
case SkShader::kMirror_TileMode:
fragBuilder->codeAppendf("float t_1 = %s - 1.0;", t);
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index 69d3028..64527a0 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -234,6 +234,18 @@
return;
}
}
+ if (!fProgram.fSettings.fCaps->canUseFractForNegativeValues() && c.fFunction.fName == "fract" &&
+ c.fFunction.fBuiltin) {
+ ASSERT(c.fArguments.size() == 1);
+
+ this->write("(0.5 - sign(");
+ this->writeExpression(*c.fArguments[0], kSequence_Precedence);
+ this->write(") * (0.5 - fract(abs(");
+ this->writeExpression(*c.fArguments[0], kSequence_Precedence);
+ this->write("))))");
+
+ return;
+ }
if (fProgram.fSettings.fCaps->mustForceNegatedAtanParamToFloat() &&
c.fFunction.fName == "atan" &&
c.fFunction.fBuiltin && c.fArguments.size() == 2 &&
diff --git a/src/sksl/SkSLUtil.h b/src/sksl/SkSLUtil.h
index f0951a3..dba5196 100644
--- a/src/sksl/SkSLUtil.h
+++ b/src/sksl/SkSLUtil.h
@@ -206,6 +206,13 @@
return result;
}
+ static sk_sp<GrShaderCaps> CannotUseFractForNegativeValues() {
+ sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
+ result->fVersionDeclString = "#version 400";
+ result->fCanUseFractForNegativeValues = false;
+ return result;
+ }
+
static sk_sp<GrShaderCaps> MustForceNegatedAtanParamToFloat() {
sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
result->fVersionDeclString = "#version 400";
diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp
index 80727d9..c1bf2bb 100644
--- a/tests/SkSLGLSLTest.cpp
+++ b/tests/SkSLGLSLTest.cpp
@@ -360,6 +360,29 @@
"}\n");
}
+DEF_TEST(SkSLFractNegative, r) {
+ static constexpr char input[] =
+ "void main() {"
+ "float x = -42.0;"
+ "sk_FragColor.r = fract(x);"
+ "}";
+ static constexpr char output_default[] =
+ "#version 400\n"
+ "out vec4 sk_FragColor;\n"
+ "void main() {\n"
+ " sk_FragColor.x = fract(-42.0);\n"
+ "}\n";
+ static constexpr char output_workaround[] =
+ "#version 400\n"
+ "out vec4 sk_FragColor;\n"
+ "void main() {\n"
+ " sk_FragColor.x = (0.5 - sign(-42.0) * (0.5 - fract(abs(-42.0))));\n"
+ "}\n";
+
+ test(r, input, *SkSL::ShaderCapsFactory::Default(), output_default);
+ test(r, input, *SkSL::ShaderCapsFactory::CannotUseFractForNegativeValues(), output_workaround);
+}
+
DEF_TEST(SkSLNegatedAtan, r) {
test(r,
"void main() { float2 x = float2(sqrt(2)); sk_FragColor.r = atan(x.x, -x.y); }",