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

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

Issue 22854005: GPU Gradients (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: remove dead line of code Created 7 years, 3 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 | « src/core/SkShader.cpp ('k') | 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 ca6386acb0e6dcfd1c53c5d594b9fa543e7a38bc..f1b5e582918d03f2107432bdf3d8dbafab07fcf3 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -831,28 +831,113 @@ GrGLGradientEffect::GrGLGradientEffect(const GrBackendEffectFactory& factory)
GrGLGradientEffect::~GrGLGradientEffect() { }
-void GrGLGradientEffect::emitYCoordUniform(GrGLShaderBuilder* builder) {
- fFSYUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
- kFloat_GrSLType, "GradientYCoordFS");
+void GrGLGradientEffect::emitUniforms(GrGLShaderBuilder* builder, EffectKey key) {
+
+ if (GrGradientEffect::kTwo_ColorType == 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
+ fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType, "GradientStartColor");
+ fColorMidUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType, "GradientMidColor");
+ fColorEndUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType, "GradientEndColor");
+
+ } else { // if not a fast case
+ fFSYUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kFloat_GrSLType, "GradientYCoordFS");
+ }
+}
+
+static inline void set_color_uni(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);
+}
+
+static inline void set_mul_color_uni(const GrGLUniformManager& uman,
+ const GrGLUniformManager::UniformHandle uni,
+ const SkColor* color){
+ float a = SkColorGetA(*color) / 255.f;
+ float aDiv255 = a / 255.f;
+ uman.set4f(uni,
+ SkColorGetR(*color) * aDiv255,
+ SkColorGetG(*color) * aDiv255,
+ SkColorGetB(*color) * aDiv255,
+ a);
}
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);
+ if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
+ set_mul_color_uni(uman, fColorStartUni, e.getColors(0));
+ set_mul_color_uni(uman, fColorEndUni, e.getColors(1));
+ } else {
+ set_color_uni(uman, fColorStartUni, e.getColors(0));
+ set_color_uni(uman, fColorEndUni, e.getColors(1));
+ }
+
+ } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){
+
+ fEffectMatrix.setData(uman, e.getMatrix(), drawEffect, NULL);
+ if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
+ set_mul_color_uni(uman, fColorStartUni, e.getColors(0));
+ set_mul_color_uni(uman, fColorMidUni, e.getColors(1));
+ set_mul_color_uni(uman, fColorEndUni, e.getColors(2));
+ } else {
+ set_color_uni(uman, fColorStartUni, e.getColors(0));
+ set_color_uni(uman, fColorMidUni, e.getColors(1));
+ set_color_uni(uman, fColorEndUni, e.getColors(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 |= kTwoColorKey;
+ } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){
+ key |= kThreeColorKey;
+ }
+
+ if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
+ key |= kPremulBeforeInterpKey;
+ }
+
+ return key;
}
void GrGLGradientEffect::setupMatrix(GrGLShaderBuilder* builder,
@@ -867,18 +952,57 @@ void GrGLGradientEffect::setupMatrix(GrGLShaderBuilder* builder,
vsVaryingType);
}
-void GrGLGradientEffect::emitColorLookup(GrGLShaderBuilder* builder,
- const char* gradientTValue,
- const char* outputColor,
- const char* inputColor,
- const GrGLShaderBuilder::TextureSampler& sampler) {
+void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder,
+ const char* gradientTValue,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const GrGLShaderBuilder::TextureSamplerArray& samplers) {
+ if (GrGradientEffect::kTwo_ColorType == 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(),
+ 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 == PremulTypeFromKey(key)) {
+ builder->fsCodeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
+ }
+
+ SkString output;
+ builder->fsCodeAppendf("\t%s = ", outputColor);
+ GrGLSLModulatef<4>(&output, inputColor, "colorTemp");
+ builder->fsCodeAppend(output.c_str());
+ builder->fsCodeAppend(";\n");
+ } else if (GrGradientEffect::kThree_ColorType == ColorTypeFromKey(key)){
+ builder->fsCodeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n",
+ gradientTValue);
+ builder->fsCodeAppendf("\tvec4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s +(1.0 - min(abs(oneMinus2t), 1.0)) * %s + clamp(-oneMinus2t, 0.0, 1.0) * %s;\n",
+ builder->getUniformVariable(fColorStartUni).c_str(),
+ builder->getUniformVariable(fColorMidUni).c_str(),
+ builder->getUniformVariable(fColorEndUni).c_str());
+ if (GrGradientEffect::kAfterInterp_PremulType == PremulTypeFromKey(key)) {
+ builder->fsCodeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
+ }
- builder->fsCodeAppendf("\tvec2 coord = vec2(%s, %s);\n",
- gradientTValue,
- builder->getUniformVariable(fFSYUni).c_str());
- builder->fsCodeAppendf("\t%s = ", outputColor);
- builder->fsAppendTextureLookupAndModulate(inputColor, sampler, "coord");
- builder->fsCodeAppend(";\n");
+ SkString output;
+ builder->fsCodeAppendf("\t%s = ", outputColor);
+ GrGLSLModulatef<4>(&output, inputColor, "colorTemp");
+ 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->fsAppendTextureLookupAndModulate(inputColor,
+ samplers[0],
+ "coord");
+ builder->fsCodeAppend(";\n");
+ }
}
/////////////////////////////////////////////////////////////////////
@@ -887,48 +1011,77 @@ 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;
-
- SkBitmap bitmap;
- shader.getGradientTableBitmap(&bitmap);
+ fMatrix = matrix;
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);
+ SkShader::GradientInfo info;
+ SkScalar pos[3] = {0};
+
+ info.fColorCount = 3;
+ info.fColors = &fColors[0];
+ info.fColorOffsets = &pos[0];
+ shader.asAGradient(&info);
+
+ // 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) {
+ fPremulType = kBeforeInterp_PremulType;
+ } else {
+ fPremulType = kAfterInterp_PremulType;
+ }
} else {
- GrTexture* texture = GrLockAndRefCachedBitmapTexture(ctx, bitmap, &params);
- 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);
+ // 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);
+ 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);
+ SkASSERT(NULL != 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->getVerticalScaleFactor();
+ fTextureAccess.reset(fAtlas->getTexture(), params);
+ } else {
+ GrTexture* texture = GrLockAndRefCachedBitmapTexture(ctx, bitmap, &params);
+ 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() {
@@ -939,12 +1092,31 @@ GrGradientEffect::~GrGradientEffect() {
bool GrGradientEffect::onIsEqual(const GrEffect& effect) const {
const GrGradientEffect& s = CastEffect<GrGradientEffect>(effect);
- return fTextureAccess.getTexture() == s.fTextureAccess.getTexture() &&
- fTextureAccess.getParams().getTileModeX() ==
+
+ if (this->fColorType == s.getColorType()){
+
+ if (kTwo_ColorType == fColorType) {
+ if (*this->getColors(0) != *s.getColors(0) ||
+ *this->getColors(1) != *s.getColors(1)) {
+ return false;
+ }
+ } else if (kThree_ColorType == fColorType) {
+ if (*this->getColors(0) != *s.getColors(0) ||
+ *this->getColors(1) != *s.getColors(1) ||
+ *this->getColors(2) != *s.getColors(2)) {
+ return false;
+ }
+ }
+
+ return fTextureAccess.getTexture() == s.fTextureAccess.getTexture() &&
+ fTextureAccess.getParams().getTileModeX() ==
s.fTextureAccess.getParams().getTileModeX() &&
- this->useAtlas() == s.useAtlas() &&
- fYCoord == s.getYCoord() &&
- fMatrix.cheapEqualTo(s.getMatrix());
+ this->useAtlas() == s.useAtlas() &&
+ fYCoord == s.getYCoord() &&
+ fMatrix.cheapEqualTo(s.getMatrix());
+ }
+
+ return false;
}
void GrGradientEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
« no previous file with comments | « src/core/SkShader.cpp ('k') | src/effects/gradients/SkGradientShaderPriv.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698