aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Brian Osman <brianosman@google.com>2017-09-11 17:21:35 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-09-11 23:48:49 +0000
commita8e5744afadd20e217a7c70099a79a222d2e7e4f (patch)
tree505e42aaa9536bf6ceec0a844c2c88a955928e84
parent3261eb219f2cbb027d6876bc99b243fe0b3c7ee3 (diff)
Add general three-stop analytic gradient shader
This fixes an Android rendering bug where radial gradients were being used for "clipping" (via DstIn blend mode). The gradient stops were placed at (0, 0.999, 1), which caused our table quantization to drop the last stop. kThree_ColorType now means "0, any t, 1". The old (special-case) kThree_ColorType is now called kSymmetricThree_ColorType. Bug: skia: Change-Id: I96a0b9e679f2d537862a3e097f7e3446474914ea Reviewed-on: https://skia-review.googlesource.com/45260 Reviewed-by: Robert Phillips <robertphillips@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
-rw-r--r--gm/gradients.cpp12
-rw-r--r--src/shaders/gradients/SkGradientShader.cpp44
-rw-r--r--src/shaders/gradients/SkGradientShaderPriv.h12
3 files changed, 48 insertions, 20 deletions
diff --git a/gm/gradients.cpp b/gm/gradients.cpp
index 2a1f9031bb..08d65f7d12 100644
--- a/gm/gradients.cpp
+++ b/gm/gradients.cpp
@@ -1074,14 +1074,15 @@ DEF_SIMPLE_GM(sweep_tiling, canvas, 690, 512) {
}
// Exercises the special-case Ganesh gradient effects.
-DEF_SIMPLE_GM(gradients_interesting, canvas, 640, 1080) {
+DEF_SIMPLE_GM(gradients_interesting, canvas, 640, 1300) {
static const SkColor colors2[] = { SK_ColorRED, SK_ColorBLUE };
static const SkColor colors3[] = { SK_ColorRED, SK_ColorYELLOW, SK_ColorBLUE };
static const SkColor colors4[] = { SK_ColorRED, SK_ColorYELLOW, SK_ColorYELLOW, SK_ColorBLUE };
- static const SkScalar hardLeft[] = { 0, 0, 1 };
- static const SkScalar hardRight[] = { 0, 1, 1 };
- static const SkScalar hardCenter[] = { 0, .5f, .5f, 1 };
+ static const SkScalar softRight[] = { 0, .999f, 1 }; // Based on Android launcher "clipping"
+ static const SkScalar hardLeft[] = { 0, 0, 1 };
+ static const SkScalar hardRight[] = { 0, 1, 1 };
+ static const SkScalar hardCenter[] = { 0, .5f, .5f, 1 };
static const struct {
const SkColor* colors;
@@ -1089,7 +1090,8 @@ DEF_SIMPLE_GM(gradients_interesting, canvas, 640, 1080) {
int count;
} configs[] = {
{ colors2, nullptr, 2 }, // kTwo_ColorType
- { colors3, nullptr, 3 }, // kThree_ColorType
+ { colors3, nullptr, 3 }, // kSymmetricThree_ColorType
+ { colors3, softRight, 3 }, // kThree_ColorType
{ colors3, hardLeft, 3 }, // kHardStopLeftEdged_ColorType
{ colors3, hardRight, 3 }, // kHardStopRightEdged_ColorType
{ colors4, hardCenter, 4 }, // kSingleHardStop_ColorType
diff --git a/src/shaders/gradients/SkGradientShader.cpp b/src/shaders/gradients/SkGradientShader.cpp
index 64d3b4820a..45f25cd7f0 100644
--- a/src/shaders/gradients/SkGradientShader.cpp
+++ b/src/shaders/gradients/SkGradientShader.cpp
@@ -1312,6 +1312,7 @@ static inline int color_type_to_color_count(GrGradientEffect::ColorType colorTyp
case GrGradientEffect::kTwo_ColorType:
return 2;
case GrGradientEffect::kThree_ColorType:
+ case GrGradientEffect::kSymmetricThree_ColorType:
return 3;
case GrGradientEffect::kTexture_ColorType:
return 0;
@@ -1348,9 +1349,9 @@ GrGradientEffect::ColorType GrGradientEffect::determineColorType(
if (2 == shader.fColorCount) {
return kTwo_ColorType;
- } else if (3 == shader.fColorCount &&
- close_to_one_half(shader.getRecs()[1].fPos)) {
- return kThree_ColorType;
+ } else if (3 == shader.fColorCount) {
+ return close_to_one_half(shader.getRecs()[1].fPos) ? kSymmetricThree_ColorType
+ : kThree_ColorType;
}
return kTexture_ColorType;
@@ -1364,9 +1365,9 @@ void GrGradientEffect::GLSLProcessor::emitUniforms(GrGLSLUniformHandler* uniform
kDefault_GrSLPrecision,
"Colors",
colorCount);
- if (ge.fColorType == kSingleHardStop_ColorType) {
- fHardStopT = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType,
- kDefault_GrSLPrecision, "HardStopT");
+ if (kSingleHardStop_ColorType == ge.fColorType || kThree_ColorType == ge.fColorType) {
+ fExtraStopT = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType,
+ kDefault_GrSLPrecision, "ExtraStopT");
}
} else {
fFSYUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
@@ -1468,12 +1469,13 @@ void GrGradientEffect::GLSLProcessor::onSetData(const GrGLSLProgramDataManager&
switch (e.getColorType()) {
case GrGradientEffect::kSingleHardStop_ColorType:
- pdman.set1f(fHardStopT, e.fPositions[1]);
+ case GrGradientEffect::kThree_ColorType:
+ pdman.set1f(fExtraStopT, e.fPositions[1]);
// fall through
case GrGradientEffect::kHardStopLeftEdged_ColorType:
case GrGradientEffect::kHardStopRightEdged_ColorType:
case GrGradientEffect::kTwo_ColorType:
- case GrGradientEffect::kThree_ColorType: {
+ case GrGradientEffect::kSymmetricThree_ColorType: {
if (e.fColors4f.count() > 0) {
// Gamma-correct / color-space aware
if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
@@ -1522,6 +1524,8 @@ uint32_t GrGradientEffect::GLSLProcessor::GenBaseGradientKey(const GrProcessor&
key |= kTwoColorKey;
} else if (GrGradientEffect::kThree_ColorType == e.getColorType()) {
key |= kThreeColorKey;
+ } else if (GrGradientEffect::kSymmetricThree_ColorType == e.getColorType()) {
+ key |= kSymmetricThreeColorKey;
} else if (GrGradientEffect::kSingleHardStop_ColorType == e.getColorType()) {
key |= kHardStopCenteredKey;
} else if (GrGradientEffect::kHardStopLeftEdged_ColorType == e.getColorType()) {
@@ -1572,7 +1576,7 @@ void GrGradientEffect::GLSLProcessor::emitAnalyticalColor(GrGLSLFPFragmentBuilde
const char* colors = uniformHandler->getUniformCStr(fColorsUni);
switch (ge.getColorType()) {
case kSingleHardStop_ColorType: {
- const char* stopT = uniformHandler->getUniformCStr(fHardStopT);
+ const char* stopT = uniformHandler->getUniformCStr(fExtraStopT);
fragBuilder->codeAppend ("float4 start, end;");
fragBuilder->codeAppend ("float relative_t;");
@@ -1622,6 +1626,25 @@ void GrGradientEffect::GLSLProcessor::emitAnalyticalColor(GrGLSLFPFragmentBuilde
}
case kThree_ColorType: {
+ const char* stopT = uniformHandler->getUniformCStr(fExtraStopT);
+
+ fragBuilder->codeAppend("float4 start, end;");
+ fragBuilder->codeAppend("float relative_t;");
+ fragBuilder->codeAppendf("if (clamp_t < %s) {", stopT);
+ fragBuilder->codeAppendf(" start = %s[0];", colors);
+ fragBuilder->codeAppendf(" end = %s[1];", colors);
+ fragBuilder->codeAppendf(" relative_t = clamp_t / %s;", stopT);
+ fragBuilder->codeAppend("} else {");
+ fragBuilder->codeAppendf(" start = %s[1];", colors);
+ fragBuilder->codeAppendf(" end = %s[2];", colors);
+ fragBuilder->codeAppendf(" relative_t = (clamp_t - %s) / (1 - %s);", stopT, stopT);
+ fragBuilder->codeAppend("}");
+ fragBuilder->codeAppend("float4 colorTemp = mix(start, end, relative_t);");
+
+ break;
+ }
+
+ case kSymmetricThree_ColorType: {
fragBuilder->codeAppendf("float oneMinus2t = 1.0 - (2.0 * clamp_t);");
fragBuilder->codeAppendf("float4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s[0];",
colors);
@@ -1715,6 +1738,7 @@ GrGradientEffect::GrGradientEffect(const CreateArgs& args, bool isOpaque)
// The two and three color specializations do not currently support tiling.
case kTwo_ColorType:
case kThree_ColorType:
+ case kSymmetricThree_ColorType:
case kHardStopLeftEdged_ColorType:
case kHardStopRightEdged_ColorType:
case kSingleHardStop_ColorType:
@@ -1843,7 +1867,7 @@ bool GrGradientEffect::onIsEqual(const GrFragmentProcessor& processor) const {
return false;
}
} else {
- if (kSingleHardStop_ColorType == fColorType) {
+ if (kSingleHardStop_ColorType == fColorType || kThree_ColorType == fColorType) {
if (!SkScalarNearlyEqual(ge.fPositions[1], fPositions[1])) {
return false;
}
diff --git a/src/shaders/gradients/SkGradientShaderPriv.h b/src/shaders/gradients/SkGradientShaderPriv.h
index 97c1e842c4..fb1447ed05 100644
--- a/src/shaders/gradients/SkGradientShaderPriv.h
+++ b/src/shaders/gradients/SkGradientShaderPriv.h
@@ -388,7 +388,8 @@ public:
enum ColorType {
kTwo_ColorType,
- kThree_ColorType, // Symmetric three color
+ kThree_ColorType, // 0, t, 1
+ kSymmetricThree_ColorType,
kTexture_ColorType,
kSingleHardStop_ColorType, // 0, t, t, 1
kHardStopLeftEdged_ColorType, // 0, 0, 1
@@ -541,10 +542,11 @@ private:
// hard stop cases (neither means using texture atlas)
kTwoColorKey = 2,
kThreeColorKey = 4,
+ kSymmetricThreeColorKey = 6,
- kHardStopCenteredKey = 6,
- kHardStopZeroZeroOneKey = 8,
- kHardStopZeroOneOneKey = 10,
+ kHardStopCenteredKey = 8,
+ kHardStopZeroZeroOneKey = 10,
+ kHardStopZeroOneOneKey = 12,
// Next two bits for tile mode
kClampTileMode = 16,
@@ -557,7 +559,7 @@ private:
SkScalar fCachedYCoord;
GrGLSLProgramDataManager::UniformHandle fColorsUni;
- GrGLSLProgramDataManager::UniformHandle fHardStopT;
+ GrGLSLProgramDataManager::UniformHandle fExtraStopT;
GrGLSLProgramDataManager::UniformHandle fFSYUni;
GrGLSLColorSpaceXformHelper fColorSpaceHelper;