Revert of Exact Ganesh Gradients for Special Cases (patchset #9 id:160001 of https...
authorhalcanary <halcanary@google.com>
Fri, 12 Aug 2016 19:35:51 +0000 (12:35 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 12 Aug 2016 19:35:51 +0000 (12:35 -0700)
Reason for revert:
specualtive revert to fix valgrind bot
Perf-Ubuntu-GCC-ShuttleA-GPU-GTX550Ti-x86_64-Release-Valgrind

Original issue's description:
> Remove generalized gradient code
>
> BUG=skia:
> GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2223203003
>
> Committed: https://skia.googlesource.com/skia/+/0c63006b88a16e3418d92852a62771615799839d
> Committed: https://skia.googlesource.com/skia/+/99818d69372d29a139935cfe5c379e491432931b
> Committed: https://skia.googlesource.com/skia/+/2a4959181fc98d5d7ee862e7cd1c7993b3343be6

TBR=bsalomon@google.com,fmenozzi@google.com
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=skia:

Review-Url: https://codereview.chromium.org/2245533005

src/effects/gradients/SkGradientShader.cpp
src/effects/gradients/SkGradientShaderPriv.h
src/effects/gradients/SkSweepGradient.cpp

index 6b387e7..820c5b2 100644 (file)
@@ -228,6 +228,23 @@ void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const {
     desc.flatten(buffer);
 }
 
+SkGradientShaderBase::GpuColorType SkGradientShaderBase::getGpuColorType(SkColor colors[3]) const {
+    if (fColorCount <= 3) {
+        memcpy(colors, fOrigColors, fColorCount * sizeof(SkColor));
+    }
+
+    if (SkShader::kClamp_TileMode == fTileMode) {
+        if (2 == fColorCount) {
+            return kTwo_GpuColorType;
+        } else if (3 == fColorCount &&
+                   (SkScalarAbs(
+                    SkFixedToScalar(fRecs[1].fPos) - SK_ScalarHalf) < SK_Scalar1 / 1000)) {
+            return kThree_GpuColorType;
+        }
+    }
+    return kTexture_GpuColorType;
+}
+
 void SkGradientShaderBase::FlipGradientColors(SkColor* colorDst, Rec* recDst,
                                               SkColor* colorSrc, Rec* recSrc,
                                               int count) {
@@ -894,190 +911,113 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
 #include "glsl/GrGLSLUniformHandler.h"
 #include "SkGr.h"
 
-static inline bool close_to_one_half(const SkFixed& val) {
-    return SkScalarNearlyEqual(SkFixedToScalar(val), SK_ScalarHalf);
-}
-
-static inline int color_type_to_color_count(GrGradientEffect::ColorType colorType) {
-    switch (colorType) {
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
-        case GrGradientEffect::kHardStopCentered_ColorType:
-            return 4;
-        case GrGradientEffect::kHardStopLeftEdged_ColorType:
-        case GrGradientEffect::kHardStopRightEdged_ColorType:
-            return 3;
-#endif
-        case GrGradientEffect::kTwo_ColorType:
-            return 2;
-        case GrGradientEffect::kThree_ColorType:
-            return 3;
-        case GrGradientEffect::kTexture_ColorType:
-            return 0;
-    }
-
-    SkDEBUGFAIL("Unhandled ColorType in color_type_to_color_count()");
-    return -1;
-}
-
-GrGradientEffect::ColorType GrGradientEffect::determineColorType(
-        const SkGradientShaderBase& shader) {
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
-    if (shader.fOrigPos) {
-        if (4 == shader.fColorCount) {
-            if (SkScalarNearlyEqual(shader.fOrigPos[0], 0.0f) &&
-                SkScalarNearlyEqual(shader.fOrigPos[1], 0.5f) &&
-                SkScalarNearlyEqual(shader.fOrigPos[2], 0.5f) &&
-                SkScalarNearlyEqual(shader.fOrigPos[3], 1.0f)) {
-
-                return kHardStopCentered_ColorType;
-            }
-        } else if (3 == shader.fColorCount) {
-            if (SkScalarNearlyEqual(shader.fOrigPos[0], 0.0f) &&
-                SkScalarNearlyEqual(shader.fOrigPos[1], 0.0f) &&
-                SkScalarNearlyEqual(shader.fOrigPos[2], 1.0f)) {
-
-                return kHardStopLeftEdged_ColorType;
-            } else if (SkScalarNearlyEqual(shader.fOrigPos[0], 0.0f) &&
-                       SkScalarNearlyEqual(shader.fOrigPos[1], 1.0f) &&
-                       SkScalarNearlyEqual(shader.fOrigPos[2], 1.0f)) {
-                
-                return kHardStopRightEdged_ColorType;
-            }
-        }
-    }
-#endif
-
-    if (SkShader::kClamp_TileMode == shader.getTileMode()) {
-        if (2 == shader.fColorCount) {
-            return kTwo_ColorType;
-        } else if (3 == shader.fColorCount &&
-                   close_to_one_half(shader.getRecs()[1].fPos)) {
-            return kThree_ColorType;
-        }
-    }
-
-    return kTexture_ColorType;
+GrGradientEffect::GLSLProcessor::GLSLProcessor()
+    : fCachedYCoord(SK_ScalarMax) {
 }
 
 void GrGradientEffect::GLSLProcessor::emitUniforms(GrGLSLUniformHandler* uniformHandler,
                                                    const GrGradientEffect& ge) {
-    if (int colorCount = color_type_to_color_count(ge.getColorType())) {
-        fColorsUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag,
-                                                     kVec4f_GrSLType,
-                                                     kDefault_GrSLPrecision,
-                                                     "Colors",
-                                                     colorCount);
-    } else {
+
+    if (SkGradientShaderBase::kTwo_GpuColorType == ge.getColorType()) { // 2 Color case
+        fColorStartUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
+                                                    kVec4f_GrSLType, kDefault_GrSLPrecision,
+                                                    "GradientStartColor");
+        fColorEndUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
+                                                  kVec4f_GrSLType, kDefault_GrSLPrecision,
+                                                  "GradientEndColor");
+
+    } else if (SkGradientShaderBase::kThree_GpuColorType == ge.getColorType()) { // 3 Color Case
+        fColorStartUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
+                                                    kVec4f_GrSLType,  kDefault_GrSLPrecision,
+                                                    "GradientStartColor");
+        fColorMidUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
+                                                  kVec4f_GrSLType, kDefault_GrSLPrecision,
+                                                  "GradientMidColor");
+        fColorEndUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
+                                                  kVec4f_GrSLType, kDefault_GrSLPrecision,
+                                                  "GradientEndColor");
+
+    } else { // if not a fast case
         fFSYUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                              kFloat_GrSLType, kDefault_GrSLPrecision,
                                              "GradientYCoordFS");
     }
 }
 
