diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp index 2ebb9c71d9..504855a478 100644 --- a/src/effects/gradients/SkGradientShader.cpp +++ b/src/effects/gradients/SkGradientShader.cpp @@ -220,6 +220,23 @@ void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const { buffer.writeMatrix(fPtsToUnit); } +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; +} + bool SkGradientShaderBase::isOpaque() const { return fColorsAreOpaque; } @@ -832,13 +849,13 @@ GrGLGradientEffect::~GrGLGradientEffect() { } void GrGLGradientEffect::emitUniforms(GrGLShaderBuilder* builder, EffectKey key) { - if (GrGradientEffect::kTwo_ColorType == ColorTypeFromKey(key)) { // 2 Color case + if (SkGradientShaderBase::kTwo_GpuColorType == ColorTypeFromKey(key)) { // 2 Color case fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "GradientStartColor"); fColorEndUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "GradientEndColor"); - } else if (GrGradientEffect::kThree_ColorType == ColorTypeFromKey(key)){ // 3 Color Case + } else if (SkGradientShaderBase::kThree_GpuColorType == ColorTypeFromKey(key)){ // 3 Color Case fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "GradientStartColor"); fColorMidUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, @@ -880,7 +897,7 @@ void GrGLGradientEffect::setData(const GrGLUniformManager& uman, const GrGradientEffect& e = drawEffect.castEffect(); - if (GrGradientEffect::kTwo_ColorType == e.getColorType()){ + if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()){ if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) { set_mul_color_uni(uman, fColorStartUni, e.getColors(0)); @@ -890,7 +907,7 @@ void GrGLGradientEffect::setData(const GrGLUniformManager& uman, set_color_uni(uman, fColorEndUni, e.getColors(1)); } - } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){ + } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()){ if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) { set_mul_color_uni(uman, fColorStartUni, e.getColors(0)); @@ -917,9 +934,9 @@ GrGLEffect::EffectKey GrGLGradientEffect::GenBaseGradientKey(const GrDrawEffect& EffectKey key = 0; - if (GrGradientEffect::kTwo_ColorType == e.getColorType()) { + if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()) { key |= kTwoColorKey; - } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){ + } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()){ key |= kThreeColorKey; } @@ -936,7 +953,7 @@ void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder, const char* outputColor, const char* inputColor, const TextureSamplerArray& samplers) { - if (GrGradientEffect::kTwo_ColorType == ColorTypeFromKey(key)){ + if (SkGradientShaderBase::kTwo_GpuColorType == ColorTypeFromKey(key)){ builder->fsCodeAppendf("\tvec4 colorTemp = mix(%s, %s, clamp(%s, 0.0, 1.0));\n", builder->getUniformVariable(fColorStartUni).c_str(), builder->getUniformVariable(fColorEndUni).c_str(), @@ -952,7 +969,7 @@ void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder, builder->fsCodeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str()); - } else if (GrGradientEffect::kThree_ColorType == ColorTypeFromKey(key)){ + } else if (SkGradientShaderBase::kThree_GpuColorType == ColorTypeFromKey(key)){ builder->fsCodeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n", gradientTValue); builder->fsCodeAppendf("\tvec4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s;\n", @@ -997,30 +1014,14 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx, fIsOpaque = shader.isOpaque(); - SkShader::GradientInfo info; - SkScalar pos[3] = {0}; - - info.fColorCount = 3; - info.fColors = &fColors[0]; - info.fColorOffsets = &pos[0]; - shader.asAGradient(&info); + fColorType = shader.getGpuColorType(&fColors[0]); // The two and three color specializations do not currently support tiling. - bool foundSpecialCase = false; - if (SkShader::kClamp_TileMode == info.fTileMode) { - if (2 == info.fColorCount) { - fRow = -1; // flag for no atlas - fColorType = kTwo_ColorType; - foundSpecialCase = true; - } else if (3 == info.fColorCount && - (SkScalarAbs(pos[1] - SK_ScalarHalf) < SK_Scalar1 / 1000)) { // 3 color symmetric - fRow = -1; // flag for no atlas - fColorType = kThree_ColorType; - foundSpecialCase = true; - } - } - if (foundSpecialCase) { - if (SkGradientShader::kInterpolateColorsInPremul_Flag & info.fGradientFlags) { + if (SkGradientShaderBase::kTwo_GpuColorType == fColorType || + SkGradientShaderBase::kThree_GpuColorType == fColorType) { + fRow = -1; + + if (SkGradientShader::kInterpolateColorsInPremul_Flag & shader.getFlags()) { fPremulType = kBeforeInterp_PremulType; } else { fPremulType = kAfterInterp_PremulType; @@ -1031,7 +1032,6 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx, fPremulType = kBeforeInterp_PremulType; SkBitmap bitmap; shader.getGradientTableBitmap(&bitmap); - fColorType = kTexture_ColorType; GrTextureStripAtlas::Desc desc; desc.fWidth = bitmap.width(); @@ -1080,12 +1080,12 @@ bool GrGradientEffect::onIsEqual(const GrEffect& effect) const { if (this->fColorType == s.getColorType()){ - if (kTwo_ColorType == fColorType) { + if (SkGradientShaderBase::kTwo_GpuColorType == fColorType) { if (*this->getColors(0) != *s.getColors(0) || *this->getColors(1) != *s.getColors(1)) { return false; } - } else if (kThree_ColorType == fColorType) { + } else if (SkGradientShaderBase::kThree_GpuColorType == fColorType) { if (*this->getColors(0) != *s.getColors(0) || *this->getColors(1) != *s.getColors(1) || *this->getColors(2) != *s.getColors(2)) { diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h index 83e0789853..1ccd0491ba 100644 --- a/src/effects/gradients/SkGradientShaderPriv.h +++ b/src/effects/gradients/SkGradientShaderPriv.h @@ -128,6 +128,18 @@ public: 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 getFlags() const { return fGradFlags; } protected: SkGradientShaderBase(SkReadBuffer& ); @@ -251,13 +263,7 @@ public: virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; - enum ColorType { - kTwo_ColorType, - kThree_ColorType, - kTexture_ColorType - }; - - ColorType getColorType() const { return fColorType; } + SkGradientShaderBase::GpuColorType getColorType() const { return fColorType; } enum PremulType { kBeforeInterp_PremulType, @@ -267,7 +273,7 @@ public: PremulType getPremulType() const { return fPremulType; } const SkColor* getColors(int pos) const { - SkASSERT(fColorType != kTexture_ColorType); + SkASSERT(fColorType != SkGradientShaderBase::kTexture_GpuColorType); SkASSERT((pos-1) <= fColorType); return &fColors[pos]; } @@ -294,18 +300,14 @@ protected: private: static const GrCoordSet kCoordSet = kLocal_GrCoordSet; - enum { - kMaxAnalyticColors = 3 // if more colors use texture - }; - GrCoordTransform fCoordTransform; GrTextureAccess fTextureAccess; SkScalar fYCoord; GrTextureStripAtlas* fAtlas; int fRow; bool fIsOpaque; - ColorType fColorType; - SkColor fColors[kMaxAnalyticColors]; + SkGradientShaderBase::GpuColorType fColorType; + SkColor fColors[3]; // More than 3 colors we use texture PremulType fPremulType; // This only changes behavior for two and three color special cases. // It is already baked into to the table for texture gradients. typedef GrEffect INHERITED; @@ -338,12 +340,12 @@ protected: kBaseKeyBitCnt = (kPremulTypeKeyBitCnt + kColorKeyBitCnt) }; - static GrGradientEffect::ColorType ColorTypeFromKey(EffectKey key){ + static SkGradientShaderBase::GpuColorType ColorTypeFromKey(EffectKey key){ if (kTwoColorKey == (key & kColorKeyMask)) { - return GrGradientEffect::kTwo_ColorType; + return SkGradientShaderBase::kTwo_GpuColorType; } else if (kThreeColorKey == (key & kColorKeyMask)) { - return GrGradientEffect::kThree_ColorType; - } else {return GrGradientEffect::kTexture_ColorType;} + return SkGradientShaderBase::kThree_GpuColorType; + } else {return SkGradientShaderBase::kTexture_GpuColorType;} } static GrGradientEffect::PremulType PremulTypeFromKey(EffectKey key){