diff options
-rw-r--r-- | include/core/SkShader.h | 4 | ||||
-rw-r--r-- | src/effects/SkGradientShader.cpp | 3 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 11 | ||||
-rw-r--r-- | src/gpu/effects/GrGradientEffects.cpp | 178 | ||||
-rw-r--r-- | src/gpu/effects/GrGradientEffects.h | 61 |
5 files changed, 203 insertions, 54 deletions
diff --git a/include/core/SkShader.h b/include/core/SkShader.h index 435643e1d3..7108c34e45 100644 --- a/include/core/SkShader.h +++ b/include/core/SkShader.h @@ -222,8 +222,10 @@ public: // to first. // 1: radius of first circle // 2: the second radius minus the first radius + kLinear_BitmapType, //<! Access bitmap using local coords transformed + // by matrix. No extras - kLast_BitmapType = kTwoPointConical_BitmapType + kLast_BitmapType = kLinear_BitmapType }; /** Optional methods for shaders that can pretend to be a bitmap/texture to play along with opengl. Default just returns kNone_BitmapType and diff --git a/src/effects/SkGradientShader.cpp b/src/effects/SkGradientShader.cpp index 559e711cfe..b86c4e2e8a 100644 --- a/src/effects/SkGradientShader.cpp +++ b/src/effects/SkGradientShader.cpp @@ -1026,14 +1026,13 @@ SkShader::BitmapType Linear_Gradient::asABitmap(SkBitmap* bitmap, this->commonAsABitmap(bitmap); } if (matrix) { - matrix->setScale(SkIntToScalar(kGradient32Length), SK_Scalar1); matrix->preConcat(fPtsToUnit); } if (xy) { xy[0] = fTileMode; xy[1] = kClamp_TileMode; } - return kDefault_BitmapType; + return kLinear_BitmapType; } SkShader::GradientType Linear_Gradient::asAGradient(GradientInfo* info) const { diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 605b640197..4e3baa3653 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -441,7 +441,8 @@ SK_COMPILE_ASSERT(SkShader::kTwoPointRadial_BitmapType == 4, shader_type_mismatch); SK_COMPILE_ASSERT(SkShader::kTwoPointConical_BitmapType == 5, shader_type_mismatch); -SK_COMPILE_ASSERT(SkShader::kLast_BitmapType == 5, shader_type_mismatch); +SK_COMPILE_ASSERT(SkShader::kLinear_BitmapType == 6, shader_type_mismatch); +SK_COMPILE_ASSERT(SkShader::kLast_BitmapType == 6, shader_type_mismatch); namespace { @@ -607,6 +608,14 @@ inline bool skPaint2GrPaintShader(SkGpuDevice* dev, twoPointParams[2])))->unref(); sampler->setFilter(GrSamplerState::kBilinear_Filter); break; + case SkShader::kLinear_BitmapType: + sampler->setCustomStage(SkNEW_ARGS(GrLinearGradient, (texture)))->unref(); + if (skPaint.isFilterBitmap()) { + sampler->setFilter(GrSamplerState::kBilinear_Filter); + } else { + sampler->setFilter(GrSamplerState::kNearest_Filter); + } + break; default: if (skPaint.isFilterBitmap()) { sampler->setFilter(GrSamplerState::kBilinear_Filter); diff --git a/src/gpu/effects/GrGradientEffects.cpp b/src/gpu/effects/GrGradientEffects.cpp index 988717a367..ec465b815b 100644 --- a/src/gpu/effects/GrGradientEffects.cpp +++ b/src/gpu/effects/GrGradientEffects.cpp @@ -9,9 +9,117 @@ #include "gl/GrGLProgramStage.h" #include "GrProgramStageFactory.h" +// Base class for GL gradient custom stages +class GrGLGradientStage : public GrGLProgramStage { +public: + + GrGLGradientStage(const GrProgramStageFactory& factory); + virtual ~GrGLGradientStage(); + + // emit code that gets a fragment's color from an expression for t; for now + // this always uses the texture, but for simpler cases we'll be able to lerp + void emitColorLookup(GrGLShaderBuilder* builder, const char* t, + const char* outputColor, const char* samplerName); + +private: + + typedef GrGLProgramStage INHERITED; +}; + +GrGLGradientStage::GrGLGradientStage(const GrProgramStageFactory& factory) + : INHERITED(factory) { } + +GrGLGradientStage::~GrGLGradientStage() { } + +void GrGLGradientStage::emitColorLookup(GrGLShaderBuilder* builder, + const char* tName, + const char* outputColor, + const char* samplerName) { + // Texture is effectively 1D so the y coordinate is 0.5, if we pack multiple + // gradients into a texture, we could instead pick the appropriate row here + builder->fSampleCoords.printf("vec2(%s, 0.5)", tName); + builder->fComplexCoord = true; + builder->emitDefaultFetch(outputColor, samplerName); +} + +///////////////////////////////////////////////////////////////////// + +GrGradientEffect::GrGradientEffect(GrTexture* texture) + : fTexture (texture) + , fUseTexture(true) { + SkSafeRef(fTexture); +} + +GrGradientEffect::~GrGradientEffect() { + if (fTexture) { + SkSafeUnref(fTexture); + } +} + +unsigned int GrGradientEffect::numTextures() const { + return fUseTexture ? 1 : 0; +} + +GrTexture* GrGradientEffect::texture(unsigned int index) + const { + GrAssert(fUseTexture && 0 == index); + return fTexture; +} + +///////////////////////////////////////////////////////////////////// + +class GrGLLinearGradient : public GrGLGradientStage { +public: + + GrGLLinearGradient(const GrProgramStageFactory& factory, + const GrCustomStage&) + : INHERITED (factory) { } + + virtual ~GrGLLinearGradient() { } + + virtual void emitVS(GrGLShaderBuilder* builder, + const char* vertexCoords) SK_OVERRIDE { } + virtual void emitFS(GrGLShaderBuilder* builder, + const char* outputColor, + const char* inputColor, + const char* samplerName) SK_OVERRIDE; + static StageKey GenKey(const GrCustomStage& s) { return 0; } + +private: + + typedef GrGLGradientStage INHERITED; +}; + +void GrGLLinearGradient::emitFS(GrGLShaderBuilder* builder, + const char* outputColor, + const char* inputColor, + const char* samplerName) { + SkString t; + t.printf("%s.x", builder->fSampleCoords.c_str()); + this->emitColorLookup(builder, t.c_str(), outputColor, samplerName); +} + ///////////////////////////////////////////////////////////////////// -class GrGLRadialGradient : public GrGLProgramStage { +GrLinearGradient::GrLinearGradient(GrTexture* texture) + : INHERITED(texture) { +} + +GrLinearGradient::~GrLinearGradient() { + +} + +const GrProgramStageFactory& GrLinearGradient::getFactory() const { + return GrTProgramStageFactory<GrLinearGradient>::getInstance(); +} + +bool GrLinearGradient::isEqual(const GrCustomStage& sBase) const { + return INHERITED::isEqual(sBase); +} + +///////////////////////////////////////////////////////////////////// + +class GrGLRadialGradient : public GrGLGradientStage { public: @@ -30,7 +138,7 @@ public: private: - typedef GrGLProgramStage INHERITED; + typedef GrGLGradientStage INHERITED; }; @@ -38,11 +146,9 @@ void GrGLRadialGradient::emitFS(GrGLShaderBuilder* builder, const char* outputColor, const char* inputColor, const char* samplerName) { - builder->fSampleCoords.printf("vec2(length(%s.xy), 0.5)", - builder->fSampleCoords.c_str()); - builder->fComplexCoord = true; - - builder->emitDefaultFetch(outputColor, samplerName); + SkString t; + t.printf("length(%s.xy)", builder->fSampleCoords.c_str()); + this->emitColorLookup(builder, t.c_str(), outputColor, samplerName); } @@ -50,7 +156,7 @@ void GrGLRadialGradient::emitFS(GrGLShaderBuilder* builder, GrRadialGradient::GrRadialGradient(GrTexture* texture) - : GrSingleTextureEffect(texture) { + : INHERITED(texture) { } @@ -73,7 +179,7 @@ bool GrRadialGradient::isEqual(const GrCustomStage& sBase) const { typedef GrGLShaderBuilder::UniformHandle UniformHandle; static const UniformHandle kInvalidUniformHandle = GrGLShaderBuilder::kInvalidUniformHandle; -class GrGLRadial2Gradient : public GrGLProgramStage { +class GrGLRadial2Gradient : public GrGLGradientStage { public: @@ -124,7 +230,7 @@ protected: private: - typedef GrGLProgramStage INHERITED; + typedef GrGLGradientStage INHERITED; }; @@ -191,6 +297,7 @@ void GrGLRadial2Gradient::emitFS(GrGLShaderBuilder* builder, SkString cName("c"); SkString ac4Name("ac4"); SkString rootName("root"); + SkString t; SkString p0; SkString p1; SkString p2; @@ -240,20 +347,15 @@ void GrGLRadial2Gradient::emitFS(GrGLShaderBuilder* builder, rootName.c_str(), bVar.c_str(), bVar.c_str(), ac4Name.c_str()); - // x coord is: (-b + params[5] * sqrt(b^2-4ac)) * params[1] - // y coord is 0.5 (texture is effectively 1D) - builder->fSampleCoords.printf("vec2((-%s + %s * %s) * %s, 0.5)", - bVar.c_str(), p5.c_str(), - rootName.c_str(), p1.c_str()); + // t is: (-b + params[5] * sqrt(b^2-4ac)) * params[1] + t.printf("(-%s + %s * %s) * %s", bVar.c_str(), p5.c_str(), + rootName.c_str(), p1.c_str()); } else { - // x coord is: -c/b - // y coord is 0.5 (texture is effectively 1D) - builder->fSampleCoords.printf("vec2((-%s / %s), 0.5)", - cName.c_str(), bVar.c_str()); + // t is: -c/b + t.printf("-%s / %s", cName.c_str(), bVar.c_str()); } - builder->fComplexCoord = true; - builder->emitDefaultFetch(outputColor, samplerName); + this->emitColorLookup(builder, t.c_str(), outputColor, samplerName); } void GrGLRadial2Gradient::initUniforms(const GrGLShaderBuilder* builder, @@ -309,7 +411,7 @@ GrRadial2Gradient::GrRadial2Gradient(GrTexture* texture, GrScalar center, GrScalar radius, bool posRoot) - : GrSingleTextureEffect(texture) + : INHERITED(texture) , fCenterX1 (center) , fRadius0 (radius) , fPosRoot (posRoot) { @@ -335,7 +437,7 @@ bool GrRadial2Gradient::isEqual(const GrCustomStage& sBase) const { ///////////////////////////////////////////////////////////////////// -class GrGLConical2Gradient : public GrGLProgramStage { +class GrGLConical2Gradient : public GrGLGradientStage { public: @@ -386,7 +488,7 @@ protected: private: - typedef GrGLProgramStage INHERITED; + typedef GrGLGradientStage INHERITED; }; @@ -536,10 +638,8 @@ void GrGLConical2Gradient::emitFS(GrGLShaderBuilder* builder, code->appendf("\t\tif (%s * %s + %s > 0.0) {\n", tName.c_str(), p5.c_str(), p3.c_str()); - // y coord is 0.5 (texture is effectively 1D) code->appendf("\t\t"); - builder->fSampleCoords.printf("vec2(%s, 0.5)", tName.c_str()); - builder->emitDefaultFetch(outputColor, samplerName); + this->emitColorLookup(builder, tName.c_str(), outputColor, samplerName); // otherwise, if r(t) for the larger root was <= 0, try the other root code->appendf("\t\t} else {\n"); @@ -550,10 +650,8 @@ void GrGLConical2Gradient::emitFS(GrGLShaderBuilder* builder, code->appendf("\t\t\tif (%s * %s + %s > 0.0) {\n", tName.c_str(), p5.c_str(), p3.c_str()); - // y coord is 0.5 (texture is effectively 1D) code->appendf("\t\t\t"); - builder->fSampleCoords.printf("vec2(%s, 0.5)", tName.c_str()); - builder->emitDefaultFetch(outputColor, samplerName); + this->emitColorLookup(builder, tName.c_str(), outputColor, samplerName); // end if (r(t) > 0) for smaller root code->appendf("\t\t\t}\n"); @@ -571,11 +669,9 @@ void GrGLConical2Gradient::emitFS(GrGLShaderBuilder* builder, code->appendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(), p5.c_str(), p3.c_str()); code->appendf("\t"); - builder->fSampleCoords.printf("vec2(%s, 0.5)", tName.c_str()); - builder->emitDefaultFetch(outputColor, samplerName); + this->emitColorLookup(builder, tName.c_str(), outputColor, samplerName); code->appendf("\t}\n"); } - builder->fComplexCoord = true; } void GrGLConical2Gradient::initUniforms(const GrGLShaderBuilder* builder, @@ -633,7 +729,7 @@ GrConical2Gradient::GrConical2Gradient(GrTexture* texture, GrScalar center, GrScalar radius, GrScalar diffRadius) - : GrSingleTextureEffect (texture) + : INHERITED (texture) , fCenterX1 (center) , fRadius0 (radius) , fDiffRadius (diffRadius) { @@ -660,7 +756,7 @@ bool GrConical2Gradient::isEqual(const GrCustomStage& sBase) const { ///////////////////////////////////////////////////////////////////// -class GrGLSweepGradient : public GrGLProgramStage { +class GrGLSweepGradient : public GrGLGradientStage { public: @@ -679,7 +775,7 @@ public: private: - typedef GrGLProgramStage INHERITED; + typedef GrGLGradientStage INHERITED; }; @@ -687,18 +783,16 @@ void GrGLSweepGradient::emitFS(GrGLShaderBuilder* builder, const char* outputColor, const char* inputColor, const char* samplerName) { - builder->fSampleCoords.printf( - "vec2(atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5, 0.5)", + SkString t; + t.printf("atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5", builder->fSampleCoords.c_str(), builder->fSampleCoords.c_str()); - builder->fComplexCoord = true; - - builder->emitDefaultFetch(outputColor, samplerName); + this->emitColorLookup(builder, t.c_str(), outputColor, samplerName); } ///////////////////////////////////////////////////////////////////// GrSweepGradient::GrSweepGradient(GrTexture* texture) - : GrSingleTextureEffect(texture) { + : INHERITED(texture) { } diff --git a/src/gpu/effects/GrGradientEffects.h b/src/gpu/effects/GrGradientEffects.h index 37e4642eab..eb1a8f2739 100644 --- a/src/gpu/effects/GrGradientEffects.h +++ b/src/gpu/effects/GrGradientEffects.h @@ -35,9 +35,54 @@ * determines the gradient value. */ +// Base class for Gr gradient effects +class GrGradientEffect : public GrCustomStage { +public: + + GrGradientEffect(GrTexture* texture); + + // TODO: Look at a GradientInfo and make the texture only if necessary + // GrGradientEffect(GrContext* ctx, GradientInfo* info); + + virtual ~GrGradientEffect(); + + unsigned int numTextures() const; + GrTexture* texture(unsigned int index) const; + + bool useTexture() const { return fUseTexture; } + +private: + + GrTexture* fTexture; + bool fUseTexture; + + typedef GrCustomStage INHERITED; + +}; + +class GrGLLinearGradient; + +class GrLinearGradient : public GrGradientEffect { + +public: + + GrLinearGradient(GrTexture* texture); + virtual ~GrLinearGradient(); + + static const char* Name() { return "Linear Gradient"; } + virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE; + virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE; + + typedef GrGLLinearGradient GLProgramStage; + +private: + + typedef GrGradientEffect INHERITED; +}; + class GrGLRadialGradient; -class GrRadialGradient : public GrSingleTextureEffect { +class GrRadialGradient : public GrGradientEffect { public: @@ -52,12 +97,12 @@ public: private: - typedef GrSingleTextureEffect INHERITED; + typedef GrGradientEffect INHERITED; }; class GrGLRadial2Gradient; -class GrRadial2Gradient : public GrSingleTextureEffect { +class GrRadial2Gradient : public GrGradientEffect { public: @@ -88,12 +133,12 @@ private: // @} - typedef GrSingleTextureEffect INHERITED; + typedef GrGradientEffect INHERITED; }; class GrGLConical2Gradient; -class GrConical2Gradient : public GrSingleTextureEffect { +class GrConical2Gradient : public GrGradientEffect { public: @@ -124,12 +169,12 @@ private: // @} - typedef GrSingleTextureEffect INHERITED; + typedef GrGradientEffect INHERITED; }; class GrGLSweepGradient; -class GrSweepGradient : public GrSingleTextureEffect { +class GrSweepGradient : public GrGradientEffect { public: @@ -144,7 +189,7 @@ public: protected: - typedef GrSingleTextureEffect INHERITED; + typedef GrGradientEffect INHERITED; }; #endif |