diff options
author | Brian Osman <brianosman@google.com> | 2017-09-11 17:21:35 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-09-11 23:48:49 +0000 |
commit | a8e5744afadd20e217a7c70099a79a222d2e7e4f (patch) | |
tree | 505e42aaa9536bf6ceec0a844c2c88a955928e84 | |
parent | 3261eb219f2cbb027d6876bc99b243fe0b3c7ee3 (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.cpp | 12 | ||||
-rw-r--r-- | src/shaders/gradients/SkGradientShader.cpp | 44 | ||||
-rw-r--r-- | src/shaders/gradients/SkGradientShaderPriv.h | 12 |
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; |