| Index: src/effects/gradients/SkGradientShader.cpp
|
| diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
|
| index 5585944e55b77369cfca9c7150a0051a0cc126f1..820c5b225d1d4187c1cf6a9e4d85d5fe5fca126b 100644
|
| --- a/src/effects/gradients/SkGradientShader.cpp
|
| +++ b/src/effects/gradients/SkGradientShader.cpp
|
| @@ -228,8 +228,21 @@
|
| desc.flatten(buffer);
|
| }
|
|
|
| -static inline bool close_to_one_half(const SkFixed& val) {
|
| - return SkScalarNearlyEqual(SkFixedToScalar(val), SK_ScalarHalf);
|
| +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,
|
| @@ -898,186 +911,113 @@
|
| #include "glsl/GrGLSLUniformHandler.h"
|
| #include "SkGr.h"
|
|
|
| -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_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_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_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;
|
| - }
|
| -
|
| - case GrGradientEffect::kTexture_ColorType: {
|
| - SkScalar yCoord = e.getYCoord();
|
| - if (yCoord != fCachedYCoord) {
|
| - pdman.set1f(fFSYUni, yCoord);
|
| - fCachedYCoord = yCoord;
|
| - }
|
| - 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));
|
| + }
|
| +
|
| + } 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 (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()) {
|
| + key |= kTwoColorKey;
|
| + } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()) {
|
| + key |= kThreeColorKey;
|
| + }
|
| +
|
| if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
|
| key |= kPremulBeforeInterpKey;
|
| }
|
| -
|
| - if (GrGradientEffect::kTwo_ColorType == e.getColorType()) {
|
| - key |= kTwoColorKey;
|
| - } else if (GrGradientEffect::kThree_ColorType == 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;
|
| - }
|
| -#endif
|
|
|
| return key;
|
| }
|
| @@ -1090,183 +1030,56 @@
|
| 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;
|
| - }
|
| -
|
| - 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;
|
| - }
|
| -
|
| - 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;
|
| - }
|
| + 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");
|
| + }
|
| +
|
| + 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());
|
| + }
|
| + 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");
|
| + }
|
| +
|
| + 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 @@
|
|
|
| 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);
|
| - }
|
| -
|
| - 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;
|
| + fColorType = shader.getGpuColorType(&fColors[0]);
|
| +
|
| + // The two and three color specializations do not currently support tiling.
|
| + if (SkGradientShaderBase::kTwo_GpuColorType == fColorType ||
|
| + SkGradientShaderBase::kThree_GpuColorType == fColorType) {
|
| + fRow = -1;
|
| +
|
| + if (SkGradientShader::kInterpolateColorsInPremul_Flag & shader.getGradFlags()) {
|
| + fPremulType = kBeforeInterp_PremulType;
|
| + } 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;
|
| }
|
| -
|
| - 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;
|
| - }
|
| -
|
| + fCoordTransform.reset(kCoordSet, matrix, texture, params.filterMode());
|
| + fTextureAccess.reset(texture, params);
|
| + fYCoord = SK_ScalarHalf;
|
| + }
|
| + this->addTextureAccess(&fTextureAccess);
|
| + }
|
| this->addCoordTransform(&fCoordTransform);
|
| }
|
|
|
| @@ -1370,27 +1152,30 @@
|
| }
|
|
|
| bool GrGradientEffect::onIsEqual(const GrFragmentProcessor& processor) const {
|
| - const GrGradientEffect& ge = processor.cast<GrGradientEffect>();
|
| -
|
| - if (this->fColorType == ge.getColorType()) {
|
| - if (kTexture_ColorType == fColorType) {
|
| - if (fYCoord != ge.getYCoord()) {
|
| + const GrGradientEffect& s = processor.cast<GrGradientEffect>();
|
| +
|
| + if (this->fColorType == s.getColorType()){
|
| +
|
| + 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)) {
|
| return false;
|
| }
|
| } else {
|
| - if (this->getPremulType() != ge.getPremulType() ||
|
| - this->fColors.count() != ge.fColors.count()) {
|
| + if (fYCoord != s.getYCoord()) {
|
| return false;
|
| }
|
| -
|
| - for (int i = 0; i < this->fColors.count(); i++) {
|
| - if (*this->getColors(i) != *ge.getColors(i)) {
|
| - return false;
|
| - }
|
| - }
|
| - }
|
| -
|
| - SkASSERT(this->useAtlas() == ge.useAtlas());
|
| + }
|
| +
|
| + SkASSERT(this->useAtlas() == s.useAtlas());
|
| return true;
|
| }
|
|
|
|
|