Chromium Code Reviews| Index: src/effects/gradients/SkGradientShader.cpp |
| diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp |
| index 4e528b5ba80b874ddafeb8cadd2d56544d4b0fdd..0aa78c59c936a1a1dc9996843b8d94247e1f7ad7 100644 |
| --- a/src/effects/gradients/SkGradientShader.cpp |
| +++ b/src/effects/gradients/SkGradientShader.cpp |
| @@ -832,28 +832,91 @@ GrGLGradientEffect::GrGLGradientEffect(const GrBackendEffectFactory& factory) |
| GrGLGradientEffect::~GrGLGradientEffect() { } |
| -void GrGLGradientEffect::emitYCoordUniform(GrGLShaderBuilder* builder) { |
| - fFSYUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, |
| - kFloat_GrSLType, "GradientYCoordFS"); |
| +void GrGLGradientEffect::emitUniforms(GrGLShaderBuilder* builder, EffectKey key) { |
| + |
| + if (GrGradientEffect::kTwo_ColorType == getColorType(key)) { // 2 Color case |
| + fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, |
| + kVec4f_GrSLType, "GradientStartColor"); |
| + fColorEndUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, |
| + kVec4f_GrSLType, "GradientEndColor"); |
| + |
| + } else if (GrGradientEffect::kThree_ColorType == getColorType(key)){ // 3 Color Case |
| + fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, |
| + kVec4f_GrSLType, "GradientStartColor"); |
| + fColorMidUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, |
| + kVec4f_GrSLType, "GradientMidColor"); |
| + fColorEndUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, |
| + kVec4f_GrSLType, "GradientEndColor"); |
| + |
| + } else { // if not a fast case |
| + fFSYUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, |
| + kFloat_GrSLType, "GradientYCoordFS"); |
| + } |
| +} |
| + |
| +static void setColorUni(const GrGLUniformManager& uman, |
| + const GrGLUniformManager::UniformHandle uni, |
| + const SkColor color){ |
| + uman.set4f(uni, |
| + SkColorGetR(color)/255.f, |
| + SkColorGetG(color)/255.f, |
| + SkColorGetB(color)/255.f, |
| + SkColorGetA(color)/255.f |
| + ); |
| } |
| void GrGLGradientEffect::setData(const GrGLUniformManager& uman, |
| const GrDrawEffect& drawEffect) { |
| + |
| const GrGradientEffect& e = drawEffect.castEffect<GrGradientEffect>(); |
| - const GrTexture* texture = e.texture(0); |
| - fEffectMatrix.setData(uman, e.getMatrix(), drawEffect, texture); |
| - SkScalar yCoord = e.getYCoord(); |
| - if (yCoord != fCachedYCoord) { |
| - uman.set1f(fFSYUni, yCoord); |
| - fCachedYCoord = yCoord; |
| + |
| + if (GrGradientEffect::kTwo_ColorType == e.getColorType()){ |
| + |
| + fEffectMatrix.setData(uman, e.getMatrix(), drawEffect, NULL); |
| + const SkColor* colors = e.getColors(); |
| + setColorUni(uman, fColorStartUni, colors[0]); |
| + setColorUni(uman, fColorEndUni, colors[1]); |
| + |
| + } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){ |
| + |
| + fEffectMatrix.setData(uman, e.getMatrix(), drawEffect, NULL); |
| + const SkColor* colors = e.getColors(); |
| + setColorUni(uman, fColorStartUni, colors[0]); |
| + setColorUni(uman, fColorMidUni, colors[1]); |
| + setColorUni(uman, fColorEndUni, colors[2]); |
| + |
| + } else { |
| + |
| + const GrTexture* texture = e.texture(0); |
| + fEffectMatrix.setData(uman, e.getMatrix(), drawEffect, texture); |
| + |
| + SkScalar yCoord = e.getYCoord(); |
| + if (yCoord != fCachedYCoord) { |
| + uman.set1f(fFSYUni, yCoord); |
| + fCachedYCoord = yCoord; |
| + } |
| } |
| } |
| -GrGLEffect::EffectKey GrGLGradientEffect::GenMatrixKey(const GrDrawEffect& drawEffect) { |
| + |
| +GrGLEffect::EffectKey GrGLGradientEffect::GenBaseGradientKey(const GrDrawEffect& drawEffect) { |
| const GrGradientEffect& e = drawEffect.castEffect<GrGradientEffect>(); |
| - const GrTexture* texture = e.texture(0); |
| - return GrGLEffectMatrix::GenKey(e.getMatrix(), drawEffect, kCoordsType, texture); |
| + const GrTexture* texture = NULL; |
| + |
| + if (GrGradientEffect::kTexture_ColorType == e.getColorType()){ |
| + texture = e.texture(0); |
| + } |
| + |
| + EffectKey key = GrGLEffectMatrix::GenKey(e.getMatrix(), drawEffect, kCoordsType, texture); |
| + |
| + if (GrGradientEffect::kTwo_ColorType == e.getColorType()) { |
| + key = key | kTwoColorKey; |
| + } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){ |
| + key = key | kThreeColorKey; |
| + } |
| + |
| + return key; |
| } |
| void GrGLGradientEffect::setupMatrix(GrGLShaderBuilder* builder, |
| @@ -868,21 +931,53 @@ void GrGLGradientEffect::setupMatrix(GrGLShaderBuilder* builder, |
| vsVaryingType); |
| } |
| -void GrGLGradientEffect::emitColorLookup(GrGLShaderBuilder* builder, |
| - const char* gradientTValue, |
| - const char* outputColor, |
| - const char* inputColor, |
| - const GrGLShaderBuilder::TextureSampler& sampler) { |
| - |
| - builder->fsCodeAppendf("\tvec2 coord = vec2(%s, %s);\n", |
| - gradientTValue, |
| - builder->getUniformVariable(fFSYUni).c_str()); |
| - builder->fsCodeAppendf("\t%s = ", outputColor); |
| - builder->appendTextureLookupAndModulate(GrGLShaderBuilder::kFragment_ShaderType, |
| - inputColor, |
| - sampler, |
| - "coord"); |
| - builder->fsCodeAppend(";\n"); |
| +void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder, |
| + const char* gradientTValue, |
| + EffectKey key, |
| + const char* outputColor, |
| + const char* inputColor, |
| + const GrGLShaderBuilder::TextureSamplerArray& samplers) { |
| + if (GrGradientEffect::kTwo_ColorType == getColorType(key)){ |
| + |
| + builder->fsCodeAppendf("\tvec4 colorTemp = mix(%s, %s, %s);\n", |
| + builder->getUniformVariable(fColorStartUni).c_str(), |
| + builder->getUniformVariable(fColorEndUni).c_str(), |
| + gradientTValue); |
| + |
| + SkString output, colorTemp; |
| + colorTemp.append("colorTemp"); |
| + builder->fsCodeAppendf("\t%s = ", outputColor); |
| + GrGLSLModulatef<4>(&output, inputColor, colorTemp.c_str()); |
| + builder->fsCodeAppend(output.c_str()); |
| + builder->fsCodeAppend(";\n"); |
| + |
| + } else if (GrGradientEffect::kThree_ColorType == getColorType(key)){ |
| + |
| + builder->fsCodeAppendf("\tfloat oneMinus2t = 1 - (2*%s);\n", |
|
bsalomon
2013/08/15 13:16:42
Some GLSL compilers will give you heartache about
|
| + gradientTValue); |
| + builder->fsCodeAppendf("\tvec4 colorTemp = clamp(oneMinus2t, 0, 1) * %s +(1 - abs(oneMinus2t)) * %s + clamp(-oneMinus2t, 0, 1) * %s;\n", |
| + builder->getUniformVariable(fColorStartUni).c_str(), |
| + builder->getUniformVariable(fColorMidUni).c_str(), |
| + builder->getUniformVariable(fColorEndUni).c_str()); |
| + |
| + SkString output, colorTemp; |
| + colorTemp.append("colorTemp"); |
| + builder->fsCodeAppendf("\t%s = ", outputColor); |
| + GrGLSLModulatef<4>(&output, inputColor, colorTemp.c_str()); |
| + builder->fsCodeAppend(output.c_str()); |
| + builder->fsCodeAppend(";\n"); |
| + |
| + } else { |
| + builder->fsCodeAppendf("\tvec2 coord = vec2(%s, %s);\n", |
| + gradientTValue, |
| + builder->getUniformVariable(fFSYUni).c_str()); |
| + builder->fsCodeAppendf("\t%s = ", outputColor); |
| + builder->appendTextureLookupAndModulate(GrGLShaderBuilder::kFragment_ShaderType, |
| + inputColor, |
| + samplers[0], |
| + "coord"); |
| + builder->fsCodeAppend(";\n"); |
| + } |
| } |
| ///////////////////////////////////////////////////////////////////// |
| @@ -891,10 +986,6 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx, |
| const SkGradientShaderBase& shader, |
| const SkMatrix& matrix, |
| SkShader::TileMode tileMode) { |
| - // TODO: check for simple cases where we don't need a texture: |
| - //GradientInfo info; |
| - //shader.asAGradient(&info); |
| - //if (info.fColorCount == 2) { ... |
| fMatrix = matrix; |
| @@ -903,36 +994,55 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx, |
| fIsOpaque = shader.isOpaque(); |
| - GrTextureStripAtlas::Desc desc; |
| - desc.fWidth = bitmap.width(); |
| - desc.fHeight = 32; |
| - desc.fRowHeight = bitmap.height(); |
| - desc.fContext = ctx; |
| - desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap.config()); |
| - fAtlas = GrTextureStripAtlas::GetAtlas(desc); |
| - SkASSERT(NULL != fAtlas); |
| - |
| - // We always filter the gradient table. Each table is one row of a texture, so 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->getVerticalScaleFactor(); |
| - fTextureAccess.reset(fAtlas->getTexture(), params); |
| + // TODO: check for simple cases where we don't need a texture: |
| + SkShader::GradientInfo info; |
| + SkScalar pos[3] = {0}; |
| + |
| + info.fColorCount = 3; |
| + info.fColors = &fColors[0]; |
| + info.fColorOffsets = &pos[0]; |
| + shader.asAGradient(&info); |
| + |
| + if (2 == info.fColorCount) { // if 2 color |
| + fRow = -1; // flag for no atlas |
| + fColorType = kTwo_ColorType; |
| + } else if (3 == info.fColorCount && (SkScalarAbs(pos[1] - 0.5) < 0.01)) { // if 3 color symmetric |
|
bsalomon
2013/08/15 13:16:42
nit: line wrap
|
| + fRow = -1; // flag for no atlas |
| + fColorType = kThree_ColorType; |
| } else { |
| - GrTexture* texture = GrLockAndRefCachedBitmapTexture(ctx, bitmap, ¶ms); |
| - fTextureAccess.reset(texture, params); |
| - fYCoord = SK_ScalarHalf; |
| - |
| - // Unlock immediately, this is not great, but we don't have a way of |
| - // knowing when else to unlock it currently, so it may get purged from |
| - // the cache, but it'll still be ref'd until it's no longer being used. |
| - GrUnlockAndUnrefCachedBitmapTexture(texture); |
| + fColorType = kTexture_ColorType; |
| + |
| + GrTextureStripAtlas::Desc desc; |
| + desc.fWidth = bitmap.width(); |
| + desc.fHeight = 32; |
| + desc.fRowHeight = bitmap.height(); |
| + desc.fContext = ctx; |
| + desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap.config()); |
| + fAtlas = GrTextureStripAtlas::GetAtlas(desc); |
| + GrAssert(NULL != fAtlas); |
| + |
| + // We always filter the gradient table. Each table is one row of a texture, so always y-clamp. |
|
bsalomon
2013/08/15 13:16:42
nit: line wrap
|
| + GrTextureParams params; |
| + params.setFilterMode(GrTextureParams::kBilerp_FilterMode); |
| + params.setTileModeX(tileMode); |
| + |
| + fRow = fAtlas->lockRow(bitmap); |
| + if (-1 != fRow) { |
| + fYCoord = fAtlas->getYOffset(fRow) + SK_ScalarHalf * |
| + fAtlas->getVerticalScaleFactor(); |
| + fTextureAccess.reset(fAtlas->getTexture(), params); |
| + } else { |
| + GrTexture* texture = GrLockAndRefCachedBitmapTexture(ctx, bitmap, ¶ms); |
| + fTextureAccess.reset(texture, params); |
| + fYCoord = SK_ScalarHalf; |
| + |
| + // Unlock immediately, this is not great, but we don't have a way of |
| + // knowing when else to unlock it currently, so it may get purged from |
| + // the cache, but it'll still be ref'd until it's no longer being used. |
| + GrUnlockAndUnrefCachedBitmapTexture(texture); |
| + } |
| + this->addTextureAccess(&fTextureAccess); |
| } |
| - this->addTextureAccess(&fTextureAccess); |
| } |
| GrGradientEffect::~GrGradientEffect() { |
| @@ -948,7 +1058,9 @@ bool GrGradientEffect::onIsEqual(const GrEffect& effect) const { |
| s.fTextureAccess.getParams().getTileModeX() && |
| this->useAtlas() == s.useAtlas() && |
| fYCoord == s.getYCoord() && |
| - fMatrix.cheapEqualTo(s.getMatrix()); |
| + fMatrix.cheapEqualTo(s.getMatrix()) |
| + && this->fColorType == s.getColorType(); |
| + // also check for colors of 2 / 3 gradients! |
| } |
| void GrGradientEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { |