diff options
Diffstat (limited to 'src/effects/gradients')
-rw-r--r-- | src/effects/gradients/SkGradientShader.cpp | 33 | ||||
-rw-r--r-- | src/effects/gradients/SkGradientShaderPriv.h | 39 | ||||
-rw-r--r-- | src/effects/gradients/SkLinearGradient.cpp | 22 | ||||
-rw-r--r-- | src/effects/gradients/SkRadialGradient.cpp | 24 | ||||
-rw-r--r-- | src/effects/gradients/SkSweepGradient.cpp | 20 | ||||
-rw-r--r-- | src/effects/gradients/SkTwoPointConicalGradient.cpp | 36 | ||||
-rw-r--r-- | src/effects/gradients/SkTwoPointRadialGradient.cpp | 46 |
7 files changed, 166 insertions, 54 deletions
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp index 60eff91d65..78c7e34a74 100644 --- a/src/effects/gradients/SkGradientShader.cpp +++ b/src/effects/gradients/SkGradientShader.cpp @@ -678,7 +678,9 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END GrGLGradientEffect::GrGLGradientEffect(const GrBackendEffectFactory& factory) : INHERITED(factory) , fCachedYCoord(GR_ScalarMax) - , fFSYUni(GrGLUniformManager::kInvalidUniformHandle) { } + , fFSYUni(GrGLUniformManager::kInvalidUniformHandle) { + fRequiresTextureMatrix = false; +} GrGLGradientEffect::~GrGLGradientEffect() { } @@ -688,13 +690,37 @@ void GrGLGradientEffect::emitYCoordUniform(GrGLShaderBuilder* builder) { } void GrGLGradientEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) { - GrScalar yCoord = static_cast<const GrGradientEffect&>(*stage.getEffect()).getYCoord(); + const GrGradientEffect& e = static_cast<const GrGradientEffect&>(*stage.getEffect()); + const GrTexture* texture = e.texture(0); + fEffectMatrix.setData(uman, e.getMatrix(), stage.getCoordChangeMatrix(), texture); + + GrScalar yCoord = e.getYCoord(); if (yCoord != fCachedYCoord) { uman.set1f(fFSYUni, yCoord); fCachedYCoord = yCoord; } } +GrGLEffect::EffectKey GrGLGradientEffect::GenMatrixKey(const GrEffectStage& s) { + const GrGradientEffect& e = static_cast<const GrGradientEffect&>(*s.getEffect()); + const GrTexture* texture = e.texture(0); + return GrGLEffectMatrix::GenKey(e.getMatrix(), s.getCoordChangeMatrix(), texture); +} + +void GrGLGradientEffect::setupMatrix(GrGLShaderBuilder* builder, + EffectKey key, + const char* vertexCoords, + const char** fsCoordName, + const char** vsVaryingName, + GrSLType* vsVaryingType) { + fEffectMatrix.emitCodeMakeFSCoords2D(builder, + key & kMatrixKeyMask, + vertexCoords, + fsCoordName, + vsVaryingName, + vsVaryingType); +} + void GrGLGradientEffect::emitColorLookup(GrGLShaderBuilder* builder, const char* gradientTValue, const char* outputColor, @@ -714,6 +740,7 @@ void GrGLGradientEffect::emitColorLookup(GrGLShaderBuilder* builder, GrGradientEffect::GrGradientEffect(GrContext* ctx, const SkGradientShaderBase& shader, + const SkMatrix& matrix, SkShader::TileMode tileMode) : INHERITED(1) { // TODO: check for simple cases where we don't need a texture: @@ -721,6 +748,8 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx, //shader.asAGradient(&info); //if (info.fColorCount == 2) { ... + fMatrix = matrix; + SkBitmap bitmap; shader.getGradientTableBitmap(&bitmap); diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h index 9f14e7f727..24379110ee 100644 --- a/src/effects/gradients/SkGradientShaderPriv.h +++ b/src/effects/gradients/SkGradientShaderPriv.h @@ -193,12 +193,13 @@ private: #if SK_SUPPORT_GPU #include "gl/GrGLEffect.h" +#include "gl/GrGLEffectMatrix.h" class GrEffectStage; class GrBackendEffectFactory; /* - * The intepretation of the texture matrix depends on the sample mode. The + * The interpretation of the texture matrix depends on the sample mode. The * texture matrix is applied both when the texture coordinates are explicit * and when vertex positions are used as texture coordinates. In the latter * case the texture matrix is applied to the pre-view-matrix position @@ -228,6 +229,7 @@ public: GrGradientEffect(GrContext* ctx, const SkGradientShaderBase& shader, + const SkMatrix& matrix, SkShader::TileMode tileMode); virtual ~GrGradientEffect(); @@ -236,11 +238,12 @@ public: bool useAtlas() const { return SkToBool(-1 != fRow); } GrScalar getYCoord() const { return fYCoord; }; + const SkMatrix& getMatrix() const { return fMatrix;} virtual bool isEqual(const GrEffect& effect) const SK_OVERRIDE { const GrGradientEffect& s = static_cast<const GrGradientEffect&>(effect); return INHERITED::isEqual(effect) && this->useAtlas() == s.useAtlas() && - fYCoord == s.getYCoord(); + fYCoord == s.getYCoord() && fMatrix.cheapEqualTo(s.getMatrix()); } protected: @@ -263,6 +266,7 @@ private: GrScalar fYCoord; GrTextureStripAtlas* fAtlas; int fRow; + SkMatrix fMatrix; typedef GrEffect INHERITED; @@ -279,6 +283,36 @@ public: virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE; protected: + /** + * Subclasses must reserve the lower kMatrixKeyBitCnt of their key for use by + * GrGLGradientEffect. + */ + enum { + kMatrixKeyBitCnt = GrGLEffectMatrix::kKeyBits, + kMatrixKeyMask = (1 << kMatrixKeyBitCnt) - 1, + }; + + /** + * Subclasses must call this. It will return a value restricted to the lower kMatrixKeyBitCnt + * bits. + */ + static EffectKey GenMatrixKey(const GrEffectStage& s); + + /** + * Inserts code to implement the GrGradientEffect's matrix. This should be called before a + * subclass emits its own code. The name of the 2D coords is output via fsCoordName and already + * incorporates any perspective division. The caller can also optionally retrieve the name of + * the varying inserted in the VS and its type, which may be either vec2f or vec3f depending + * upon whether the matrix has perspective or not. It is not necessary to mask the key before + * calling. + */ + void setupMatrix(GrGLShaderBuilder* builder, + EffectKey key, + const char* vertexCoords, + const char** fsCoordName, + const char** vsVaryingName = NULL, + GrSLType* vsVaryingType = NULL); + // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses // should call this method from their emitCode(). void emitYCoordUniform(GrGLShaderBuilder* builder); @@ -295,6 +329,7 @@ protected: private: GrScalar fCachedYCoord; GrGLUniformManager::UniformHandle fFSYUni; + GrGLEffectMatrix fEffectMatrix; typedef GrGLEffect INHERITED; }; diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp index d9576565b5..71614505a1 100644 --- a/src/effects/gradients/SkLinearGradient.cpp +++ b/src/effects/gradients/SkLinearGradient.cpp @@ -495,7 +495,9 @@ public: const char* inputColor, const TextureSamplerArray&) SK_OVERRIDE; - static EffectKey GenKey(const GrEffectStage&, const GrGLCaps& caps) { return 0; } + static EffectKey GenKey(const GrEffectStage& stage, const GrGLCaps&) { + return GenMatrixKey(stage); + } private: @@ -507,8 +509,11 @@ private: class GrLinearGradient : public GrGradientEffect { public: - GrLinearGradient(GrContext* ctx, const SkLinearGradient& shader, SkShader::TileMode tm) - : INHERITED(ctx, shader, tm) { } + GrLinearGradient(GrContext* ctx, + const SkLinearGradient& shader, + const SkMatrix& matrix, + SkShader::TileMode tm) + : INHERITED(ctx, shader, matrix, tm) { } virtual ~GrLinearGradient() { } static const char* Name() { return "Linear Gradient"; } @@ -553,15 +558,18 @@ GrEffect* GrLinearGradient::TestCreate(SkRandom* random, ///////////////////////////////////////////////////////////////////// void GrGLLinearGradient::emitCode(GrGLShaderBuilder* builder, - const GrEffectStage&, - EffectKey, + const GrEffectStage& stage, + EffectKey key, const char* vertexCoords, const char* outputColor, const char* inputColor, const TextureSamplerArray& samplers) { this->emitYCoordUniform(builder); + const char* coords; + this->setupMatrix(builder, key, vertexCoords, &coords); SkString t; - t.printf("%s.x", builder->defaultTexCoordsName()); + t.append(coords); + t.append(".x"); this->emitColorLookup(builder, t.c_str(), outputColor, inputColor, samplers[0]); } @@ -574,7 +582,7 @@ bool SkLinearGradient::asNewEffect(GrContext* context, GrEffectStage* stage) con return false; } matrix.postConcat(fPtsToUnit); - stage->setEffect(SkNEW_ARGS(GrLinearGradient, (context, *this, fTileMode)), matrix)->unref(); + stage->setEffect(SkNEW_ARGS(GrLinearGradient, (context, *this, matrix, fTileMode)))->unref(); return true; } diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp index a20ea35a1a..02a56da588 100644 --- a/src/effects/gradients/SkRadialGradient.cpp +++ b/src/effects/gradients/SkRadialGradient.cpp @@ -490,7 +490,9 @@ public: const char* inputColor, const TextureSamplerArray&) SK_OVERRIDE; - static EffectKey GenKey(const GrEffectStage&, const GrGLCaps& caps) { return 0; } + static EffectKey GenKey(const GrEffectStage& stage, const GrGLCaps&) { + return GenMatrixKey(stage); + } private: @@ -503,8 +505,11 @@ private: class GrRadialGradient : public GrGradientEffect { public: - GrRadialGradient(GrContext* ctx, const SkRadialGradient& shader, SkShader::TileMode tm) - : INHERITED(ctx, shader, tm) { + GrRadialGradient(GrContext* ctx, + const SkRadialGradient& shader, + const SkMatrix& matrix, + SkShader::TileMode tm) + : INHERITED(ctx, shader, matrix, tm) { } virtual ~GrRadialGradient() { } @@ -551,15 +556,18 @@ GrEffect* GrRadialGradient::TestCreate(SkRandom* random, ///////////////////////////////////////////////////////////////////// void GrGLRadialGradient::emitCode(GrGLShaderBuilder* builder, - const GrEffectStage&, - EffectKey, + const GrEffectStage& stage, + EffectKey key, const char* vertexCoords, const char* outputColor, const char* inputColor, const TextureSamplerArray& samplers) { this->emitYCoordUniform(builder); - SkString t; - t.printf("length(%s.xy)", builder->defaultTexCoordsName()); + const char* coords; + this->setupMatrix(builder, key, vertexCoords, &coords); + SkString t("length("); + t.append(coords); + t.append(")"); this->emitColorLookup(builder, t.c_str(), outputColor, inputColor, samplers[0]); } @@ -573,7 +581,7 @@ bool SkRadialGradient::asNewEffect(GrContext* context, GrEffectStage* stage) con return false; } matrix.postConcat(fPtsToUnit); - stage->setEffect(SkNEW_ARGS(GrRadialGradient, (context, *this, fTileMode)), matrix)->unref(); + stage->setEffect(SkNEW_ARGS(GrRadialGradient, (context, *this, matrix, fTileMode)))->unref(); return true; } diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp index a783e3757c..589cf4ad14 100644 --- a/src/effects/gradients/SkSweepGradient.cpp +++ b/src/effects/gradients/SkSweepGradient.cpp @@ -399,7 +399,9 @@ public: const char* inputColor, const TextureSamplerArray&) SK_OVERRIDE; - static EffectKey GenKey(const GrEffectStage&, const GrGLCaps& caps) { return 0; } + static EffectKey GenKey(const GrEffectStage& stage, const GrGLCaps&) { + return GenMatrixKey(stage); + } private: @@ -413,8 +415,9 @@ class GrSweepGradient : public GrGradientEffect { public: GrSweepGradient(GrContext* ctx, - const SkSweepGradient& shader) - : INHERITED(ctx, shader, SkShader::kClamp_TileMode) { } + const SkSweepGradient& shader, + const SkMatrix& matrix) + : INHERITED(ctx, shader, matrix, SkShader::kClamp_TileMode) { } virtual ~GrSweepGradient() { } static const char* Name() { return "Sweep Gradient"; } @@ -457,16 +460,17 @@ GrEffect* GrSweepGradient::TestCreate(SkRandom* random, ///////////////////////////////////////////////////////////////////// void GrGLSweepGradient::emitCode(GrGLShaderBuilder* builder, - const GrEffectStage&, - EffectKey, + const GrEffectStage& stage, + EffectKey key, const char* vertexCoords, const char* outputColor, const char* inputColor, const TextureSamplerArray& samplers) { this->emitYCoordUniform(builder); + const char* coords; + this->setupMatrix(builder, key, vertexCoords, &coords); SkString t; - t.printf("atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5", - builder->defaultTexCoordsName(), builder->defaultTexCoordsName()); + t.printf("atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5", coords, coords); this->emitColorLookup(builder, t.c_str(), outputColor, inputColor, samplers[0]); } @@ -478,7 +482,7 @@ bool SkSweepGradient::asNewEffect(GrContext* context, GrEffectStage* stage) cons return false; } matrix.postConcat(fPtsToUnit); - stage->setEffect(SkNEW_ARGS(GrSweepGradient, (context, *this)), matrix)->unref(); + stage->setEffect(SkNEW_ARGS(GrSweepGradient, (context, *this, matrix)))->unref(); return true; } diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp index f93f660837..41292bb43a 100644 --- a/src/effects/gradients/SkTwoPointConicalGradient.cpp +++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp @@ -371,8 +371,9 @@ public: GrConical2Gradient(GrContext* ctx, const SkTwoPointConicalGradient& shader, + const SkMatrix& matrix, SkShader::TileMode tm) - : INHERITED(ctx, shader, tm) + : INHERITED(ctx, shader, matrix, tm) , fCenterX1(shader.getCenterX1()) , fRadius0(shader.getStartRadius()) , fDiffRadius(shader.getDiffRadius()) { } @@ -468,12 +469,17 @@ GrGLConical2Gradient::GrGLConical2Gradient( } void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder, - const GrEffectStage&, - EffectKey, + const GrEffectStage& stage, + EffectKey key, const char* vertexCoords, const char* outputColor, const char* inputColor, const TextureSamplerArray& samplers) { + const char* fsCoords; + const char* vsCoordsVarying; + GrSLType coordsVaryingType; + this->setupMatrix(builder, key, vertexCoords, &fsCoords, &vsCoordsVarying, &coordsVaryingType); + this->emitYCoordUniform(builder); // 2 copies of uniform array, 1 for each of vertex & fragment shader, // to work around Xoom bug. Doesn't seem to cause performance decrease @@ -485,7 +491,7 @@ void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder, // For radial gradients without perspective we can pass the linear // part of the quadratic as a varying. - if (!builder->defaultTextureMatrixIsPerspective()) { + if (kVec2f_GrSLType == coordsVaryingType) { builder->addVarying(kFloat_GrSLType, "Conical2BCoeff", &fVSVaryingName, &fFSVaryingName); } @@ -502,11 +508,11 @@ void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder, // For radial gradients without perspective we can pass the linear // part of the quadratic as a varying. - if (!builder->defaultTextureMatrixIsPerspective()) { + if (kVec2f_GrSLType == coordsVaryingType) { // r2Var = -2 * (r2Parm[2] * varCoord.x - r2Param[3] * r2Param[5]) code->appendf("\t%s = -2.0 * (%s * %s.x + %s * %s);\n", fVSVaryingName, p2.c_str(), - vertexCoords, p3.c_str(), p5.c_str()); + vsCoordsVarying, p3.c_str(), p5.c_str()); } } @@ -538,12 +544,12 @@ void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder, // If we we're able to interpolate the linear component, // bVar is the varying; otherwise compute it SkString bVar; - if (!builder->defaultTextureMatrixIsPerspective()) { + if (kVec2f_GrSLType == coordsVaryingType) { bVar = fFSVaryingName; } else { bVar = "b"; code->appendf("\tfloat %s = -2.0 * (%s * %s.x + %s * %s);\n", - bVar.c_str(), p2.c_str(), builder->defaultTexCoordsName(), + bVar.c_str(), p2.c_str(), fsCoords, p3.c_str(), p5.c_str()); } @@ -553,7 +559,7 @@ void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder, // c = (x^2)+(y^2) - params[4] code->appendf("\tfloat %s = dot(%s, %s) - %s;\n", cName.c_str(), - builder->defaultTexCoordsName(), builder->defaultTexCoordsName(), + fsCoords, fsCoords, p4.c_str()); // Non-degenerate case (quadratic) @@ -669,7 +675,15 @@ void GrGLConical2Gradient::setData(const GrGLUniformManager& uman, const GrEffec } GrGLEffect::EffectKey GrGLConical2Gradient::GenKey(const GrEffectStage& s, const GrGLCaps&) { - return (static_cast<const GrConical2Gradient&>(*s.getEffect()).isDegenerate()); + enum { + kIsDegenerate = 1 << kMatrixKeyBitCnt, + }; + + EffectKey key = GenMatrixKey(s); + if (static_cast<const GrConical2Gradient&>(*s.getEffect()).isDegenerate()) { + key |= kIsDegenerate; + } + return key; } ///////////////////////////////////////////////////////////////////// @@ -695,7 +709,7 @@ bool SkTwoPointConicalGradient::asNewEffect(GrContext* context, matrix.postConcat(rot); } - stage->setEffect(SkNEW_ARGS(GrConical2Gradient, (context, *this, fTileMode)), matrix)->unref(); + stage->setEffect(SkNEW_ARGS(GrConical2Gradient, (context, *this, matrix, fTileMode)))->unref(); return true; } diff --git a/src/effects/gradients/SkTwoPointRadialGradient.cpp b/src/effects/gradients/SkTwoPointRadialGradient.cpp index 659bce0099..d0186291f2 100644 --- a/src/effects/gradients/SkTwoPointRadialGradient.cpp +++ b/src/effects/gradients/SkTwoPointRadialGradient.cpp @@ -404,8 +404,11 @@ private: class GrRadial2Gradient : public GrGradientEffect { public: - GrRadial2Gradient(GrContext* ctx, const SkTwoPointRadialGradient& shader, SkShader::TileMode tm) - : INHERITED(ctx, shader, tm) + GrRadial2Gradient(GrContext* ctx, + const SkTwoPointRadialGradient& shader, + const SkMatrix& matrix, + SkShader::TileMode tm) + : INHERITED(ctx, shader, matrix, tm) , fCenterX1(shader.getCenterX1()) , fRadius0(shader.getStartRadius()) , fPosRoot(shader.getDiffRadius() < 0) { } @@ -501,14 +504,19 @@ GrGLRadial2Gradient::GrGLRadial2Gradient( } void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder, - const GrEffectStage&, - EffectKey, + const GrEffectStage& stage, + EffectKey key, const char* vertexCoords, const char* outputColor, const char* inputColor, const TextureSamplerArray& samplers) { this->emitYCoordUniform(builder); + const char* fsCoords; + const char* vsCoordsVarying; + GrSLType coordsVaryingType; + this->setupMatrix(builder, key, vertexCoords, &fsCoords, &vsCoordsVarying, &coordsVaryingType); + // 2 copies of uniform array, 1 for each of vertex & fragment shader, // to work around Xoom bug. Doesn't seem to cause performance decrease // in test apps, but need to keep an eye on it. @@ -519,9 +527,8 @@ void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder, // For radial gradients without perspective we can pass the linear // part of the quadratic as a varying. - if (!builder->defaultTextureMatrixIsPerspective()) { - builder->addVarying(kFloat_GrSLType, "Radial2BCoeff", - &fVSVaryingName, &fFSVaryingName); + if (kVec2f_GrSLType == coordsVaryingType) { + builder->addVarying(kFloat_GrSLType, "Radial2BCoeff", &fVSVaryingName, &fFSVaryingName); } // VS @@ -534,11 +541,11 @@ void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder, // For radial gradients without perspective we can pass the linear // part of the quadratic as a varying. - if (!builder->defaultTextureMatrixIsPerspective()) { + if (kVec2f_GrSLType == coordsVaryingType) { // r2Var = 2 * (r2Parm[2] * varCoord.x - r2Param[3]) code->appendf("\t%s = 2.0 *(%s * %s.x - %s);\n", fVSVaryingName, p2.c_str(), - vertexCoords, p3.c_str()); + vsCoordsVarying, p3.c_str()); } } @@ -565,20 +572,19 @@ void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder, // If we we're able to interpolate the linear component, // bVar is the varying; otherwise compute it SkString bVar; - if (!builder->defaultTextureMatrixIsPerspective()) { + if (kVec2f_GrSLType == coordsVaryingType) { bVar = fFSVaryingName; } else { bVar = "b"; code->appendf("\tfloat %s = 2.0 * (%s * %s.x - %s);\n", - bVar.c_str(), p2.c_str(), - builder->defaultTexCoordsName(), p3.c_str()); + bVar.c_str(), p2.c_str(), fsCoords, p3.c_str()); } // c = (x^2)+(y^2) - params[4] code->appendf("\tfloat %s = dot(%s, %s) - %s;\n", cName.c_str(), - builder->defaultTexCoordsName(), - builder->defaultTexCoordsName(), + fsCoords, + fsCoords, p4.c_str()); // If we aren't degenerate, emit some extra code, and accept a slightly @@ -643,7 +649,15 @@ void GrGLRadial2Gradient::setData(const GrGLUniformManager& uman, const GrEffect } GrGLEffect::EffectKey GrGLRadial2Gradient::GenKey(const GrEffectStage& s, const GrGLCaps&) { - return (static_cast<const GrRadial2Gradient&>(*s.getEffect()).isDegenerate()); + enum { + kIsDegenerate = 1 << kMatrixKeyBitCnt, + }; + + EffectKey key = GenMatrixKey(s); + if (static_cast<const GrRadial2Gradient&>(*s.getEffect()).isDegenerate()) { + key |= kIsDegenerate; + } + return key; } ///////////////////////////////////////////////////////////////////// @@ -667,7 +681,7 @@ bool SkTwoPointRadialGradient::asNewEffect(GrContext* context, matrix.postConcat(rot); } - stage->setEffect(SkNEW_ARGS(GrRadial2Gradient, (context, *this, fTileMode)), matrix)->unref(); + stage->setEffect(SkNEW_ARGS(GrRadial2Gradient, (context, *this, matrix, fTileMode)))->unref(); return true; } |