-static inline void set_after_interp_color_uni_array(const GrGLSLProgramDataManager& pdman,
-                                       const GrGLSLProgramDataManager::UniformHandle uni,
-                                       const SkTDArray<SkColor>& colors) {
-    int count = colors.count();
-    constexpr int kSmallCount = 10;
-
-    SkAutoSTArray<4*kSmallCount, float> vals(4*count);
-
-    for (int i = 0; i < colors.count(); i++) {
-        // RGBA
-        vals[4*i + 0] = SkColorGetR(colors[i]) / 255.f;
-        vals[4*i + 1] = SkColorGetG(colors[i]) / 255.f;
-        vals[4*i + 2] = SkColorGetB(colors[i]) / 255.f;
-        vals[4*i + 3] = SkColorGetA(colors[i]) / 255.f;
-    }
-
-    pdman.set4fv(uni, colors.count(), vals.get());
+static inline void set_color_uni(const GrGLSLProgramDataManager& pdman,
+                                 const GrGLSLProgramDataManager::UniformHandle uni,
+                                 const SkColor* color) {
+       pdman.set4f(uni,
+                   SkColorGetR(*color) / 255.f,
+                   SkColorGetG(*color) / 255.f,
+                   SkColorGetB(*color) / 255.f,
+                   SkColorGetA(*color) / 255.f);
 }
 
-static inline void set_before_interp_color_uni_array(const GrGLSLProgramDataManager& pdman,
-                                              const GrGLSLProgramDataManager::UniformHandle uni,
-                                              const SkTDArray<SkColor>& colors) {
-    int count = colors.count();
-    constexpr int kSmallCount = 10;
-
-    SkAutoSTArray<4*kSmallCount, float> vals(4*count);
-
-    for (int i = 0; i < count; i++) {
-        float a = SkColorGetA(colors[i]) / 255.f;
-        float aDiv255 = a / 255.f;
-
-        // RGBA
-        vals[4*i + 0] = SkColorGetR(colors[i]) * aDiv255;
-        vals[4*i + 1] = SkColorGetG(colors[i]) * aDiv255;
-        vals[4*i + 2] = SkColorGetB(colors[i]) * aDiv255;
-        vals[4*i + 3] = a;
-    }
-
-    pdman.set4fv(uni, count, vals.get());
+static inline void set_mul_color_uni(const GrGLSLProgramDataManager& pdman,
+                                     const GrGLSLProgramDataManager::UniformHandle uni,
+                                     const SkColor* color){
+       float a = SkColorGetA(*color) / 255.f;
+       float aDiv255 = a / 255.f;
+       pdman.set4f(uni,
+                   SkColorGetR(*color) * aDiv255,
+                   SkColorGetG(*color) * aDiv255,
+                   SkColorGetB(*color) * aDiv255,
+                   a);
 }
 
 void GrGradientEffect::GLSLProcessor::onSetData(const GrGLSLProgramDataManager& pdman,
                                                 const GrProcessor& processor) {
+
     const GrGradientEffect& e = processor.cast<GrGradientEffect>();
 
-    switch (e.getColorType()) {
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
-        case GrGradientEffect::kHardStopCentered_ColorType:
-        case GrGradientEffect::kHardStopLeftEdged_ColorType:
-        case GrGradientEffect::kHardStopRightEdged_ColorType:
-#endif
-        case GrGradientEffect::kTwo_ColorType:
-        case GrGradientEffect::kThree_ColorType: {
-            if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
-                set_before_interp_color_uni_array(pdman, fColorsUni, e.fColors);
-            } else {
-                set_after_interp_color_uni_array(pdman, fColorsUni, e.fColors);
-            }
 
-            break;
+    if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()){
+
+        if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
+            set_mul_color_uni(pdman, fColorStartUni, e.getColors(0));
+            set_mul_color_uni(pdman, fColorEndUni,   e.getColors(1));
+        } else {
+            set_color_uni(pdman, fColorStartUni, e.getColors(0));
+            set_color_uni(pdman, fColorEndUni,   e.getColors(1));
         }
 
-        case GrGradientEffect::kTexture_ColorType: {
-            SkScalar yCoord = e.getYCoord();
-            if (yCoord != fCachedYCoord) {
-                pdman.set1f(fFSYUni, yCoord);
-                fCachedYCoord = yCoord;
-            }
-            break;
+    } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()){
+
+        if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
+            set_mul_color_uni(pdman, fColorStartUni, e.getColors(0));
+            set_mul_color_uni(pdman, fColorMidUni,   e.getColors(1));
+            set_mul_color_uni(pdman, fColorEndUni,   e.getColors(2));
+        } else {
+            set_color_uni(pdman, fColorStartUni, e.getColors(0));
+            set_color_uni(pdman, fColorMidUni,   e.getColors(1));
+            set_color_uni(pdman, fColorEndUni,   e.getColors(2));
+        }
+    } else {
+
+        SkScalar yCoord = e.getYCoord();
+        if (yCoord != fCachedYCoord) {
+            pdman.set1f(fFSYUni, yCoord);
+            fCachedYCoord = yCoord;
         }
     }
 }
 
