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
This commit is contained in:
parent
1eda1eb203
commit
2a4959181f
@ -228,23 +228,6 @@ void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const {
|
|||||||
desc.flatten(buffer);
|
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,
|
void SkGradientShaderBase::FlipGradientColors(SkColor* colorDst, Rec* recDst,
|
||||||
SkColor* colorSrc, Rec* recSrc,
|
SkColor* colorSrc, Rec* recSrc,
|
||||||
int count) {
|
int count) {
|
||||||
@ -911,114 +894,191 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
|
|||||||
#include "glsl/GrGLSLUniformHandler.h"
|
#include "glsl/GrGLSLUniformHandler.h"
|
||||||
#include "SkGr.h"
|
#include "SkGr.h"
|
||||||
|
|
||||||
GrGradientEffect::GLSLProcessor::GLSLProcessor()
|
static inline bool close_to_one_half(const SkFixed& val) {
|
||||||
: fCachedYCoord(SK_ScalarMax) {
|
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,
|
void GrGradientEffect::GLSLProcessor::emitUniforms(GrGLSLUniformHandler* uniformHandler,
|
||||||
const GrGradientEffect& ge) {
|
const GrGradientEffect& ge) {
|
||||||
|
if (int colorCount = color_type_to_color_count(ge.getColorType())) {
|
||||||
if (SkGradientShaderBase::kTwo_GpuColorType == ge.getColorType()) { // 2 Color case
|
fColorsUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag,
|
||||||
fColorStartUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
kVec4f_GrSLType,
|
||||||
kVec4f_GrSLType, kDefault_GrSLPrecision,
|
kDefault_GrSLPrecision,
|
||||||
"GradientStartColor");
|
"Colors",
|
||||||
fColorEndUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
colorCount);
|
||||||
kVec4f_GrSLType, kDefault_GrSLPrecision,
|
} else {
|
||||||
"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,
|
fFSYUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||||
kFloat_GrSLType, kDefault_GrSLPrecision,
|
kFloat_GrSLType, kDefault_GrSLPrecision,
|
||||||
"GradientYCoordFS");
|
"GradientYCoordFS");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void set_color_uni(const GrGLSLProgramDataManager& pdman,
|
static inline void set_after_interp_color_uni_array(const GrGLSLProgramDataManager& pdman,
|
||||||
const GrGLSLProgramDataManager::UniformHandle uni,
|
const GrGLSLProgramDataManager::UniformHandle uni,
|
||||||
const SkColor* color) {
|
const SkTDArray<SkColor>& colors) {
|
||||||
pdman.set4f(uni,
|
int count = colors.count();
|
||||||
SkColorGetR(*color) / 255.f,
|
constexpr int kSmallCount = 10;
|
||||||
SkColorGetG(*color) / 255.f,
|
|
||||||
SkColorGetB(*color) / 255.f,
|
SkAutoSTArray<4*kSmallCount, float> vals(4*count);
|
||||||
SkColorGetA(*color) / 255.f);
|
|
||||||
|
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_mul_color_uni(const GrGLSLProgramDataManager& pdman,
|
static inline void set_before_interp_color_uni_array(const GrGLSLProgramDataManager& pdman,
|
||||||
const GrGLSLProgramDataManager::UniformHandle uni,
|
const GrGLSLProgramDataManager::UniformHandle uni,
|
||||||
const SkColor* color){
|
const SkTDArray<SkColor>& colors) {
|
||||||
float a = SkColorGetA(*color) / 255.f;
|
int count = colors.count();
|
||||||
float aDiv255 = a / 255.f;
|
constexpr int kSmallCount = 10;
|
||||||
pdman.set4f(uni,
|
|
||||||
SkColorGetR(*color) * aDiv255,
|
SkAutoSTArray<4*kSmallCount, float> vals(4*count);
|
||||||
SkColorGetG(*color) * aDiv255,
|
|
||||||
SkColorGetB(*color) * aDiv255,
|
for (int i = 0; i < count; i++) {
|
||||||
a);
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrGradientEffect::GLSLProcessor::onSetData(const GrGLSLProgramDataManager& pdman,
|
void GrGradientEffect::GLSLProcessor::onSetData(const GrGLSLProgramDataManager& pdman,
|
||||||
const GrProcessor& processor) {
|
const GrProcessor& processor) {
|
||||||
|
|
||||||
const GrGradientEffect& e = processor.cast<GrGradientEffect>();
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()){
|
break;
|
||||||
|
|
||||||
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()){
|
case GrGradientEffect::kTexture_ColorType: {
|
||||||
|
SkScalar yCoord = e.getYCoord();
|
||||||
if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
|
if (yCoord != fCachedYCoord) {
|
||||||
set_mul_color_uni(pdman, fColorStartUni, e.getColors(0));
|
pdman.set1f(fFSYUni, yCoord);
|
||||||
set_mul_color_uni(pdman, fColorMidUni, e.getColors(1));
|
fCachedYCoord = yCoord;
|
||||||
set_mul_color_uni(pdman, fColorEndUni, e.getColors(2));
|
}
|
||||||
} else {
|
break;
|
||||||
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) {
|
uint32_t GrGradientEffect::GLSLProcessor::GenBaseGradientKey(const GrProcessor& processor) {
|
||||||
const GrGradientEffect& e = processor.cast<GrGradientEffect>();
|
const GrGradientEffect& e = processor.cast<GrGradientEffect>();
|
||||||
|
|
||||||
uint32_t key = 0;
|
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()) {
|
if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
|
||||||
key |= kPremulBeforeInterpKey;
|
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;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1030,56 +1090,183 @@ void GrGradientEffect::GLSLProcessor::emitColor(GrGLSLFPFragmentBuilder* fragBui
|
|||||||
const char* outputColor,
|
const char* outputColor,
|
||||||
const char* inputColor,
|
const char* inputColor,
|
||||||
const SamplerHandle* texSamplers) {
|
const SamplerHandle* texSamplers) {
|
||||||
if (SkGradientShaderBase::kTwo_GpuColorType == ge.getColorType()){
|
switch (ge.getColorType()) {
|
||||||
fragBuilder->codeAppendf("\tvec4 colorTemp = mix(%s, %s, clamp(%s, 0.0, 1.0));\n",
|
#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
|
||||||
uniformHandler->getUniformVariable(fColorStartUni).c_str(),
|
case kHardStopCentered_ColorType: {
|
||||||
uniformHandler->getUniformVariable(fColorEndUni).c_str(),
|
const char* t = gradientTValue;
|
||||||
gradientTValue);
|
const char* colors = uniformHandler->getUniformCStr(fColorsUni);
|
||||||
// Note that we could skip this step if both colors are known to be opaque. Two
|
|
||||||
// considerations:
|
fragBuilder->codeAppendf("float clamp_t = clamp(%s, 0.0, 1.0);", t);
|
||||||
// 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
|
// Account for tile mode
|
||||||
// shader as thekBeforeIterp case). This same optimization applies to the 3 color case
|
if (SkShader::kRepeat_TileMode == ge.fTileMode) {
|
||||||
// below.
|
fragBuilder->codeAppendf("clamp_t = fract(%s);", t);
|
||||||
if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) {
|
} else if (SkShader::kMirror_TileMode == ge.fTileMode) {
|
||||||
fragBuilder->codeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
|
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,
|
case kHardStopLeftEdged_ColorType: {
|
||||||
(GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
|
const char* t = gradientTValue;
|
||||||
} else if (SkGradientShaderBase::kThree_GpuColorType == ge.getColorType()) {
|
const char* colors = uniformHandler->getUniformCStr(fColorsUni);
|
||||||
fragBuilder->codeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n",
|
|
||||||
gradientTValue);
|
fragBuilder->codeAppendf("float clamp_t = clamp(%s, 0.0, 1.0);", t);
|
||||||
fragBuilder->codeAppendf("\tvec4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s;\n",
|
|
||||||
uniformHandler->getUniformVariable(fColorStartUni).c_str());
|
// Account for tile mode
|
||||||
if (!glslCaps->canUseMinAndAbsTogether()) {
|
if (SkShader::kRepeat_TileMode == ge.fTileMode) {
|
||||||
// The Tegra3 compiler will sometimes never return if we have
|
fragBuilder->codeAppendf("clamp_t = fract(%s);", t);
|
||||||
// min(abs(oneMinus2t), 1.0), or do the abs first in a separate expression.
|
} else if (SkShader::kMirror_TileMode == ge.fTileMode) {
|
||||||
fragBuilder->codeAppend("\tfloat minAbs = abs(oneMinus2t);\n");
|
fragBuilder->codeAppendf("if (%s < 0.0 || %s > 1.0) {", t, t);
|
||||||
fragBuilder->codeAppend("\tminAbs = minAbs > 1.0 ? 1.0 : minAbs;\n");
|
fragBuilder->codeAppendf(" if (mod(floor(%s), 2.0) == 0.0) {", t);
|
||||||
fragBuilder->codeAppendf("\tcolorTemp += (1.0 - minAbs) * %s;\n",
|
fragBuilder->codeAppendf(" clamp_t = fract(%s);", t);
|
||||||
uniformHandler->getUniformVariable(fColorMidUni).c_str());
|
fragBuilder->codeAppendf(" } else {");
|
||||||
} else {
|
fragBuilder->codeAppendf(" clamp_t = 1.0 - fract(%s);", t);
|
||||||
fragBuilder->codeAppendf("\tcolorTemp += (1.0 - min(abs(oneMinus2t), 1.0)) * %s;\n",
|
fragBuilder->codeAppendf(" }");
|
||||||
uniformHandler->getUniformVariable(fColorMidUni).c_str());
|
fragBuilder->codeAppendf("}");
|
||||||
}
|
}
|
||||||
fragBuilder->codeAppendf("\tcolorTemp += clamp(-oneMinus2t, 0.0, 1.0) * %s;\n",
|
|
||||||
uniformHandler->getUniformVariable(fColorEndUni).c_str());
|
fragBuilder->codeAppendf("vec4 colorTemp = mix(%s[1], %s[2], clamp_t);", colors,
|
||||||
if (GrGradientEffect::kAfterInterp_PremulType == ge.getPremulType()) {
|
colors);
|
||||||
fragBuilder->codeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
|
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("\t%s = %s;\n", outputColor,
|
case kHardStopRightEdged_ColorType: {
|
||||||
(GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
|
const char* t = gradientTValue;
|
||||||
} else {
|
const char* colors = uniformHandler->getUniformCStr(fColorsUni);
|
||||||
fragBuilder->codeAppendf("\tvec2 coord = vec2(%s, %s);\n",
|
|
||||||
gradientTValue,
|
fragBuilder->codeAppendf("float clamp_t = clamp(%s, 0.0, 1.0);", t);
|
||||||
uniformHandler->getUniformVariable(fFSYUni).c_str());
|
|
||||||
fragBuilder->codeAppendf("\t%s = ", outputColor);
|
// Account for tile mode
|
||||||
fragBuilder->appendTextureLookupAndModulate(inputColor,
|
if (SkShader::kRepeat_TileMode == ge.fTileMode) {
|
||||||
texSamplers[0],
|
fragBuilder->codeAppendf("clamp_t = fract(%s);", t);
|
||||||
"coord");
|
} else if (SkShader::kMirror_TileMode == ge.fTileMode) {
|
||||||
fragBuilder->codeAppend(";\n");
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1092,56 +1279,87 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx,
|
|||||||
|
|
||||||
fIsOpaque = shader.isOpaque();
|
fIsOpaque = shader.isOpaque();
|
||||||
|
|
||||||
fColorType = shader.getGpuColorType(&fColors[0]);
|
fColorType = this->determineColorType(shader);
|
||||||
|
|
||||||
// The two and three color specializations do not currently support tiling.
|
if (kTexture_ColorType != fColorType) {
|
||||||
if (SkGradientShaderBase::kTwo_GpuColorType == fColorType ||
|
if (shader.fOrigColors) {
|
||||||
SkGradientShaderBase::kThree_GpuColorType == fColorType) {
|
fColors = SkTDArray<SkColor>(shader.fOrigColors, shader.fColorCount);
|
||||||
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;
|
#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
|
||||||
desc.fWidth = bitmap.width();
|
if (shader.fOrigPos) {
|
||||||
desc.fHeight = 32;
|
fPositions = SkTDArray<SkScalar>(shader.fOrigPos, shader.fColorCount);
|
||||||
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);
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
this->addCoordTransform(&fCoordTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1152,30 +1370,27 @@ GrGradientEffect::~GrGradientEffect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool GrGradientEffect::onIsEqual(const GrFragmentProcessor& processor) const {
|
bool GrGradientEffect::onIsEqual(const GrFragmentProcessor& processor) const {
|
||||||
const GrGradientEffect& s = processor.cast<GrGradientEffect>();
|
const GrGradientEffect& ge = processor.cast<GrGradientEffect>();
|
||||||
|
|
||||||
if (this->fColorType == s.getColorType()){
|
if (this->fColorType == ge.getColorType()) {
|
||||||
|
if (kTexture_ColorType == fColorType) {
|
||||||
if (SkGradientShaderBase::kTwo_GpuColorType == fColorType) {
|
if (fYCoord != ge.getYCoord()) {
|
||||||
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;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (fYCoord != s.getYCoord()) {
|
if (this->getPremulType() != ge.getPremulType() ||
|
||||||
|
this->fColors.count() != ge.fColors.count()) {
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,10 @@
|
|||||||
#include "SkShader.h"
|
#include "SkShader.h"
|
||||||
#include "SkOnce.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,
|
static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1,
|
||||||
int count) {
|
int count) {
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
@ -128,7 +132,8 @@ public:
|
|||||||
bool getDither() const { return fCacheDither; }
|
bool getDither() const { return fCacheDither; }
|
||||||
|
|
||||||
private:
|
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;
|
uint16_t* fCache16;
|
||||||
SkPMColor* fCache32;
|
SkPMColor* fCache32;
|
||||||
|
|
||||||
@ -197,17 +202,6 @@ public:
|
|||||||
kDitherStride16 = kCache16Count,
|
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; }
|
uint32_t getGradFlags() const { return fGradFlags; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -220,7 +214,6 @@ protected:
|
|||||||
const SkMatrix fPtsToUnit;
|
const SkMatrix fPtsToUnit;
|
||||||
TileMode fTileMode;
|
TileMode fTileMode;
|
||||||
TileProc fTileProc;
|
TileProc fTileProc;
|
||||||
int fColorCount;
|
|
||||||
uint8_t fGradFlags;
|
uint8_t fGradFlags;
|
||||||
|
|
||||||
struct Rec {
|
struct Rec {
|
||||||
@ -254,9 +247,15 @@ private:
|
|||||||
public:
|
public:
|
||||||
SkColor* fOrigColors; // original colors, before modulation by paint in context.
|
SkColor* fOrigColors; // original colors, before modulation by paint in context.
|
||||||
SkScalar* fOrigPos; // original positions
|
SkScalar* fOrigPos; // original positions
|
||||||
|
int fColorCount;
|
||||||
|
|
||||||
|
SkTArray<sk_sp<SkShader>> fSubGradients;
|
||||||
|
|
||||||
bool colorsAreOpaque() const { return fColorsAreOpaque; }
|
bool colorsAreOpaque() const { return fColorsAreOpaque; }
|
||||||
|
|
||||||
|
TileMode getTileMode() const { return fTileMode; }
|
||||||
|
Rec* getRecs() const { return fRecs; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool fColorsAreOpaque;
|
bool fColorsAreOpaque;
|
||||||
|
|
||||||
@ -336,9 +335,30 @@ public:
|
|||||||
virtual ~GrGradientEffect();
|
virtual ~GrGradientEffect();
|
||||||
|
|
||||||
bool useAtlas() const { return SkToBool(-1 != fRow); }
|
bool useAtlas() const { return SkToBool(-1 != fRow); }
|
||||||
SkScalar getYCoord() const { return fYCoord; };
|
SkScalar getYCoord() const { return fYCoord; }
|
||||||
|
|
||||||
SkGradientShaderBase::GpuColorType getColorType() const { return fColorType; }
|
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);
|
||||||
|
|
||||||
enum PremulType {
|
enum PremulType {
|
||||||
kBeforeInterp_PremulType,
|
kBeforeInterp_PremulType,
|
||||||
@ -348,8 +368,8 @@ public:
|
|||||||
PremulType getPremulType() const { return fPremulType; }
|
PremulType getPremulType() const { return fPremulType; }
|
||||||
|
|
||||||
const SkColor* getColors(int pos) const {
|
const SkColor* getColors(int pos) const {
|
||||||
SkASSERT(fColorType != SkGradientShaderBase::kTexture_GpuColorType);
|
SkASSERT(fColorType != kTexture_ColorType);
|
||||||
SkASSERT((pos-1) <= fColorType);
|
SkASSERT(pos < fColors.count());
|
||||||
return &fColors[pos];
|
return &fColors[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,8 +378,8 @@ protected:
|
|||||||
The function decides whether stop values should be used or not. The return value indicates
|
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
|
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
|
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
|
size kMaxRandomGradientColors. It may be updated to nullptr, indicating that nullptr should
|
||||||
passed to the gradient factory rather than the array.
|
be passed to the gradient factory rather than the array.
|
||||||
*/
|
*/
|
||||||
static const int kMaxRandomGradientColors = 4;
|
static const int kMaxRandomGradientColors = 4;
|
||||||
static int RandomGradientParams(SkRandom* r,
|
static int RandomGradientParams(SkRandom* r,
|
||||||
@ -376,26 +396,31 @@ protected:
|
|||||||
private:
|
private:
|
||||||
static const GrCoordSet kCoordSet = kLocal_GrCoordSet;
|
static const GrCoordSet kCoordSet = kLocal_GrCoordSet;
|
||||||
|
|
||||||
|
SkTDArray<SkColor> fColors;
|
||||||
|
SkTDArray<SkScalar> fPositions;
|
||||||
|
SkShader::TileMode fTileMode;
|
||||||
|
|
||||||
GrCoordTransform fCoordTransform;
|
GrCoordTransform fCoordTransform;
|
||||||
GrTextureAccess fTextureAccess;
|
GrTextureAccess fTextureAccess;
|
||||||
SkScalar fYCoord;
|
SkScalar fYCoord;
|
||||||
GrTextureStripAtlas* fAtlas;
|
GrTextureStripAtlas* fAtlas;
|
||||||
int fRow;
|
int fRow;
|
||||||
bool fIsOpaque;
|
bool fIsOpaque;
|
||||||
SkGradientShaderBase::GpuColorType fColorType;
|
ColorType fColorType;
|
||||||
SkColor fColors[3]; // More than 3 colors we use texture
|
PremulType fPremulType; // This is already baked into the table for texture gradients, and
|
||||||
PremulType fPremulType; // This only changes behavior for two and three color special cases.
|
// only changes behavior for gradients that don't use a texture.
|
||||||
// It is already baked into to the table for texture gradients.
|
|
||||||
typedef GrFragmentProcessor INHERITED;
|
typedef GrFragmentProcessor INHERITED;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Base class for GLSL gradient effects
|
// Base class for GL gradient effects
|
||||||
class GrGradientEffect::GLSLProcessor : public GrGLSLFragmentProcessor {
|
class GrGradientEffect::GLSLProcessor : public GrGLSLFragmentProcessor {
|
||||||
public:
|
public:
|
||||||
GLSLProcessor();
|
GLSLProcessor() {
|
||||||
|
fCachedYCoord = SK_ScalarMax;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
|
void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
|
||||||
@ -412,10 +437,10 @@ protected:
|
|||||||
// should call this method from their emitCode().
|
// should call this method from their emitCode().
|
||||||
void emitUniforms(GrGLSLUniformHandler*, const GrGradientEffect&);
|
void emitUniforms(GrGLSLUniformHandler*, const GrGradientEffect&);
|
||||||
|
|
||||||
|
// Emit code that gets a fragment's color from an expression for t; has branches for
|
||||||
// emit code that gets a fragment's color from an expression for t; Has branches for 3 separate
|
// several control flows inside -- 2-color gradients, 3-color symmetric gradients, 4+
|
||||||
// control flows inside -- 2 color gradients, 3 color symmetric gradients (both using
|
// color gradients that use the traditional texture lookup, as well as several varieties
|
||||||
// native GLSL mix), and 4+ color gradients that use the traditional texture lookup.
|
// of hard stop gradients
|
||||||
void emitColor(GrGLSLFPFragmentBuilder* fragBuilder,
|
void emitColor(GrGLSLFPFragmentBuilder* fragBuilder,
|
||||||
GrGLSLUniformHandler* uniformHandler,
|
GrGLSLUniformHandler* uniformHandler,
|
||||||
const GrGLSLCaps* caps,
|
const GrGLSLCaps* caps,
|
||||||
@ -428,18 +453,30 @@ protected:
|
|||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
// First bit for premul before/after interp
|
// First bit for premul before/after interp
|
||||||
kPremulBeforeInterpKey = 1,
|
kPremulBeforeInterpKey = 1,
|
||||||
|
|
||||||
// Next two bits for 2/3 color type (neither means using texture atlas)
|
// Next three bits for 2/3 color type or different special
|
||||||
kTwoColorKey = 4,
|
// hard stop cases (neither means using texture atlas)
|
||||||
kThreeColorKey = 6,
|
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
|
||||||
};
|
};
|
||||||
|
|
||||||
SkScalar fCachedYCoord;
|
SkScalar fCachedYCoord;
|
||||||
|
GrGLSLProgramDataManager::UniformHandle fColorsUni;
|
||||||
GrGLSLProgramDataManager::UniformHandle fFSYUni;
|
GrGLSLProgramDataManager::UniformHandle fFSYUni;
|
||||||
GrGLSLProgramDataManager::UniformHandle fColorStartUni;
|
|
||||||
GrGLSLProgramDataManager::UniformHandle fColorMidUni;
|
|
||||||
GrGLSLProgramDataManager::UniformHandle fColorEndUni;
|
|
||||||
|
|
||||||
typedef GrGLSLFragmentProcessor INHERITED;
|
typedef GrGLSLFragmentProcessor INHERITED;
|
||||||
};
|
};
|
||||||
|
@ -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
|
// 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
|
// thus must us -1.0 * %s.x to work correctly
|
||||||
if (args.fGLSLCaps->mustForceNegatedAtanParamToFloat()){
|
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());
|
coords2D.c_str(), coords2D.c_str());
|
||||||
} else {
|
} 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());
|
coords2D.c_str(), coords2D.c_str());
|
||||||
}
|
}
|
||||||
this->emitColor(args.fFragBuilder,
|
this->emitColor(args.fFragBuilder,
|
||||||
|
Loading…
Reference in New Issue
Block a user