aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkShader.h4
-rw-r--r--src/effects/SkGradientShader.cpp3
-rw-r--r--src/gpu/SkGpuDevice.cpp11
-rw-r--r--src/gpu/effects/GrGradientEffects.cpp178
-rw-r--r--src/gpu/effects/GrGradientEffects.h61
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