+
 uint32_t GrGradientEffect::GLSLProcessor::GenBaseGradientKey(const GrProcessor& processor) {
     const GrGradientEffect& e = processor.cast<GrGradientEffect>();
 
     uint32_t key = 0;
 
-    if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
-        key |= kPremulBeforeInterpKey;
-    }
-
-    if (GrGradientEffect::kTwo_ColorType == e.getColorType()) {
+    if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()) {
         key |= kTwoColorKey;
-    } else if (GrGradientEffect::kThree_ColorType == e.getColorType()) {
+    } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()) {
         key |= kThreeColorKey;
     }
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
-    else if (GrGradientEffect::kHardStopCentered_ColorType == e.getColorType()) {
-        key |= kHardStopCenteredKey;
-    } else if (GrGradientEffect::kHardStopLeftEdged_ColorType == e.getColorType()) {
-        key |= kHardStopZeroZeroOneKey;
-    } else if (GrGradientEffect::kHardStopRightEdged_ColorType == e.getColorType()) {
-        key |= kHardStopZeroOneOneKey;
-    }
-   
-    if (SkShader::TileMode::kClamp_TileMode == e.fTileMode) {
-        key |= kClampTileMode;
-    } else if (SkShader::TileMode::kRepeat_TileMode == e.fTileMode) {
-        key |= kRepeatTileMode;
-    } else {
-        key |= kMirrorTileMode;
+
+    if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
+        key |= kPremulBeforeInterpKey;
     }
-#endif
 
     return key;
 }
