Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Unified Diff: src/effects/gradients/SkGradientShader.cpp

Issue 2223203003: Exact Ganesh Gradients for Special Cases (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Remove unused field fSubGradients, fix valgrind 'uninitialized value' bug Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/effects/gradients/SkGradientShaderPriv.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/effects/gradients/SkGradientShader.cpp
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index 820c5b225d1d4187c1cf6a9e4d85d5fe5fca126b..457b89dcf5858a7ae53476df08cbcd488fec4863 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,89 @@ 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;
+#endif
+ }
+
+#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
+ 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 +1372,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;
}
« no previous file with comments | « no previous file | src/effects/gradients/SkGradientShaderPriv.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698