diff options
author | 2016-08-12 06:33:52 -0700 | |
---|---|---|
committer | 2016-08-12 06:33:52 -0700 | |
commit | 2a4959181fc98d5d7ee862e7cd1c7993b3343be6 (patch) | |
tree | 71053a063b1fe398ad684a8b1367461a4c764e56 /src/effects/gradients/SkGradientShader.cpp | |
parent | 1eda1eb2039518f534c4b893482c8b0f8c4abeab (diff) |
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
Review-Url: https://codereview.chromium.org/2223203003
Diffstat (limited to 'src/effects/gradients/SkGradientShader.cpp')
-rw-r--r-- | src/effects/gradients/SkGradientShader.cpp | 607 |
1 files changed, 411 insertions, 196 deletions
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp index 820c5b225d..6b387e7153 100644 --- a/src/effects/gradients/SkGradientShader.cpp +++ b/src/effects/gradients/SkGradientShader.cpp @@ -228,23 +228,6 @@ 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) { @@ -911,113 +894,190 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END #include "glsl/GrGLSLUniformHandler.h" #include "SkGr.h" -GrGradientEffect::GLSLProcessor::GLSLProcessor() - : fCachedYCoord(SK_ScalarMax) { +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; } void GrGradientEffect::GLSLProcessor::emitUniforms(GrGLSLUniformHandler* uniformHandler, const GrGradientEffect& ge) { - - 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 + if (int colorCount = color_type_to_color_count(ge.getColorType())) { + fColorsUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag, + kVec4f_GrSLType, + kDefault_GrSLPrecision, + "Colors", + colorCount); + } else { fFSYUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision, "GradientYCoordFS"); } } -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_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; + } -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); + pdman.set4fv(uni, colors.count(), vals.get()); } -void GrGradientEffect::GLSLProcessor::onSetData(const GrGLSLProgramDataManager& pdman, - const GrProcessor& processor) { +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; - const GrGradientEffect& e = processor.cast<GrGradientEffect>(); + 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; - if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()){ + // 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; + } - 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)); - } + pdman.set4fv(uni, count, vals.get()); +} - } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()){ +void GrGradientEffect::GLSLProcessor::onSetData(const GrGLSLProgramDataManager& pdman, + const GrProcessor& processor) { + const GrGradientEffect& e = processor.cast<GrGradientEffect>(); - 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)); + 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; } - } else { - SkScalar yCoord = e.getYCoord(); - if (yCoord != fCachedYCoord) { - pdman.set1f(fFSYUni, yCoord); - fCachedYCoord = yCoord; + case GrGradientEffect::kTexture_ColorType: { + SkScalar yCoord = e.getYCoord(); + if (yCoord != fCachedYCoord) { + pdman.set1f(fFSYUni, yCoord); + fCachedYCoord = yCoord; + } + break; } } } - uint32_t GrGradientEffect::GLSLProcessor::GenBaseGradientKey(const GrProcessor& processor) { const GrGradientEffect& e = processor.cast<GrGradientEffect>(); uint32_t key = 0; - if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()) { + if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) { + key |= kPremulBeforeInterpKey; + } + + if (GrGradientEffect::kTwo_ColorType == e.getColorType()) { key |= kTwoColorKey; - } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()) { + } else if (GrGradientEffect::kThree_ColorType == e.getColorType()) { key |= kThreeColorKey; } - - if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) { - key |= kPremulBeforeInterpKey; +#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; + } +#endif return key; } @@ -1030,56 +1090,183 @@ void GrGradientEffect::GLSLProcessor::emitColor(GrGLSLFPFragmentBuilder* fragBui const char* outputColor, const char* inputColor, const SamplerHandle* texSamplers) { - 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"); + 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; } - 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 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; } - 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 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 - 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"); + 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; + } + + 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; + } + + 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; + } } } @@ -1092,56 +1279,87 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx, fIsOpaque = shader.isOpaque(); - fColorType = shader.getGpuColorType(&fColors[0]); + fColorType = this->determineColorType(shader); - // The two and three color specializations do not currently support tiling. - if (SkGradientShaderBase::kTwo_GpuColorType == fColorType || - SkGradientShaderBase::kThree_GpuColorType == fColorType) { - fRow = -1; + if (kTexture_ColorType != fColorType) { + if (shader.fOrigColors) { + fColors = SkTDArray<SkColor>(shader.fOrigColors, shader.fColorCount); + } - if (SkGradientShader::kInterpolateColorsInPremul_Flag & shader.getGradFlags()) { - fPremulType = kBeforeInterp_PremulType; - } else { - fPremulType = kAfterInterp_PremulType; +#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS + if (shader.fOrigPos) { + fPositions = SkTDArray<SkScalar>(shader.fOrigPos, shader.fColorCount); } - 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; + + fTileMode = tileMode; +#endif + } + + 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, texture, params.filterMode()); - fTextureAccess.reset(texture, params); - fYCoord = SK_ScalarHalf; - } - this->addTextureAccess(&fTextureAccess); + + 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. + 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; + } + + this->addTextureAccess(&fTextureAccess); + + break; } + this->addCoordTransform(&fCoordTransform); } @@ -1152,30 +1370,27 @@ GrGradientEffect::~GrGradientEffect() { } bool GrGradientEffect::onIsEqual(const GrFragmentProcessor& processor) const { - const GrGradientEffect& s = processor.cast<GrGradientEffect>(); - - if (this->fColorType == s.getColorType()){ + const GrGradientEffect& ge = processor.cast<GrGradientEffect>(); - 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 (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)) { + if (this->fColorType == ge.getColorType()) { + if (kTexture_ColorType == fColorType) { + if (fYCoord != ge.getYCoord()) { return false; } } else { - if (fYCoord != s.getYCoord()) { + if (this->getPremulType() != ge.getPremulType() || + this->fColors.count() != ge.fColors.count()) { return false; } + + for (int i = 0; i < this->fColors.count(); i++) { + if (*this->getColors(i) != *ge.getColors(i)) { + return false; + } + } } - SkASSERT(this->useAtlas() == s.useAtlas()); + SkASSERT(this->useAtlas() == ge.useAtlas()); return true; } |