@@ -1090,183 +1030,56 @@ void GrGradientEffect::GLSLProcessor::emitColor(GrGLSLFPFragmentBuilder* fragBui
                                                 const char* outputColor,
                                                 const char* inputColor,
                                                 const SamplerHandle* texSamplers) {
-    switch (ge.getColorType()) {
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
-        case kHardStopCentered_ColorType: {
-            const char* t      = gradientTValue;
-            const char* colors = uniformHandler->getUniformCStr(fColorsUni);
-
-            fragBuilder->codeAppendf("float clamp_t = clamp(%s, 0.0, 1.0);", t);
-
-            // Account for tile mode
-            if (SkShader::kRepeat_TileMode == ge.fTileMode) {
-                fragBuilder->codeAppendf("clamp_t = fract(%s);", t);
-            } else if (SkShader::kMirror_TileMode == ge.fTileMode) {
-                fragBuilder->codeAppendf("if (%s < 0.0 || %s > 1.0) {", t, t);
-                fragBuilder->codeAppendf("    if (mod(floor(%s), 2.0) == 0.0) {", t);
-                fragBuilder->codeAppendf("        clamp_t = fract(%s);", t);
-                fragBuilder->codeAppendf("    } else {");
-                fragBuilder->codeAppendf("        clamp_t = 1.0 - fract(%s);", t);
-                fragBuilder->codeAppendf("    }");
-                fragBuilder->codeAppendf("}");
-            }
-
-            // Calculate color
-            fragBuilder->codeAppendf("float relative_t = fract(2.0 * clamp_t);");
-            if (SkShader::kClamp_TileMode == ge.fTileMode) {
-                fragBuilder->codeAppendf("relative_t += step(1.0, %s);", t);
-            }
-            fragBuilder->codeAppendf("vec4 colorTemp = mix(%s[0], %s[1], relative_t);", colors,
-                                     colors);
-            fragBuilder->codeAppendf("if (clamp_t >= 0.5) {");
-            fragBuilder->codeAppendf("    colorTemp = mix(%s[2], %s[3], relative_t);", colors,
-                                     colors);
-            fragBuilder->codeAppendf("}");
-
-            if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) {
-                fragBuilder->codeAppend("colorTemp.rgb *= colorTemp.a;");
-            }
-            fragBuilder->codeAppendf("%s = %s;", outputColor,
-                                     (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
-
-            break;
+    if (SkGradientShaderBase::kTwo_GpuColorType == ge.getColorType()){
+        fragBuilder->codeAppendf("\tvec4 colorTemp = mix(%s, %s, clamp(%s, 0.0, 1.0));\n",
+                                 uniformHandler->getUniformVariable(fColorStartUni).c_str(),
+                                 uniformHandler->getUniformVariable(fColorEndUni).c_str(),
+                                 gradientTValue);
+        // Note that we could skip this step if both colors are known to be opaque. Two
+        // considerations:
+        // The gradient SkShader reporting opaque is more restrictive than necessary in the two pt
+        // case. Make sure the key reflects this optimization (and note that it can use the same
+        // shader as thekBeforeIterp case). This same optimization applies to the 3 color case
+        // below.
+        if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) {
+            fragBuilder->codeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
         }
 
-        case kHardStopLeftEdged_ColorType: {
-            const char* t      = gradientTValue;
-            const char* colors = uniformHandler->getUniformCStr(fColorsUni);
-
-            fragBuilder->codeAppendf("float clamp_t = clamp(%s, 0.0, 1.0);", t);
-
-            // Account for tile mode
-            if (SkShader::kRepeat_TileMode == ge.fTileMode) {
-                fragBuilder->codeAppendf("clamp_t = fract(%s);", t);
-            } else if (SkShader::kMirror_TileMode == ge.fTileMode) {
-                fragBuilder->codeAppendf("if (%s < 0.0 || %s > 1.0) {", t, t);
-                fragBuilder->codeAppendf("    if (mod(floor(%s), 2.0) == 0.0) {", t);
-                fragBuilder->codeAppendf("        clamp_t = fract(%s);", t);
-                fragBuilder->codeAppendf("    } else {");
-                fragBuilder->codeAppendf("        clamp_t = 1.0 - fract(%s);", t);
-                fragBuilder->codeAppendf("    }");
-                fragBuilder->codeAppendf("}");
-            }
-
-            fragBuilder->codeAppendf("vec4 colorTemp = mix(%s[1], %s[2], clamp_t);", colors,
-                                     colors);
-            if (SkShader::kClamp_TileMode == ge.fTileMode) {
-                fragBuilder->codeAppendf("if (%s < 0.0) {", t);
-                fragBuilder->codeAppendf("    colorTemp = %s[0];", colors);
-                fragBuilder->codeAppendf("}");
-            }
-
-            if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) {
-                fragBuilder->codeAppend("colorTemp.rgb *= colorTemp.a;");
-            }
-            fragBuilder->codeAppendf("%s = %s;", outputColor,
-                                     (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
-
-            break;
-        }
-
-        case kHardStopRightEdged_ColorType: {
-            const char* t      = gradientTValue;
-            const char* colors = uniformHandler->getUniformCStr(fColorsUni);
-
-            fragBuilder->codeAppendf("float clamp_t = clamp(%s, 0.0, 1.0);", t);
-
-            // Account for tile mode
-            if (SkShader::kRepeat_TileMode == ge.fTileMode) {
-                fragBuilder->codeAppendf("clamp_t = fract(%s);", t);
-            } else if (SkShader::kMirror_TileMode == ge.fTileMode) {
-                fragBuilder->codeAppendf("if (%s < 0.0 || %s > 1.0) {", t, t);
-                fragBuilder->codeAppendf("    if (mod(floor(%s), 2.0) == 0.0) {", t);
-                fragBuilder->codeAppendf("        clamp_t = fract(%s);", t);
-                fragBuilder->codeAppendf("    } else {");
-                fragBuilder->codeAppendf("        clamp_t = 1.0 - fract(%s);", t);
-                fragBuilder->codeAppendf("    }");
-                fragBuilder->codeAppendf("}");
-            }
-
-            fragBuilder->codeAppendf("vec4 colorTemp = mix(%s[0], %s[1], clamp_t);", colors,
-                                     colors);
-            if (SkShader::kClamp_TileMode == ge.fTileMode) {
-                fragBuilder->codeAppendf("if (%s > 1.0) {", t);
-                fragBuilder->codeAppendf("    colorTemp = %s[2];", colors);
-                fragBuilder->codeAppendf("}");
-            }
-
-            if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) {
-                fragBuilder->codeAppend("colorTemp.rgb *= colorTemp.a;");
-            }
-            fragBuilder->codeAppendf("%s = %s;", outputColor,
-                                     (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
-
-            break;
-        }
-#endif
-
-        case kTwo_ColorType: {
-            const char* t      = gradientTValue;
-            const char* colors = uniformHandler->getUniformCStr(fColorsUni);
-
-            fragBuilder->codeAppendf("vec4 colorTemp = mix(%s[0], %s[1], clamp(%s, 0.0, 1.0));",
-                                     colors, colors, t);
-
-            // We could skip this step if both colors are known to be opaque. Two
-            // considerations:
-            // The gradient SkShader reporting opaque is more restrictive than necessary in the two
-            // pt case. Make sure the key reflects this optimization (and note that it can use the
-            // same shader as thekBeforeIterp case). This same optimization applies to the 3 color
-            // case below.
-            if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) {
-                fragBuilder->codeAppend("colorTemp.rgb *= colorTemp.a;");
-            }
-
-            fragBuilder->codeAppendf("%s = %s;", outputColor,
-                                     (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
-
-            break;
+        fragBuilder->codeAppendf("\t%s = %s;\n", outputColor,
+                                 (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
+    } else if (SkGradientShaderBase::kThree_GpuColorType == ge.getColorType()) {
+        fragBuilder->codeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n",
+                                 gradientTValue);
+        fragBuilder->codeAppendf("\tvec4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s;\n",
+                                 uniformHandler->getUniformVariable(fColorStartUni).c_str());
+        if (!glslCaps->canUseMinAndAbsTogether()) {
+            // The Tegra3 compiler will sometimes never return if we have
+            // min(abs(oneMinus2t), 1.0), or do the abs first in a separate expression.
+            fragBuilder->codeAppend("\tfloat minAbs = abs(oneMinus2t);\n");
+            fragBuilder->codeAppend("\tminAbs = minAbs > 1.0 ? 1.0 : minAbs;\n");
+            fragBuilder->codeAppendf("\tcolorTemp += (1.0 - minAbs) * %s;\n",
+                                     uniformHandler->getUniformVariable(fColorMidUni).c_str());
+        } else {
+            fragBuilder->codeAppendf("\tcolorTemp += (1.0 - min(abs(oneMinus2t), 1.0)) * %s;\n",
+                                     uniformHandler->getUniformVariable(fColorMidUni).c_str());
         }
-
-        case kThree_ColorType: {
-            const char* t      = gradientTValue;
-            const char* colors = uniformHandler->getUniformCStr(fColorsUni);
-
-            fragBuilder->codeAppendf("float oneMinus2t = 1.0 - (2.0 * %s);", t);
-            fragBuilder->codeAppendf("vec4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s[0];",
-                                     colors);
-            if (!glslCaps->canUseMinAndAbsTogether()) {
-                // The Tegra3 compiler will sometimes never return if we have
-                // min(abs(oneMinus2t), 1.0), or do the abs first in a separate expression.
-                fragBuilder->codeAppendf("float minAbs = abs(oneMinus2t);");
-                fragBuilder->codeAppendf("minAbs = minAbs > 1.0 ? 1.0 : minAbs;");
-                fragBuilder->codeAppendf("colorTemp += (1.0 - minAbs) * %s[1];", colors);
-            } else {
-                fragBuilder->codeAppendf("colorTemp += (1.0 - min(abs(oneMinus2t), 1.0)) * %s[1];",
-                                         colors);
-            }
-            fragBuilder->codeAppendf("colorTemp += clamp(-oneMinus2t, 0.0, 1.0) * %s[2];", colors);
-
-            if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) {
-                fragBuilder->codeAppend("colorTemp.rgb *= colorTemp.a;");
-            }
-
-            fragBuilder->codeAppendf("%s = %s;", outputColor,
-                                     (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
-
-            break;
+        fragBuilder->codeAppendf("\tcolorTemp += clamp(-oneMinus2t, 0.0, 1.0) * %s;\n",
+                                 uniformHandler->getUniformVariable(fColorEndUni).c_str());
+        if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) {
+            fragBuilder->codeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
         }
 
-        case kTexture_ColorType: {
-            const char* fsyuni = uniformHandler->getUniformCStr(fFSYUni);
-
-            fragBuilder->codeAppendf("vec2 coord = vec2(%s, %s);", gradientTValue, fsyuni);
-            fragBuilder->codeAppendf("%s = ", outputColor);
-            fragBuilder->appendTextureLookupAndModulate(inputColor, texSamplers[0], "coord");
-            fragBuilder->codeAppend(";");
-
-            break;
-        }
+        fragBuilder->codeAppendf("\t%s = %s;\n", outputColor,
+                                 (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
+    } else {
+        fragBuilder->codeAppendf("\tvec2 coord = vec2(%s, %s);\n",
+                                 gradientTValue,
+                                 uniformHandler->getUniformVariable(fFSYUni).c_str());
+        fragBuilder->codeAppendf("\t%s = ", outputColor);
+        fragBuilder->appendTextureLookupAndModulate(inputColor,
+                                                    texSamplers[0],
+                                                    "coord");
+        fragBuilder->codeAppend(";\n");
     }
 }
 
@@ -1279,87 +1092,56 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx,
 
     fIsOpaque = shader.isOpaque();
 
-    fColorType = this->determineColorType(shader);
-
-    if (kTexture_ColorType != fColorType) {
-        if (shader.fOrigColors) {
-            fColors = SkTDArray<SkColor>(shader.fOrigColors, shader.fColorCount);
-        }
-
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
-        if (shader.fOrigPos) {
-            fPositions = SkTDArray<SkScalar>(shader.fOrigPos, shader.fColorCount);
-        }
+    fColorType = shader.getGpuColorType(&fColors[0]);
 
-        fTileMode = tileMode;
-#endif
-    }
+    // The two and three color specializations do not currently support tiling.
+    if (SkGradientShaderBase::kTwo_GpuColorType == fColorType ||
+        SkGradientShaderBase::kThree_GpuColorType == fColorType) {
+        fRow = -1;
 
-    switch (fColorType) {
-        // The two and three color specializations do not currently support tiling.
-        case kTwo_ColorType:
-        case kThree_ColorType:
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
-        case kHardStopLeftEdged_ColorType:
-        case kHardStopRightEdged_ColorType:
-        case kHardStopCentered_ColorType:
-#endif
-            fRow = -1;
-
-            if (SkGradientShader::kInterpolateColorsInPremul_Flag & shader.getGradFlags()) {
-                fPremulType = kBeforeInterp_PremulType;
-            } else {
-                fPremulType = kAfterInterp_PremulType;
-            }
-
-            fCoordTransform.reset(kCoordSet, matrix);
-
-            break;
-        case kTexture_ColorType:
-            // doesn't matter how this is set, just be consistent because it is part of the
-            // effect key.
+        if (SkGradientShader::kInterpolateColorsInPremul_Flag & shader.getGradFlags()) {
             fPremulType = kBeforeInterp_PremulType;
-
-            SkBitmap bitmap;
-            shader.getGradientTableBitmap(&bitmap);
-
-            GrTextureStripAtlas::Desc desc;
-            desc.fWidth  = bitmap.width();
-            desc.fHeight = 32;
-            desc.fRowHeight = bitmap.height();
-            desc.fContext = ctx;
-            desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.info(), *ctx->caps());
-            fAtlas = GrTextureStripAtlas::GetAtlas(desc);
-            SkASSERT(fAtlas);
-
-            // We always filter the gradient table. Each table is one row of a texture, always
-            // y-clamp.
-            GrTextureParams params;
-            params.setFilterMode(GrTextureParams::kBilerp_FilterMode);
-            params.setTileModeX(tileMode);
-
-            fRow = fAtlas->lockRow(bitmap);
-            if (-1 != fRow) {
-                fYCoord = fAtlas->getYOffset(fRow)+SK_ScalarHalf*fAtlas->getNormalizedTexelHeight();
-                fCoordTransform.reset(kCoordSet, matrix, fAtlas->getTexture(), params.filterMode());
-                fTextureAccess.reset(fAtlas->getTexture(), params);
-            } else {
-                SkAutoTUnref<GrTexture> texture(
-                    GrRefCachedBitmapTexture(ctx, bitmap, params,
-                                             SkSourceGammaTreatment::kRespect));
-                if (!texture) {
-                    return;
-                }
-                fCoordTransform.reset(kCoordSet, matrix, texture, params.filterMode());
-                fTextureAccess.reset(texture, params);
-                fYCoord = SK_ScalarHalf;
+        } else {
+            fPremulType = kAfterInterp_PremulType;
+        }
+        fCoordTransform.reset(kCoordSet, matrix);
+    } else {
+        // doesn't matter how this is set, just be consistent because it is part of the effect key.
+        fPremulType = kBeforeInterp_PremulType;
+        SkBitmap bitmap;
+        shader.getGradientTableBitmap(&bitmap);
+
+        GrTextureStripAtlas::Desc desc;
+        desc.fWidth  = bitmap.width();
+        desc.fHeight = 32;
+        desc.fRowHeight = bitmap.height();
+        desc.fContext = ctx;
+        desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.info(), *ctx->caps());
+        fAtlas = GrTextureStripAtlas::GetAtlas(desc);
+        SkASSERT(fAtlas);
+
+        // We always filter the gradient table. Each table is one row of a texture, always y-clamp.
+        GrTextureParams params;
+        params.setFilterMode(GrTextureParams::kBilerp_FilterMode);
+        params.setTileModeX(tileMode);
+
+        fRow = fAtlas->lockRow(bitmap);
+        if (-1 != fRow) {
+            fYCoord = fAtlas->getYOffset(fRow) + SK_ScalarHalf * fAtlas->getNormalizedTexelHeight();
+            fCoordTransform.reset(kCoordSet, matrix, fAtlas->getTexture(), params.filterMode());
+            fTextureAccess.reset(fAtlas->getTexture(), params);
+        } else {
+            SkAutoTUnref<GrTexture> texture(
+                GrRefCachedBitmapTexture(ctx, bitmap, params, SkSourceGammaTreatment::kRespect));
+            if (!texture) {
+                return;
             }
-
-            this->addTextureAccess(&fTextureAccess);
-
-            break;
+            fCoordTransform.reset(kCoordSet, matrix, texture, params.filterMode());
+            fTextureAccess.reset(texture, params);
+            fYCoord = SK_ScalarHalf;
+        }
+        this->addTextureAccess(&fTextureAccess);
     }
-
     this->addCoordTransform(&fCoordTransform);
 }
 
@@ -1370,27 +1152,30 @@ GrGradientEffect::~GrGradientEffect() {
 }
 
 bool GrGradientEffect::onIsEqual(const GrFragmentProcessor& processor) const {
-    const GrGradientEffect& ge = processor.cast<GrGradientEffect>();
+    const GrGradientEffect& s = processor.cast<GrGradientEffect>();
+
+    if (this->fColorType == s.getColorType()){
 
-    if (this->fColorType == ge.getColorType()) {
-        if (kTexture_ColorType == fColorType) {
-            if (fYCoord != ge.getYCoord()) {
+        if (SkGradientShaderBase::kTwo_GpuColorType == fColorType) {
+            if (this->getPremulType() != s.getPremulType() ||
+                *this->getColors(0) != *s.getColors(0) ||
+                *this->getColors(1) != *s.getColors(1)) {
                 return false;
             }
-        } else {
-            if (this->getPremulType() != ge.getPremulType() ||
-                this->fColors.count() != ge.fColors.count()) {
+        } else if (SkGradientShaderBase::kThree_GpuColorType == fColorType) {
+            if (this->getPremulType() != s.getPremulType() ||
+                *this->getColors(0) != *s.getColors(0) ||
+                *this->getColors(1) != *s.getColors(1) ||
+                *this->getColors(2) != *s.getColors(2)) {
                 return false;
             }
-
-            for (int i = 0; i < this->fColors.count(); i++) {
-                if (*this->getColors(i) != *ge.getColors(i)) {
-                    return false;
-                }
+        } else {
+            if (fYCoord != s.getYCoord()) {
+                return false;
             }
         }
 
-        SkASSERT(this->useAtlas() == ge.useAtlas());
+        SkASSERT(this->useAtlas() == s.useAtlas());
         return true;
     }
 
index ba3a65a..50ad427 100644 (file)
 #include "SkShader.h"
 #include "SkOnce.h"
 
-#if SK_SUPPORT_GPU
-    #define GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS 1
-#endif
-
 static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1,
                                int count) {
     if (count > 0) {
@@ -132,8 +128,7 @@ public:
         bool getDither() const { return fCacheDither; }
 
     private:
-        // Working pointers. If either is nullptr, we need to recompute the corresponding
-        // cache values.
+        // Working pointers. If either is nullptr, we need to recompute the corresponding cache values.
         uint16_t*   fCache16;
         SkPMColor*  fCache32;
 
@@ -202,6 +197,17 @@ public:
         kDitherStride16 = kCache16Count,
     };
 
+    enum GpuColorType {
+        kTwo_GpuColorType,
+        kThree_GpuColorType, // Symmetric three color
+        kTexture_GpuColorType
+    };
+
+    // Determines and returns the gradient is a two color gradient, symmetric three color gradient
+    // or other (texture gradient). If it is two or symmetric three color, the colors array will
+    // also be filled with the gradient colors
+    GpuColorType getGpuColorType(SkColor colors[3]) const;
+
     uint32_t getGradFlags() const { return fGradFlags; }
 
 protected:
@@ -214,6 +220,7 @@ protected:
     const SkMatrix fPtsToUnit;
     TileMode    fTileMode;
     TileProc    fTileProc;
+    int         fColorCount;
     uint8_t     fGradFlags;
 
     struct Rec {
@@ -247,15 +254,9 @@ private:
 public:
     SkColor*    fOrigColors; // original colors, before modulation by paint in context.
     SkScalar*   fOrigPos;   // original positions
-    int         fColorCount;
-
-    SkTArray<sk_sp<SkShader>> fSubGradients;
 
     bool colorsAreOpaque() const { return fColorsAreOpaque; }
 
-    TileMode getTileMode() const { return fTileMode; }
-    Rec* getRecs() const { return fRecs; }
-
 private:
     bool        fColorsAreOpaque;
 
@@ -335,30 +336,9 @@ public:
     virtual ~GrGradientEffect();
 
     bool useAtlas() const { return SkToBool(-1 != fRow); }
-    SkScalar getYCoord() const { return fYCoord; }
+    SkScalar getYCoord() const { return fYCoord; };
 
-    enum ColorType {
-        kTwo_ColorType,
-        kThree_ColorType, // Symmetric three color
-        kTexture_ColorType,
-
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
-        kHardStopCentered_ColorType,   // 0, 0.5, 0.5, 1
-        kHardStopLeftEdged_ColorType,  // 0, 0, 1
-        kHardStopRightEdged_ColorType, // 0, 1, 1
-#endif
-    };
-
-    ColorType getColorType() const { return fColorType; }
-
-    // Determines the type of gradient, one of:
-    //    - Two-color
-    //    - Symmetric three-color
-    //    - Texture
-    //    - Centered hard stop
-    //    - Left-edged hard stop
-    //    - Right-edged hard stop
-    ColorType determineColorType(const SkGradientShaderBase& shader);
+    SkGradientShaderBase::GpuColorType getColorType() const { return fColorType; }
 
     enum PremulType {
         kBeforeInterp_PremulType,
@@ -368,8 +348,8 @@ public:
     PremulType getPremulType() const { return fPremulType; }
 
     const SkColor* getColors(int pos) const {
-        SkASSERT(fColorType != kTexture_ColorType);
-        SkASSERT(pos < fColors.count());
+        SkASSERT(fColorType != SkGradientShaderBase::kTexture_GpuColorType);
+        SkASSERT((pos-1) <= fColorType);
         return &fColors[pos];
     }
 
@@ -378,8 +358,8 @@ protected:
         The function decides whether stop values should be used or not. The return value indicates
         the number of colors, which will be capped by kMaxRandomGradientColors. colors should be
         sized to be at least kMaxRandomGradientColors. stops is a pointer to an array of at least
-        size kMaxRandomGradientColors. It may be updated to nullptr, indicating that nullptr should
-        be passed to the gradient factory rather than the array.
+        size kMaxRandomGradientColors. It may be updated to nullptr, indicating that nullptr should be
+        passed to the gradient factory rather than the array.
     */
     static const int kMaxRandomGradientColors = 4;
     static int RandomGradientParams(SkRandom* r,
@@ -396,31 +376,26 @@ protected:
 private:
     static const GrCoordSet kCoordSet = kLocal_GrCoordSet;
 
-    SkTDArray<SkColor>  fColors;
-    SkTDArray<SkScalar> fPositions;
-    SkShader::TileMode  fTileMode;
-
     GrCoordTransform fCoordTransform;
     GrTextureAccess fTextureAccess;
     SkScalar fYCoord;
     GrTextureStripAtlas* fAtlas;
     int fRow;
     bool fIsOpaque;
-    ColorType fColorType;
-    PremulType fPremulType; // This is already baked into the table for texture gradients, and
-                            // only changes behavior for gradients that don't use a texture.
+    SkGradientShaderBase::GpuColorType fColorType;
+    SkColor fColors[3]; // More than 3 colors we use texture
+    PremulType fPremulType; // This only changes behavior for two and three color special cases.
+                            // It is already baked into to the table for texture gradients.
     typedef GrFragmentProcessor INHERITED;
 
 };
 
 ///////////////////////////////////////////////////////////////////////////////
 
-// Base class for GL gradient effects
+// Base class for GLSL gradient effects
 class GrGradientEffect::GLSLProcessor : public GrGLSLFragmentProcessor {
 public:
-    GLSLProcessor() {
-        fCachedYCoord = SK_ScalarMax;
-    }
+    GLSLProcessor();
 
 protected:
     void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
@@ -437,10 +412,10 @@ protected:
     // should call this method from their emitCode().
     void emitUniforms(GrGLSLUniformHandler*, const GrGradientEffect&);
 
-    // Emit code that gets a fragment's color from an expression for t; has branches for
-    // several control flows inside -- 2-color gradients, 3-color symmetric gradients, 4+
-    // color gradients that use the traditional texture lookup, as well as several varieties
-    // of hard stop gradients
+
+    // emit code that gets a fragment's color from an expression for t; Has branches for 3 separate
+    // control flows inside -- 2 color gradients, 3 color symmetric gradients (both using
+    // native GLSL mix), and 4+ color gradients that use the traditional texture lookup.
     void emitColor(GrGLSLFPFragmentBuilder* fragBuilder,
                    GrGLSLUniformHandler* uniformHandler,
                    const GrGLSLCaps* caps,
@@ -453,30 +428,18 @@ protected:
 private:
     enum {
         // First bit for premul before/after interp
-        kPremulBeforeInterpKey  =  1,
-
-        // Next three bits for 2/3 color type or different special
-        // hard stop cases (neither means using texture atlas)
-        kTwoColorKey            =  2,
-        kThreeColorKey          =  4,
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
-        kHardStopCenteredKey    =  6,
-        kHardStopZeroZeroOneKey =  8,
-        kHardStopZeroOneOneKey  = 10,
-
-        // Next two bits for tile mode
-        kClampTileMode          = 16,
-        kRepeatTileMode         = 32,
-        kMirrorTileMode         = 48,
-
-        // Lower six bits for premul, 2/3 color type, and tile mode
-        kReservedBits           = 6,
-#endif
+        kPremulBeforeInterpKey = 1,
+
+        // Next two bits for 2/3 color type (neither means using texture atlas)
+        kTwoColorKey   = 4,
+        kThreeColorKey = 6,
     };
 
     SkScalar fCachedYCoord;
-    GrGLSLProgramDataManager::UniformHandle fColorsUni;
     GrGLSLProgramDataManager::UniformHandle fFSYUni;
+    GrGLSLProgramDataManager::UniformHandle fColorStartUni;
+    GrGLSLProgramDataManager::UniformHandle fColorMidUni;
+    GrGLSLProgramDataManager::UniformHandle fColorEndUni;
 
     typedef GrGLSLFragmentProcessor INHERITED;
 };
index 505cfd2..6e32aa3 100644 (file)
@@ -218,10 +218,10 @@ void GrSweepGradient::GLSLSweepProcessor::emitCode(EmitArgs& args) {
     // On Intel GPU there is an issue where it reads the second arguement to atan "- %s.x" as an int
     // thus must us -1.0 * %s.x to work correctly
     if (args.fGLSLCaps->mustForceNegatedAtanParamToFloat()){
-        t.printf("(atan(- %s.y, -1.0 * %s.x) * 0.1591549430918 + 0.5)",
+        t.printf("atan(- %s.y, -1.0 * %s.x) * 0.1591549430918 + 0.5",
                  coords2D.c_str(), coords2D.c_str());
     } else {
-        t.printf("(atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5)",
+        t.printf("atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5",
                  coords2D.c_str(), coords2D.c_str());
     }
     this->emitColor(args.fFragBuilder,