aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/tests.gyp1
-rw-r--r--include/gpu/GrEffect.h12
-rw-r--r--include/gpu/GrPaint.h34
-rw-r--r--src/effects/SkBitmapAlphaThresholdShader.cpp2
-rw-r--r--src/effects/SkColorFilters.cpp290
-rw-r--r--src/effects/SkDisplacementMapEffect.cpp1
-rw-r--r--src/effects/SkMatrixConvolutionImageFilter.cpp2
-rw-r--r--src/effects/SkPerlinNoiseShader.cpp1
-rw-r--r--src/effects/gradients/SkGradientShader.cpp4
-rw-r--r--src/gpu/GrAAConvexPathRenderer.cpp2
-rw-r--r--src/gpu/GrAARectRenderer.cpp4
-rw-r--r--src/gpu/GrDrawState.cpp8
-rw-r--r--src/gpu/GrDrawState.h18
-rw-r--r--src/gpu/GrOvalRenderer.cpp6
-rw-r--r--src/gpu/GrPaint.cpp6
-rw-r--r--src/gpu/SkGpuDevice.cpp7
-rw-r--r--src/gpu/effects/GrBezierEffect.cpp6
-rw-r--r--src/gpu/effects/GrBicubicEffect.cpp4
-rw-r--r--src/gpu/gl/GrGLProgram.cpp164
-rw-r--r--src/gpu/gl/GrGLProgram.h2
-rw-r--r--src/gpu/gl/GrGLProgramDesc.cpp48
-rw-r--r--src/gpu/gl/GrGLProgramDesc.h1
-rw-r--r--src/gpu/gl/GrGLSL.cpp2
-rw-r--r--src/gpu/gl/GrGLSL.h242
-rw-r--r--src/gpu/gl/GrGLSL_impl.h221
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.cpp24
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.h20
-rw-r--r--tests/GLProgramsTest.cpp3
-rw-r--r--tests/GpuColorFilterTest.cpp131
29 files changed, 795 insertions, 471 deletions
diff --git a/gyp/tests.gyp b/gyp/tests.gyp
index 4c61a5c964..5a3ae4da80 100644
--- a/gyp/tests.gyp
+++ b/gyp/tests.gyp
@@ -69,6 +69,7 @@
'../tests/GLInterfaceValidation.cpp',
'../tests/GLProgramsTest.cpp',
'../tests/GpuBitmapCopyTest.cpp',
+ '../tests/GpuColorFilterTest.cpp',
'../tests/GpuDrawPathTest.cpp',
'../tests/GrContextFactoryTest.cpp',
'../tests/GradientTest.cpp',
diff --git a/include/gpu/GrEffect.h b/include/gpu/GrEffect.h
index 78752702f5..5fed5329fb 100644
--- a/include/gpu/GrEffect.h
+++ b/include/gpu/GrEffect.h
@@ -95,6 +95,9 @@ public:
*/
virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const = 0;
+ /** Will this effect read the source color value? */
+ bool willUseInputColor() const { return fWillUseInputColor; }
+
/** This object, besides creating back-end-specific helper objects, is used for run-time-type-
identification. The factory should be an instance of templated class,
GrTBackendEffectFactory. It is templated on the subclass of GrEffect. The subclass must have
@@ -221,6 +224,7 @@ protected:
GrEffect()
: fWillReadDstColor(false)
, fWillReadFragmentPosition(false)
+ , fWillUseInputColor(true)
, fHasVertexCode(false)
, fEffectRef(NULL) {}
@@ -287,6 +291,13 @@ protected:
*/
void setWillReadFragmentPosition() { fWillReadFragmentPosition = true; }
+ /**
+ * If the effect will generate a result that does not depend on the input color value then it must
+ * call this function from its constructor. Otherwise, when its generated backend-specific code
+ * might fail during variable binding due to unused variables.
+ */
+ void setWillNotUseInputColor() { fWillUseInputColor = false; }
+
private:
bool isEqual(const GrEffect& other) const {
if (&this->getFactory() != &other.getFactory()) {
@@ -321,6 +332,7 @@ private:
SkSTArray<kMaxVertexAttribs, GrSLType, true> fVertexAttribTypes;
bool fWillReadDstColor;
bool fWillReadFragmentPosition;
+ bool fWillUseInputColor;
bool fHasVertexCode;
GrEffectRef* fEffectRef;
diff --git a/include/gpu/GrPaint.h b/include/gpu/GrPaint.h
index 25557f9b9a..50a32a5743 100644
--- a/include/gpu/GrPaint.h
+++ b/include/gpu/GrPaint.h
@@ -85,31 +85,13 @@ public:
bool isDither() const { return fDither; }
/**
- * Enables a SkXfermode::Mode-based color filter applied to the primitive color. The constant
- * color passed to this function is considered the "src" color and the primitive's color is
- * considered the "dst" color. Defaults to kDst_Mode which equates to simply passing through
- * the primitive color unmodified.
- */
- void setXfermodeColorFilter(SkXfermode::Mode mode, GrColor color) {
- fColorFilterColor = color;
- fColorFilterXfermode = mode;
- }
- SkXfermode::Mode getColorFilterMode() const { return fColorFilterXfermode; }
- GrColor getColorFilterColor() const { return fColorFilterColor; }
-
- /**
- * Disables the SkXfermode::Mode color filter.
- */
- void resetColorFilter() {
- fColorFilterXfermode = SkXfermode::kDst_Mode;
- fColorFilterColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
- }
-
- /**
* Appends an additional color effect to the color computation.
*/
const GrEffectRef* addColorEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) {
SkASSERT(NULL != effect);
+ if (!(*effect)->willUseInputColor()) {
+ fColorStages.reset();
+ }
SkNEW_APPEND_TO_TARRAY(&fColorStages, GrEffectStage, (effect, attr0, attr1));
return effect;
}
@@ -119,6 +101,9 @@ public:
*/
const GrEffectRef* addCoverageEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) {
SkASSERT(NULL != effect);
+ if (!(*effect)->willUseInputColor()) {
+ fCoverageStages.reset();
+ }
SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrEffectStage, (effect, attr0, attr1));
return effect;
}
@@ -153,9 +138,6 @@ public:
fColor = paint.fColor;
fCoverage = paint.fCoverage;
- fColorFilterColor = paint.fColorFilterColor;
- fColorFilterXfermode = paint.fColorFilterXfermode;
-
fColorStages = paint.fColorStages;
fCoverageStages = paint.fCoverageStages;
@@ -171,7 +153,6 @@ public:
this->resetColor();
this->resetCoverage();
this->resetStages();
- this->resetColorFilter();
}
/**
@@ -245,9 +226,6 @@ private:
GrColor fColor;
uint8_t fCoverage;
- GrColor fColorFilterColor;
- SkXfermode::Mode fColorFilterXfermode;
-
void resetBlend() {
fSrcBlendCoeff = kOne_GrBlendCoeff;
fDstBlendCoeff = kZero_GrBlendCoeff;
diff --git a/src/effects/SkBitmapAlphaThresholdShader.cpp b/src/effects/SkBitmapAlphaThresholdShader.cpp
index 6f1c94a310..7fb09fdbc3 100644
--- a/src/effects/SkBitmapAlphaThresholdShader.cpp
+++ b/src/effects/SkBitmapAlphaThresholdShader.cpp
@@ -150,7 +150,7 @@ public:
"\t\t}\n");
builder->fsCodeAppendf("color = %s = %s;\n", outputColor,
- (GrGLSLExpr<4>(inputColor) * GrGLSLExpr<4>("color")).c_str());
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr4("color")).c_str());
}
virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect& e) SK_OVERRIDE {
diff --git a/src/effects/SkColorFilters.cpp b/src/effects/SkColorFilters.cpp
index a821129e85..66ddb0250a 100644
--- a/src/effects/SkColorFilters.cpp
+++ b/src/effects/SkColorFilters.cpp
@@ -85,6 +85,9 @@ public:
}
#endif
+#if SK_SUPPORT_GPU
+ virtual GrEffectRef* asNewEffect(GrContext*) const SK_OVERRIDE;
+#endif
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
protected:
@@ -117,6 +120,293 @@ private:
typedef SkColorFilter INHERITED;
};
+///////////////////////////////////////////////////////////////////////////////
+#if SK_SUPPORT_GPU
+#include "GrBlend.h"
+#include "GrEffect.h"
+#include "GrEffectUnitTest.h"
+#include "GrTBackendEffectFactory.h"
+#include "gl/GrGLEffect.h"
+#include "SkGr.h"
+
+namespace {
+/**
+ * A definition of blend equation for one coefficient. Generates a
+ * blend_coeff * value "expression".
+ */
+template<typename ColorExpr>
+static inline ColorExpr blend_term(SkXfermode::Coeff coeff,
+ const ColorExpr& src,
+ const ColorExpr& dst,
+ const ColorExpr& value) {
+ switch (coeff) {
+ default:
+ GrCrash("Unexpected xfer coeff.");
+ case SkXfermode::kZero_Coeff: /** 0 */
+ return ColorExpr(0);
+ case SkXfermode::kOne_Coeff: /** 1 */
+ return value;
+ case SkXfermode::kSC_Coeff:
+ return src * value;
+ case SkXfermode::kISC_Coeff:
+ return (ColorExpr(1) - src) * dst;
+ case SkXfermode::kDC_Coeff:
+ return dst * value;
+ case SkXfermode::kIDC_Coeff:
+ return (ColorExpr(1) - dst) * value;
+ case SkXfermode::kSA_Coeff: /** src alpha */
+ return src.a() * value;
+ case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */
+ return (typename ColorExpr::AExpr(1) - src.a()) * value;
+ case SkXfermode::kDA_Coeff: /** dst alpha */
+ return dst.a() * value;
+ case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */
+ return (typename ColorExpr::AExpr(1) - dst.a()) * value;
+ }
+}
+/**
+ * Creates a color filter expression which modifies the color by
+ * the specified color filter.
+ */
+template <typename ColorExpr>
+static inline ColorExpr color_filter_expression(const SkXfermode::Mode& mode,
+ const ColorExpr& filterColor,
+ const ColorExpr& inColor) {
+ SkXfermode::Coeff colorCoeff;
+ SkXfermode::Coeff filterColorCoeff;
+ SkAssertResult(SkXfermode::ModeAsCoeff(mode, &filterColorCoeff, &colorCoeff));
+ return blend_term(colorCoeff, filterColor, inColor, inColor) +
+ blend_term(filterColorCoeff, filterColor, inColor, filterColor);
+}
+
+}
+
+class ModeColorFilterEffect : public GrEffect {
+public:
+ static GrEffectRef* Create(const GrColor& c, SkXfermode::Mode mode) {
+ AutoEffectUnref effect(SkNEW_ARGS(ModeColorFilterEffect, (c, mode)));
+ return CreateEffectRef(effect);
+ }
+
+ virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
+
+ bool willUseFilterColor() const {
+ SkXfermode::Coeff dstCoeff;
+ SkXfermode::Coeff srcCoeff;
+ SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
+ if (SkXfermode::kZero_Coeff == srcCoeff) {
+ return GrBlendCoeffRefsSrc(sk_blend_to_grblend(dstCoeff));
+ }
+ return true;
+ }
+
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
+ return GrTBackendEffectFactory<ModeColorFilterEffect>::getInstance();
+ }
+
+ static const char* Name() { return "ModeColorFilterEffect"; }
+
+ SkXfermode::Mode mode() const { return fMode; }
+ GrColor color() const { return fColor; }
+
+ class GLEffect : public GrGLEffect {
+ public:
+ GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
+ : INHERITED(factory) {
+ }
+
+ virtual void emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray& coords,
+ const TextureSamplerArray& samplers) SK_OVERRIDE {
+ SkXfermode::Mode mode = drawEffect.castEffect<ModeColorFilterEffect>().mode();
+
+ SkASSERT(SkXfermode::kDst_Mode != mode);
+ const char* colorFilterColorUniName = NULL;
+ if (drawEffect.castEffect<ModeColorFilterEffect>().willUseFilterColor()) {
+ fFilterColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType, "FilterColor",
+ &colorFilterColorUniName);
+ }
+
+ GrGLSLExpr4 filter =
+ color_filter_expression(mode, GrGLSLExpr4(colorFilterColorUniName), GrGLSLExpr4(inputColor));
+
+ builder->fsCodeAppendf("\t%s = %s;\n", outputColor, filter.c_str());
+ }
+
+ static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
+ const ModeColorFilterEffect& colorModeFilter = drawEffect.castEffect<ModeColorFilterEffect>();
+ // The SL code does not depend on filter color at the moment, so no need to represent it
+ // in the key.
+ EffectKey modeKey = colorModeFilter.mode();
+ return modeKey;
+ }
+
+ virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) SK_OVERRIDE {
+ if (fFilterColorUni.isValid()) {
+ const ModeColorFilterEffect& colorModeFilter = drawEffect.castEffect<ModeColorFilterEffect>();
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(colorModeFilter.color(), c);
+ uman.set4fv(fFilterColorUni, 0, 1, c);
+ }
+ }
+
+ private:
+
+ GrGLUniformManager::UniformHandle fFilterColorUni;
+ typedef GrGLEffect INHERITED;
+ };
+
+ GR_DECLARE_EFFECT_TEST;
+
+private:
+ ModeColorFilterEffect(GrColor color, SkXfermode::Mode mode)
+ : fMode(mode),
+ fColor(color) {
+
+ SkXfermode::Coeff dstCoeff;
+ SkXfermode::Coeff srcCoeff;
+ SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
+ // These could be calculated from the blend equation with template trickery..
+ if (SkXfermode::kZero_Coeff == dstCoeff && !GrBlendCoeffRefsDst(sk_blend_to_grblend(srcCoeff))) {
+ this->setWillNotUseInputColor();
+ }
+ }
+
+ virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
+ const ModeColorFilterEffect& s = CastEffect<ModeColorFilterEffect>(other);
+ return fMode == s.fMode && fColor == s.fColor;
+ }
+
+ SkXfermode::Mode fMode;
+ GrColor fColor;
+
+ typedef GrEffect INHERITED;
+};
+
+namespace {
+
+/** Function color_component_to_int tries to reproduce the GLSL rounding. The spec doesn't specify
+ * to which direction the 0.5 goes.
+ */
+static inline int color_component_to_int(float value) {
+ return sk_float_round2int(GrMax(0.f, GrMin(1.f, value)) * 255.f);
+}
+
+/** MaskedColorExpr is used to evaluate the color and valid color component flags through the
+ * blending equation. It has members similar to GrGLSLExpr so that it can be used with the
+ * templated helpers above.
+ */
+class MaskedColorExpr {
+public:
+ MaskedColorExpr(const float color[], uint32_t flags)
+ : fFlags(flags) {
+ fColor[0] = color[0];
+ fColor[1] = color[1];
+ fColor[2] = color[2];
+ fColor[3] = color[3];
+ }
+
+ MaskedColorExpr(float v, uint32_t flags = kRGBA_GrColorComponentFlags)
+ : fFlags(flags) {
+ fColor[0] = v;
+ fColor[1] = v;
+ fColor[2] = v;
+ fColor[3] = v;
+ }
+
+ MaskedColorExpr operator*(const MaskedColorExpr& other) const {
+ float tmp[4];
+ tmp[0] = fColor[0] * other.fColor[0];
+ tmp[1] = fColor[1] * other.fColor[1];
+ tmp[2] = fColor[2] * other.fColor[2];
+ tmp[3] = fColor[3] * other.fColor[3];
+
+ return MaskedColorExpr(tmp, fFlags & other.fFlags);
+ }
+
+ MaskedColorExpr operator+(const MaskedColorExpr& other) const {
+ float tmp[4];
+ tmp[0] = fColor[0] + other.fColor[0];
+ tmp[1] = fColor[1] + other.fColor[1];
+ tmp[2] = fColor[2] + other.fColor[2];
+ tmp[3] = fColor[3] + other.fColor[3];
+
+ return MaskedColorExpr(tmp, fFlags & other.fFlags);
+ }
+
+ MaskedColorExpr operator-(const MaskedColorExpr& other) const {
+ float tmp[4];
+ tmp[0] = fColor[0] - other.fColor[0];
+ tmp[1] = fColor[1] - other.fColor[1];
+ tmp[2] = fColor[2] - other.fColor[2];
+ tmp[3] = fColor[3] - other.fColor[3];
+
+ return MaskedColorExpr(tmp, fFlags & other.fFlags);
+ }
+
+ MaskedColorExpr a() const {
+ uint32_t flags = (fFlags & kA_GrColorComponentFlag) ? kRGBA_GrColorComponentFlags : 0;
+ return MaskedColorExpr(fColor[3], flags);
+ }
+
+ GrColor getColor() const {
+ return GrColorPackRGBA(color_component_to_int(fColor[0]),
+ color_component_to_int(fColor[1]),
+ color_component_to_int(fColor[2]),
+ color_component_to_int(fColor[3]));
+ }
+
+ uint32_t getValidComponents() const { return fFlags; }
+
+ typedef MaskedColorExpr AExpr;
+private:
+ float fColor[4];
+ uint32_t fFlags;
+};
+
+}
+
+void ModeColorFilterEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
+ float inputColor[4];
+ GrColorToRGBAFloat(*color, inputColor);
+ float filterColor[4];
+ GrColorToRGBAFloat(fColor, filterColor);
+ MaskedColorExpr result =
+ color_filter_expression(fMode,
+ MaskedColorExpr(filterColor, kRGBA_GrColorComponentFlags),
+ MaskedColorExpr(inputColor, *validFlags));
+
+ *color = result.getColor();
+ *validFlags = result.getValidComponents();
+}
+
+GR_DEFINE_EFFECT_TEST(ModeColorFilterEffect);
+GrEffectRef* ModeColorFilterEffect::TestCreate(SkRandom* rand,
+ GrContext*,
+ const GrDrawTargetCaps&,
+ GrTexture*[]) {
+ int mode = rand->nextRangeU(0, SkXfermode::kLastCoeffMode);
+ GrColor color = rand->nextU();
+ static AutoEffectUnref gEffect(SkNEW_ARGS(ModeColorFilterEffect, (color, static_cast<SkXfermode::Mode>(mode))));
+ return CreateEffectRef(gEffect);
+}
+
+GrEffectRef* SkModeColorFilter::asNewEffect(GrContext*) const {
+ if (SkXfermode::kDst_Mode != fMode) {
+ return ModeColorFilterEffect::Create(SkColor2GrColor(fColor), fMode);
+ }
+ return NULL;
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
class Src_SkModeColorFilter : public SkModeColorFilter {
public:
Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {}
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index 3722178c29..ff2e837d8a 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -348,6 +348,7 @@ GrDisplacementMapEffect::GrDisplacementMapEffect(
this->addTextureAccess(&fDisplacementAccess);
this->addCoordTransform(&fColorTransform);
this->addTextureAccess(&fColorAccess);
+ this->setWillNotUseInputColor();
}
GrDisplacementMapEffect::~GrDisplacementMapEffect() {
diff --git a/src/effects/SkMatrixConvolutionImageFilter.cpp b/src/effects/SkMatrixConvolutionImageFilter.cpp
index a9dfecce59..c89b9dc63f 100644
--- a/src/effects/SkMatrixConvolutionImageFilter.cpp
+++ b/src/effects/SkMatrixConvolutionImageFilter.cpp
@@ -423,6 +423,7 @@ void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder,
const char* inputColor,
const TransformedCoordsArray& coords,
const TextureSamplerArray& samplers) {
+ sk_ignore_unused_variable(inputColor);
SkString coords2D = builder->ensureFSCoords2D(coords, 0);
fBoundsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kVec4f_GrSLType, "Bounds");
@@ -548,6 +549,7 @@ GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(GrTexture* texture,
}
fTarget[0] = static_cast<float>(target.x());
fTarget[1] = static_cast<float>(target.y());
+ this->setWillNotUseInputColor();
}
GrMatrixConvolutionEffect::~GrMatrixConvolutionEffect() {
diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp
index df6b78e9e1..af51afc031 100644
--- a/src/effects/SkPerlinNoiseShader.cpp
+++ b/src/effects/SkPerlinNoiseShader.cpp
@@ -610,6 +610,7 @@ protected:
m.postTranslate(SK_Scalar1, SK_Scalar1);
fCoordTransform.reset(kLocal_GrCoordSet, m);
this->addCoordTransform(&fCoordTransform);
+ this->setWillNotUseInputColor();
}
SkPerlinNoiseShader::Type fType;
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index fb8bbacdc1..c90adfeca0 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -951,7 +951,7 @@ void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder,
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
- (GrGLSLExpr<4>(inputColor) * GrGLSLExpr<4>("colorTemp")).c_str());
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
} else if (GrGradientEffect::kThree_ColorType == ColorTypeFromKey(key)){
builder->fsCodeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n",
gradientTValue);
@@ -975,7 +975,7 @@ void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder,
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
- (GrGLSLExpr<4>(inputColor) * GrGLSLExpr<4>("colorTemp")).c_str());
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
} else {
builder->fsCodeAppendf("\tvec2 coord = vec2(%s, %s);\n",
gradientTValue,
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp
index 2292929e39..a8af559991 100644
--- a/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/GrAAConvexPathRenderer.cpp
@@ -564,7 +564,7 @@ public:
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
- (GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
}
diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp
index a6b8d97c0b..ee7c024fe8 100644
--- a/src/gpu/GrAARectRenderer.cpp
+++ b/src/gpu/GrAARectRenderer.cpp
@@ -86,7 +86,7 @@ public:
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
- (GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("coverage")).c_str());
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr1("coverage")).c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
@@ -219,7 +219,7 @@ public:
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
- (GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("coverage")).c_str());
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr1("coverage")).c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index d1d6c5813e..1743604a19 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -59,7 +59,6 @@ void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRende
this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
- this->setColorFilter(paint.getColorFilterColor(), paint.getColorFilterMode());
this->setCoverage(paint.getCoverage());
}
@@ -219,13 +218,6 @@ bool GrDrawState::srcAlphaWillBeOne() const {
(*effect)->getConstantColorComponents(&color, &validComponentFlags);
}
- // Check if the color filter could introduce an alpha.
- // We could skip the above work when this is true, but it is rare and the right fix is to make
- // the color filter a GrEffect and implement getConstantColorComponents() for it.
- if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
- validComponentFlags = 0;
- }
-
// Check whether coverage is treated as color. If so we run through the coverage computation.
if (this->isCoverageDrawing()) {
GrColor coverageColor = this->getCoverage();
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 889dec9686..2e4d7f86c4 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -265,18 +265,6 @@ public:
}
/**
- * Add a color filter that can be represented by a color and a mode. Applied
- * after color-computing effect stages.
- */
- void setColorFilter(GrColor c, SkXfermode::Mode mode) {
- fCommon.fColorFilterColor = c;
- fCommon.fColorFilterMode = mode;
- }
-
- GrColor getColorFilterColor() const { return fCommon.fColorFilterColor; }
- SkXfermode::Mode getColorFilterMode() const { return fCommon.fColorFilterMode; }
-
- /**
* Constructor sets the color to be 'color' which is undone by the destructor.
*/
class AutoColorRestore : public ::SkNoncopyable {
@@ -914,8 +902,6 @@ private:
fCommon.fFlagBits = 0x0;
fCommon.fStencilSettings.setDisabled();
fCommon.fCoverage = 0xffffffff;
- fCommon.fColorFilterMode = SkXfermode::kDst_Mode;
- fCommon.fColorFilterColor = 0x0;
fCommon.fDrawFace = kBoth_DrawFace;
}
@@ -932,8 +918,6 @@ private:
int fVACount;
GrStencilSettings fStencilSettings;
GrColor fCoverage;
- SkXfermode::Mode fColorFilterMode;
- GrColor fColorFilterColor;
DrawFace fDrawFace;
// This is simply a different representation of info in fVertexAttribs and thus does
@@ -951,8 +935,6 @@ private:
!memcmp(fVAPtr, other.fVAPtr, fVACount * sizeof(GrVertexAttrib)) &&
fStencilSettings == other.fStencilSettings &&
fCoverage == other.fCoverage &&
- fColorFilterMode == other.fColorFilterMode &&
- fColorFilterColor == other.fColorFilterColor &&
fDrawFace == other.fDrawFace;
SkASSERT(!result || 0 == memcmp(fFixedFunctionVertexAttribIndices,
other.fFixedFunctionVertexAttribIndices,
diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp
index 91e3997349..27bd74a88a 100644
--- a/src/gpu/GrOvalRenderer.cpp
+++ b/src/gpu/GrOvalRenderer.cpp
@@ -117,7 +117,7 @@ public:
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
- (GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
@@ -249,7 +249,7 @@ public:
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
- (GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
@@ -407,7 +407,7 @@ public:
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
- (GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
diff --git a/src/gpu/GrPaint.cpp b/src/gpu/GrPaint.cpp
index fec62bbde5..7499cd0ea2 100644
--- a/src/gpu/GrPaint.cpp
+++ b/src/gpu/GrPaint.cpp
@@ -56,12 +56,6 @@ bool GrPaint::getOpaqueAndKnownColor(GrColor* solidColor,
// TODO: Share this implementation with GrDrawState
- // Since fColorFilterXfermode is going away soon, we aren't attempting to handle anything but
- // the default setting.
- if (SkXfermode::kDst_Mode != fColorFilterXfermode) {
- return false;
- }
-
GrColor coverage = GrColorPackRGBA(fCoverage, fCoverage, fCoverage, fCoverage);
uint32_t coverageComps = kRGBA_GrColorComponentFlags;
int count = fCoverageStages.count();
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 1498fc4c42..a70a0f5f5c 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -475,13 +475,6 @@ inline bool skPaint2GrPaintNoShader(SkGpuDevice* dev,
SkAutoTUnref<GrEffectRef> effect(colorFilter->asNewEffect(dev->context()));
if (NULL != effect.get()) {
grPaint->addColorEffect(effect);
- } else {
- // TODO: rewrite this using asNewEffect()
- SkColor color;
- SkXfermode::Mode filterMode;
- if (colorFilter->asColorMode(&color, &filterMode)) {
- grPaint->setXfermodeColorFilter(filterMode, SkColor2GrColor(color));
- }
}
}
}
diff --git a/src/gpu/effects/GrBezierEffect.cpp b/src/gpu/effects/GrBezierEffect.cpp
index 9cca054a40..c9a2bea052 100644
--- a/src/gpu/effects/GrBezierEffect.cpp
+++ b/src/gpu/effects/GrBezierEffect.cpp
@@ -111,7 +111,7 @@ void GrGLConicEffect::emitCode(GrGLFullShaderBuilder* builder,
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
- (GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
}
GrGLEffect::EffectKey GrGLConicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
@@ -239,7 +239,7 @@ void GrGLQuadEffect::emitCode(GrGLFullShaderBuilder* builder,
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
- (GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
@@ -383,7 +383,7 @@ void GrGLCubicEffect::emitCode(GrGLFullShaderBuilder* builder,
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
- (GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
}
GrGLEffect::EffectKey GrGLCubicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
diff --git a/src/gpu/effects/GrBicubicEffect.cpp b/src/gpu/effects/GrBicubicEffect.cpp
index ccbf78808b..25a15916de 100644
--- a/src/gpu/effects/GrBicubicEffect.cpp
+++ b/src/gpu/effects/GrBicubicEffect.cpp
@@ -44,6 +44,8 @@ void GrGLBicubicEffect::emitCode(GrGLShaderBuilder* builder,
const char* inputColor,
const TransformedCoordsArray& coords,
const TextureSamplerArray& samplers) {
+ sk_ignore_unused_variable(inputColor);
+
SkString coords2D = builder->ensureFSCoords2D(coords, 0);
fCoefficientsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kMat44f_GrSLType, "Coefficients");
@@ -106,6 +108,7 @@ GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
fCoefficients[x * 4 + y] = SkScalarToFloat(coefficients[y * 4 + x]);
}
}
+ this->setWillNotUseInputColor();
}
GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
@@ -120,6 +123,7 @@ GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
fCoefficients[x * 4 + y] = SkScalarToFloat(coefficients[y * 4 + x]);
}
}
+ this->setWillNotUseInputColor();
}
GrBicubicEffect::~GrBicubicEffect() {
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index c1b3a31218..7ddd8613f1 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -48,7 +48,6 @@ GrGLProgram::GrGLProgram(GrGpuGL* gpu,
fDstCopyTexUnit = -1;
fColor = GrColor_ILLEGAL;
- fColorFilterColor = GrColor_ILLEGAL;
if (fDesc.getHeader().fHasVertexCode ||
!fGpu->shouldUseFixedFunctionTexturing()) {
@@ -97,117 +96,6 @@ void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
}
}
-namespace {
-// given two blend coefficients determine whether the src
-// and/or dst computation can be omitted.
-inline void need_blend_inputs(SkXfermode::Coeff srcCoeff,
- SkXfermode::Coeff dstCoeff,
- bool* needSrcValue,
- bool* needDstValue) {
- if (SkXfermode::kZero_Coeff == srcCoeff) {
- switch (dstCoeff) {
- // these all read the src
- case SkXfermode::kSC_Coeff:
- case SkXfermode::kISC_Coeff:
- case SkXfermode::kSA_Coeff:
- case SkXfermode::kISA_Coeff:
- *needSrcValue = true;
- break;
- default:
- *needSrcValue = false;
- break;
- }
- } else {
- *needSrcValue = true;
- }
- if (SkXfermode::kZero_Coeff == dstCoeff) {
- switch (srcCoeff) {
- // these all read the dst
- case SkXfermode::kDC_Coeff:
- case SkXfermode::kIDC_Coeff:
- case SkXfermode::kDA_Coeff:
- case SkXfermode::kIDA_Coeff:
- *needDstValue = true;
- break;
- default:
- *needDstValue = false;
- break;
- }
- } else {
- *needDstValue = true;
- }
-}
-
-/**
- * Create a blend_coeff * value string to be used in shader code. Sets empty
- * string if result is trivially zero.
- */
-inline void blend_term_string(SkString* str, SkXfermode::Coeff coeff,
- const char* src, const char* dst,
- const char* value) {
- switch (coeff) {
- case SkXfermode::kZero_Coeff: /** 0 */
- *str = "";
- break;
- case SkXfermode::kOne_Coeff: /** 1 */
- *str = value;
- break;
- case SkXfermode::kSC_Coeff:
- str->printf("(%s * %s)", src, value);
- break;
- case SkXfermode::kISC_Coeff:
- str->printf("((vec4(1) - %s) * %s)", src, value);
- break;
- case SkXfermode::kDC_Coeff:
- str->printf("(%s * %s)", dst, value);
- break;
- case SkXfermode::kIDC_Coeff:
- str->printf("((vec4(1) - %s) * %s)", dst, value);
- break;
- case SkXfermode::kSA_Coeff: /** src alpha */
- str->printf("(%s.a * %s)", src, value);
- break;
- case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */
- str->printf("((1.0 - %s.a) * %s)", src, value);
- break;
- case SkXfermode::kDA_Coeff: /** dst alpha */
- str->printf("(%s.a * %s)", dst, value);
- break;
- case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */
- str->printf("((1.0 - %s.a) * %s)", dst, value);
- break;
- default:
- GrCrash("Unexpected xfer coeff.");
- break;
- }
-}
-/**
- * Adds a line to the fragment shader code which modifies the color by
- * the specified color filter.
- */
-void add_color_filter(GrGLShaderBuilder* builder,
- const char * outputVar,
- SkXfermode::Coeff uniformCoeff,
- SkXfermode::Coeff colorCoeff,
- const char* filterColor,
- const char* inColor) {
- SkString colorStr, constStr;
- blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor);
- blend_term_string(&constStr, uniformCoeff, filterColor, inColor, filterColor);
- GrGLSLExpr<4> sum;
- if (colorStr.isEmpty() && constStr.isEmpty()) {
- sum = GrGLSLExpr<4>(0);
- } else if (colorStr.isEmpty()) {
- sum = constStr;
- } else if (constStr.isEmpty()) {
- sum = colorStr;
- } else {
- sum = GrGLSLExpr<4>(colorStr) + GrGLSLExpr<4>(constStr);
- }
- builder->fsCodeAppendf("\t%s = %s;\n", outputVar, sum.c_str());
-}
-}
-
bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[]) {
@@ -216,40 +104,17 @@ bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
// incoming color to current stage being processed.
- GrGLSLExpr<4> inColor = builder->getInputColor();
-
- // Get the coeffs for the Mode-based color filter, determine if color is needed.
- SkXfermode::Coeff colorCoeff;
- SkXfermode::Coeff filterColorCoeff;
- SkAssertResult(
- SkXfermode::ModeAsCoeff(header.fColorFilterXfermode,
- &filterColorCoeff,
- &colorCoeff));
- bool needColor, needFilterColor;
- need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor);
+ GrGLSLExpr4 inColor = builder->getInputColor();
fColorEffects.reset(
builder->createAndEmitEffects(colorStages,
fDesc.effectKeys(),
- needColor ? fDesc.numColorEffects() : 0,
+ fDesc.numColorEffects(),
&inColor));
- // Insert the color filter. This will soon be replaced by a color effect.
- if (SkXfermode::kDst_Mode != header.fColorFilterXfermode) {
- const char* colorFilterColorUniName = NULL;
- fUniformHandles.fColorFilterUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
- kVec4f_GrSLType, "FilterColor",
- &colorFilterColorUniName);
-
- builder->fsCodeAppend("\tvec4 filteredColor;\n");
- add_color_filter(builder, "filteredColor", filterColorCoeff,
- colorCoeff, colorFilterColorUniName, inColor.c_str());
- inColor = "filteredColor";
- }
-
///////////////////////////////////////////////////////////////////////////
// compute the partial coverage
- GrGLSLExpr<4> inCoverage = builder->getInputCoverage();
+ GrGLSLExpr4 inCoverage = builder->getInputCoverage();
fCoverageEffects.reset(
builder->createAndEmitEffects(coverageStages,
@@ -272,13 +137,13 @@ bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
const char* secondaryOutputName = builder->enableSecondaryOutput();
// default coeff to ones for kCoverage_DualSrcOutput
- GrGLSLExpr<4> coeff(1);
+ GrGLSLExpr4 coeff(1);
if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) {
// Get (1-A) into coeff
- coeff = GrGLSLExprCast4(GrGLSLExpr<1>(1) - GrGLSLExprExtractAlpha(inColor));
+ coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inColor.a());
} else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == header.fCoverageOutput) {
// Get (1-RGBA) into coeff
- coeff = GrGLSLExpr<4>(1) - inColor;
+ coeff = GrGLSLExpr4(1) - inColor;
}
// Get coeff * coverage into modulate and then write that to the dual source output.
builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inCoverage).c_str());
@@ -288,12 +153,12 @@ bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
// combine color and coverage as frag color
// Get "color * coverage" into fragColor
- GrGLSLExpr<4> fragColor = inColor * inCoverage;
+ GrGLSLExpr4 fragColor = inColor * inCoverage;
// Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) {
- GrGLSLExpr<4> dstCoeff = GrGLSLExpr<4>(1) - inCoverage;
+ GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inCoverage;
- GrGLSLExpr<4> dstContribution = dstCoeff * GrGLSLExpr<4>(builder->dstColor());
+ GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(builder->dstColor());
fragColor = fragColor + dstContribution;
}
@@ -352,15 +217,6 @@ void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
this->setCoverage(drawState, coverage, sharedState);
this->setMatrixAndRenderTargetHeight(drawState);
- // Setup the SkXfermode::Mode-based colorfilter uniform if necessary
- if (fUniformHandles.fColorFilterUni.isValid() &&
- fColorFilterColor != drawState.getColorFilterColor()) {
- GrGLfloat c[4];
- GrColorToRGBAFloat(drawState.getColorFilterColor(), c);
- fUniformManager.set4fv(fUniformHandles.fColorFilterUni, 0, 1, c);
- fColorFilterColor = drawState.getColorFilterColor();
- }
-
if (NULL != dstCopy) {
if (fUniformHandles.fDstCopyTopLeftUni.isValid()) {
fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni,
@@ -409,7 +265,7 @@ void GrGLProgram::setColor(const GrDrawState& drawState,
}
break;
case GrGLProgramDesc::kUniform_ColorInput:
- if (fColor != color) {
+ if (fColor != color && fUniformHandles.fColorUni.isValid()) {
// OpenGL ES doesn't support unsigned byte varieties of glUniform
GrGLfloat c[4];
GrColorToRGBAFloat(color, c);
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 23ed45602a..8e2ae74aab 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -139,7 +139,6 @@ private:
UniformHandle fViewMatrixUni;
UniformHandle fColorUni;
UniformHandle fCoverageUni;
- UniformHandle fColorFilterUni;
// We use the render target height to provide a y-down frag coord when specifying
// origin_upper_left is not supported.
@@ -187,7 +186,6 @@ private:
MatrixState fMatrixState;
GrColor fColor;
GrColor fCoverage;
- GrColor fColorFilterColor;
int fDstCopyTexUnit;
SkAutoTDelete<GrGLProgramEffects> fColorEffects;
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index f9728ff556..d95874252e 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -56,6 +56,27 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
bool skipColor = SkToBool(blendOpts & (GrDrawState::kEmitTransBlack_BlendOptFlag |
GrDrawState::kEmitCoverage_BlendOptFlag));
+ int firstEffectiveColorStage = 0;
+ bool inputColorIsUsed = true;
+ if (!skipColor) {
+ firstEffectiveColorStage = drawState.numColorStages();
+ while (firstEffectiveColorStage > 0 && inputColorIsUsed) {
+ --firstEffectiveColorStage;
+ const GrEffect* effect = drawState.getColorStage(firstEffectiveColorStage).getEffect()->get();
+ inputColorIsUsed = effect->willUseInputColor();
+ }
+ }
+
+ int firstEffectiveCoverageStage = 0;
+ bool inputCoverageIsUsed = true;
+ if (!skipCoverage) {
+ firstEffectiveCoverageStage = drawState.numCoverageStages();
+ while (firstEffectiveCoverageStage > 0 && inputCoverageIsUsed) {
+ --firstEffectiveCoverageStage;
+ const GrEffect* effect = drawState.getCoverageStage(firstEffectiveCoverageStage).getEffect()->get();
+ inputCoverageIsUsed = effect->willUseInputColor();
+ }
+ }
// The descriptor is used as a cache key. Thus when a field of the
// descriptor will not affect program generation (because of the attribute
@@ -70,10 +91,11 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) ||
- (!requiresColorAttrib && 0xffffffff == drawState.getColor());
+ (!requiresColorAttrib && 0xffffffff == drawState.getColor()) ||
+ (!inputColorIsUsed);
- int numEffects = (skipColor ? 0 : drawState.numColorStages()) +
- (skipCoverage ? 0 : drawState.numCoverageStages());
+ int numEffects = (skipColor ? 0 : (drawState.numColorStages() - firstEffectiveColorStage)) +
+ (skipCoverage ? 0 : (drawState.numCoverageStages() - firstEffectiveCoverageStage));
size_t newKeyLength = KeyLength(numEffects);
bool allocChanged;
@@ -93,7 +115,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
bool readFragPosition = false;
bool hasVertexCode = false;
if (!skipColor) {
- for (int s = 0; s < drawState.numColorStages(); ++s) {
+ for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
effectKeys[currEffectKey++] =
get_key_and_update_stats(drawState.getColorStage(s), gpu->glCaps(),
requiresLocalCoordAttrib, &readsDst, &readFragPosition,
@@ -101,7 +123,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
}
}
if (!skipCoverage) {
- for (int s = 0; s < drawState.numCoverageStages(); ++s) {
+ for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
effectKeys[currEffectKey++] =
get_key_and_update_stats(drawState.getCoverageStage(s), gpu->glCaps(),
requiresLocalCoordAttrib, &readsDst, &readFragPosition,
@@ -111,7 +133,6 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
header->fHasVertexCode = hasVertexCode || requiresLocalCoordAttrib;
header->fEmitsPointSize = isPoints;
- header->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : drawState.getColorFilterMode();
// Currently the experimental GS will only work with triangle prims (and it doesn't do anything
// other than pass through values from the VS to the FS anyway).
@@ -139,7 +160,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
if (skipCoverage) {
header->fCoverageInput = kTransBlack_ColorInput;
- } else if (covIsSolidWhite) {
+ } else if (covIsSolidWhite || !inputCoverageIsUsed) {
header->fCoverageInput = kSolidWhite_ColorInput;
} else if (defaultToUniformInputs && !requiresCoverageAttrib) {
header->fCoverageInput = kUniform_ColorInput;
@@ -202,10 +223,6 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
bool separateCoverageFromColor = false;
if (!drawState.isCoverageDrawing() && !skipCoverage &&
(drawState.numCoverageStages() > 0 || requiresCoverageAttrib)) {
- // color filter is applied between color/coverage computation
- if (SkXfermode::kDst_Mode != header->fColorFilterXfermode) {
- separateCoverageFromColor = true;
- }
// If we're stenciling then we want to discard samples that have zero coverage
if (drawState.getStencil().doesWrite()) {
@@ -237,24 +254,23 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
}
}
if (!skipColor) {
- for (int s = 0; s < drawState.numColorStages(); ++s) {
+ for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
colorStages->push_back(&drawState.getColorStage(s));
}
- header->fColorEffectCnt = drawState.numColorStages();
}
if (!skipCoverage) {
SkTArray<const GrEffectStage*, true>* array;
if (separateCoverageFromColor) {
array = coverageStages;
- header->fCoverageEffectCnt = drawState.numCoverageStages();
} else {
array = colorStages;
- header->fColorEffectCnt += drawState.numCoverageStages();
}
- for (int s = 0; s < drawState.numCoverageStages(); ++s) {
+ for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
array->push_back(&drawState.getCoverageStage(s));
}
}
+ header->fColorEffectCnt = colorStages->count();
+ header->fCoverageEffectCnt = coverageStages->count();
*desc->checksum() = 0;
*desc->checksum() = SkChecksum::Compute(reinterpret_cast<uint32_t*>(desc->fKey.get()),
diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h
index c8ad77cff5..ec3f097906 100644
--- a/src/gpu/gl/GrGLProgramDesc.h
+++ b/src/gpu/gl/GrGLProgramDesc.h
@@ -160,7 +160,6 @@ private:
SkBool8 fHasVertexCode;
SkBool8 fEmitsPointSize;
- SkXfermode::Mode fColorFilterXfermode : 8;
// To enable experimental geometry shader code (not for use in
// production)
diff --git a/src/gpu/gl/GrGLSL.cpp b/src/gpu/gl/GrGLSL.cpp
index f0088fcdf8..0f740d9290 100644
--- a/src/gpu/gl/GrGLSL.cpp
+++ b/src/gpu/gl/GrGLSL.cpp
@@ -77,7 +77,7 @@ namespace {
void GrGLSLMulVarBy4f(SkString* outAppend,
unsigned tabCnt,
const char* vec4VarName,
- const GrGLSLExpr<4>& mulFactor) {
+ const GrGLSLExpr4& mulFactor) {
if (mulFactor.isOnes()) {
*outAppend = SkString();
}
diff --git a/src/gpu/gl/GrGLSL.h b/src/gpu/gl/GrGLSL.h
index 9387d2bbbb..8c5da51bde 100644
--- a/src/gpu/gl/GrGLSL.h
+++ b/src/gpu/gl/GrGLSL.h
@@ -76,34 +76,48 @@ static inline const char* GrGLSLTypeString(GrSLType t) {
}
}
-/** A class representing a GLSL expression.
+/** A generic base-class representing a GLSL expression.
* The instance can be a variable name, expression or vecN(0) or vecN(1). Does simple constant
* folding with help of 1 and 0.
- * Complex expressions can be constructed with operators *, +, -
+ *
+ * Clients should not use this class, rather the specific instantiations defined
+ * later, for example GrGLSLExpr4.
*/
-template <int N>
+template <typename Self>
class GrGLSLExpr {
public:
+ bool isOnes() const { return kOnes_ExprType == fType; }
+ bool isZeros() const { return kZeros_ExprType == fType; }
+
+ const char* c_str() const {
+ if (kZeros_ExprType == fType) {
+ return Self::ZerosStr();
+ } else if (kOnes_ExprType == fType) {
+ return Self::OnesStr();
+ }
+ SkASSERT(!fExpr.isEmpty()); // Empty expressions should not be used.
+ return fExpr.c_str();
+ }
+
+protected:
/** Constructs an invalid expression.
* Useful only as a return value from functions that never actually return
* this and instances that will be assigned to later. */
GrGLSLExpr()
: fType(kFullExpr_ExprType) {
- SK_COMPILE_ASSERT(N > 0 && N <= 4, dimensions_not_in_range);
// The only constructor that is allowed to build an empty expression.
SkASSERT(!this->isValid());
}
/** Constructs an expression with all components as value v */
explicit GrGLSLExpr(int v) {
- SK_COMPILE_ASSERT(N > 0 && N <= 4, dimensions_not_in_range);
if (v == 0) {
fType = kZeros_ExprType;
} else if (v == 1) {
fType = kOnes_ExprType;
} else {
fType = kFullExpr_ExprType;
- fExpr.appendf(CastIntStr(), v);
+ fExpr.appendf(Self::CastIntStr(), v);
}
}
@@ -111,7 +125,6 @@ public:
* Argument expr is a simple expression or a parenthesized expression. */
// TODO: make explicit once effects input Exprs.
GrGLSLExpr(const char expr[]) {
- SK_COMPILE_ASSERT(N > 0 && N <= 4, dimensions_not_in_range);
if (NULL == expr) { // TODO: remove this once effects input Exprs.
fType = kOnes_ExprType;
} else {
@@ -125,7 +138,6 @@ public:
* Argument expr is a simple expression or a parenthesized expression. */
// TODO: make explicit once effects input Exprs.
GrGLSLExpr(const SkString& expr) {
- SK_COMPILE_ASSERT(N > 0 && N <= 4, dimensions_not_in_range);
if (expr.isEmpty()) { // TODO: remove this once effects input Exprs.
fType = kOnes_ExprType;
} else {
@@ -135,77 +147,61 @@ public:
SkASSERT(this->isValid());
}
- bool isOnes() const { return kOnes_ExprType == fType; }
- bool isZeros() const { return kZeros_ExprType == fType; }
-
- const char* c_str() const {
- if (kZeros_ExprType == fType) {
- return ZerosStr();
- } else if (kOnes_ExprType == fType) {
- return OnesStr();
- }
- SkASSERT(!fExpr.isEmpty()); // Empty expressions should not be used.
- return fExpr.c_str();
- }
-
-private:
+ /** Constructs an expression from a string with one substitution. */
GrGLSLExpr(const char format[], const char in0[])
: fType(kFullExpr_ExprType) {
fExpr.appendf(format, in0);
}
+ /** Constructs an expression from a string with two substitutions. */
GrGLSLExpr(const char format[], const char in0[], const char in1[])
: fType(kFullExpr_ExprType) {
fExpr.appendf(format, in0, in1);
}
- GrGLSLExpr(const char format[], const char in0[], char in1)
- : fType(kFullExpr_ExprType) {
- fExpr.appendf(format, in0, in1);
- }
-
bool isValid() const {
return kFullExpr_ExprType != fType || !fExpr.isEmpty();
}
- static const char* ZerosStr();
- static const char* OnesStr();
- static const char* ExtractAlphaStr();
- static const char* CastStr();
- static const char* CastIntStr();
-
- /** Casts the expression expr into smaller or bigger expression.
- * Casting is done with GLSL rules:
- * M==3, N==4 vec3(a, b, c) -> vec4(a, b, c, 0)
- * N==4, M==3 vec4(a, b, c, d) -> vec3(a, b, c)
+ /** Returns expression casted to another type.
+ * Generic implementation that is called for non-trivial cases of casts. */
+ template <typename T>
+ static Self VectorCastImpl(const T& other);
+
+ /** Returns a GLSL multiplication: component-wise or component-by-scalar.
+ * The multiplication will be component-wise or multiply each component by a scalar.
+ *
+ * The returned expression will compute the value of:
+ * vecN(in0.x * in1.x, ...) if dim(T0) == dim(T1) (component-wise)
+ * vecN(in0.x * in1, ...) if dim(T1) == 1 (vector by scalar)
+ * vecN(in0 * in1.x, ...) if dim(T0) == 1 (scalar by vector)
*/
- template <int M>
- static GrGLSLExpr<N> VectorCast(const GrGLSLExpr<M>& expr);
+ template <typename T0, typename T1>
+ static Self Mul(T0 in0, T1 in1);
- /** GLSL multiplication: component-wise or multiply each component by a scalar.
- * M == N --> vecN(in0.x * in1.x, ...)
- * M == 1 --> vecN(in0.x * in1, ...)
- * otherwise --> compile-time error
+ /** Returns a GLSL addition: component-wise or add a scalar to each component.
+ * Return value computes:
+ * vecN(in0.x + in1.x, ...) or vecN(in0.x + in1, ...) or vecN(in0 + in1.x, ...).
*/
- template <int M>
- static GrGLSLExpr<N> Mul(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1);
+ template <typename T0, typename T1>
+ static Self Add(T0 in0, T1 in1);
- /** GLSL addition: component-wise or add a scalar to each compoment.
- * M == N --> vecN(in0.x + in1.x, ...)
- * M == 1 --> vecN(in0.x + in1, ...)
- * otherwise --> compile-time error
+ /** Returns a GLSL subtraction: component-wise or subtract compoments by a scalar.
+ * Return value computes
+ * vecN(in0.x - in1.x, ...) or vecN(in0.x - in1, ...) or vecN(in0 - in1.x, ...).
*/
- template <int M>
- static GrGLSLExpr<N> Add(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1);
+ template <typename T0, typename T1>
+ static Self Sub(T0 in0, T1 in1);
- /** GLSL subtraction: component-wise or subtract compoments by a scalar.
- * M == N --> vecN(in0.x - in1.x, ...)
- * M == 1 --> vecN(in0.x - in1, ...)
- * otherwise --> compile-time error
+ /** Returns expression that accesses component(s) of the expression.
+ * format should be the form "%s.x" where 'x' is the component(s) to access.
+ * Caller is responsible for making sure the amount of components in the
+ * format string is equal to dim(T).
*/
- template <int M>
- static GrGLSLExpr<N> Sub(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1);
+ template <typename T>
+ T extractComponents(const char format[]) const;
+private:
enum ExprType {
kZeros_ExprType,
kOnes_ExprType,
@@ -213,66 +209,112 @@ private:
};
ExprType fType;
SkString fExpr;
+};
- template <int> friend class GrGLSLExpr;
-
- /** Multiplies two expressions component-wise. */
- template <int M> friend GrGLSLExpr<M> operator*(const GrGLSLExpr<M>&, const GrGLSLExpr<M>&);
- /** Adds two expressions component-wise. */
- template <int M> friend GrGLSLExpr<M> operator+(const GrGLSLExpr<M>&, const GrGLSLExpr<M>&);
- /** Subtracts two expressions component-wise. */
- template <int M> friend GrGLSLExpr<M> operator-(const GrGLSLExpr<M>&, const GrGLSLExpr<M>&);
- /** Multiplies every component of an expression with a scalar expression. */
- friend GrGLSLExpr<4> operator*(const GrGLSLExpr<4>&, const GrGLSLExpr<1>&);
- /** Adds a scalar expression to every component of an expression. */
- friend GrGLSLExpr<4> operator+(const GrGLSLExpr<4>&, const GrGLSLExpr<1>&);
- /** Subtracts a scalar expression from every component of an expression. */
- friend GrGLSLExpr<4> operator-(const GrGLSLExpr<4>&, const GrGLSLExpr<1>&);
-
- friend GrGLSLExpr<1> GrGLSLExprExtractAlpha(const GrGLSLExpr<4>& expr);
- friend GrGLSLExpr<4> GrGLSLExprCast4(const GrGLSLExpr<1>& expr);
+class GrGLSLExpr1;
+class GrGLSLExpr4;
+
+/** Class representing a float GLSL expression. */
+class GrGLSLExpr1 : public GrGLSLExpr<GrGLSLExpr1> {
+public:
+ GrGLSLExpr1()
+ : INHERITED() {
+ }
+ explicit GrGLSLExpr1(int v)
+ : INHERITED(v) {
+ }
+ GrGLSLExpr1(const char* expr)
+ : INHERITED(expr) {
+ }
+ GrGLSLExpr1(const SkString& expr)
+ : INHERITED(expr) {
+ }
+
+ static GrGLSLExpr1 VectorCast(const GrGLSLExpr1& expr);
+
+private:
+ GrGLSLExpr1(const char format[], const char in0[])
+ : INHERITED(format, in0) {
+ }
+ GrGLSLExpr1(const char format[], const char in0[], const char in1[])
+ : INHERITED(format, in0, in1) {
+ }
+
+ static const char* ZerosStr();
+ static const char* OnesStr();
+ static const char* CastStr();
+ static const char* CastIntStr();
+
+ friend GrGLSLExpr1 operator*(const GrGLSLExpr1& in0, const GrGLSLExpr1&in1);
+ friend GrGLSLExpr1 operator+(const GrGLSLExpr1& in0, const GrGLSLExpr1&in1);
+ friend GrGLSLExpr1 operator-(const GrGLSLExpr1& in0, const GrGLSLExpr1&in1);
+
+ friend class GrGLSLExpr<GrGLSLExpr1>;
+ friend class GrGLSLExpr<GrGLSLExpr4>;
+
+ typedef GrGLSLExpr<GrGLSLExpr1> INHERITED;
};
+/** Class representing a float vector (vec4) GLSL expression. */
+class GrGLSLExpr4 : public GrGLSLExpr<GrGLSLExpr4> {
+public:
+ GrGLSLExpr4()
+ : INHERITED() {
+ }
+ explicit GrGLSLExpr4(int v)
+ : INHERITED(v) {
+ }
+ GrGLSLExpr4(const char* expr)
+ : INHERITED(expr) {
+ }
+ GrGLSLExpr4(const SkString& expr)
+ : INHERITED(expr) {
+ }
-template <int N>
-inline GrGLSLExpr<N> operator*(const GrGLSLExpr<N>& in0, const GrGLSLExpr<N>&in1) {
- return GrGLSLExpr<N>::Mul(in0, in1);
-}
+ typedef GrGLSLExpr1 AExpr;
+ AExpr a() const;
-template <int N>
-inline GrGLSLExpr<N> operator+(const GrGLSLExpr<N>& in0, const GrGLSLExpr<N>&in1) {
- return GrGLSLExpr<N>::Add(in0, in1);
-}
+ /** GLSL vec4 cast / constructor, eg vec4(floatv) -> vec4(floatv, floatv, floatv, floatv) */
+ static GrGLSLExpr4 VectorCast(const GrGLSLExpr1& expr);
+ static GrGLSLExpr4 VectorCast(const GrGLSLExpr4& expr);
-template <int N>
-inline GrGLSLExpr<N> operator-(const GrGLSLExpr<N>& in0, const GrGLSLExpr<N>&in1) {
- return GrGLSLExpr<N>::Sub(in0, in1);
-}
+private:
+ GrGLSLExpr4(const char format[], const char in0[])
+ : INHERITED(format, in0) {
+ }
+ GrGLSLExpr4(const char format[], const char in0[], const char in1[])
+ : INHERITED(format, in0, in1) {
+ }
-inline GrGLSLExpr<4> operator*(const GrGLSLExpr<4>& in0, const GrGLSLExpr<1>& in1) {
- return GrGLSLExpr<4>::Mul(in0, in1);
-}
+ static const char* ZerosStr();
+ static const char* OnesStr();
+ static const char* CastStr();
+ static const char* CastIntStr();
-inline GrGLSLExpr<4> operator+(const GrGLSLExpr<4>& in0, const GrGLSLExpr<1>& in1) {
- return GrGLSLExpr<4>::Add(in0, in1);
-}
+ // The vector-by-scalar and scalar-by-vector binary operations.
+ friend GrGLSLExpr4 operator*(const GrGLSLExpr1& in0, const GrGLSLExpr4&in1);
+ friend GrGLSLExpr4 operator+(const GrGLSLExpr1& in0, const GrGLSLExpr4&in1);
+ friend GrGLSLExpr4 operator-(const GrGLSLExpr1& in0, const GrGLSLExpr4&in1);
+ friend GrGLSLExpr4 operator*(const GrGLSLExpr4& in0, const GrGLSLExpr1&in1);
+ friend GrGLSLExpr4 operator+(const GrGLSLExpr4& in0, const GrGLSLExpr1&in1);
+ friend GrGLSLExpr4 operator-(const GrGLSLExpr4& in0, const GrGLSLExpr1&in1);
-inline GrGLSLExpr<4> operator-(const GrGLSLExpr<4>& in0, const GrGLSLExpr<1>& in1) {
- return GrGLSLExpr<4>::Sub(in0, in1);
-}
+ // The vector-by-vector, i.e. component-wise, binary operations.
+ friend GrGLSLExpr4 operator*(const GrGLSLExpr4& in0, const GrGLSLExpr4&in1);
+ friend GrGLSLExpr4 operator+(const GrGLSLExpr4& in0, const GrGLSLExpr4&in1);
+ friend GrGLSLExpr4 operator-(const GrGLSLExpr4& in0, const GrGLSLExpr4&in1);
-/** Casts an vec1 expression to vec4 expresison, eg. vec1(v) -> vec4(v,v,v,v). */
-GrGLSLExpr<4> GrGLSLExprCast4(const GrGLSLExpr<1>& expr);
+ friend class GrGLSLExpr<GrGLSLExpr4>;
-/** Extracts alpha component from an expression of vec<4>. */
-GrGLSLExpr<1> GrGLSLExprExtractAlpha(const GrGLSLExpr<4>& expr);
+ typedef GrGLSLExpr<GrGLSLExpr4> INHERITED;
+};
/**
* Does an inplace mul, *=, of vec4VarName by mulFactor.
* A semicolon and newline are added after the assignment.
*/
void GrGLSLMulVarBy4f(SkString* outAppend, unsigned tabCnt,
- const char* vec4VarName, const GrGLSLExpr<4>& mulFactor);
+ const char* vec4VarName, const GrGLSLExpr4& mulFactor);
#include "GrGLSL_impl.h"
diff --git a/src/gpu/gl/GrGLSL_impl.h b/src/gpu/gl/GrGLSL_impl.h
index 008d512f9c..bdd69cc76b 100644
--- a/src/gpu/gl/GrGLSL_impl.h
+++ b/src/gpu/gl/GrGLSL_impl.h
@@ -8,133 +8,168 @@
#ifndef GrGLSL_impl_DEFINED
#define GrGLSL_impl_DEFINED
-template<>
-inline const char* GrGLSLExpr<4>::ZerosStr() {
- return "vec4(0)";
+template<typename Self>
+template<typename T>
+inline Self GrGLSLExpr<Self>::VectorCastImpl(const T& expr) {
+ if (expr.isZeros()) {
+ return Self(0);
+ }
+ if (expr.isOnes()) {
+ return Self(1);
+ }
+ return Self(Self::CastStr(), expr.c_str());
}
-template<>
-inline const char* GrGLSLExpr<4>::OnesStr() {
- return "vec4(1)";
+template<typename Self>
+template<typename T0, typename T1>
+inline Self GrGLSLExpr<Self>::Mul(T0 in0, T1 in1) {
+ if (in0.isZeros() || in1.isZeros()) {
+ return Self(0);
+ }
+ if (in0.isOnes()) {
+ return Self::VectorCast(in1);
+ }
+ if (in1.isOnes()) {
+ return Self::VectorCast(in0);
+ }
+ return Self("(%s * %s)", in0.c_str(), in1.c_str());
}
-template<>
-inline const char* GrGLSLExpr<4>::ExtractAlphaStr() {
- return "%s.a";
+template<typename Self>
+template<typename T0, typename T1>
+inline Self GrGLSLExpr<Self>::Add(T0 in0, T1 in1) {
+ if (in1.isZeros()) {
+ return Self::VectorCast(in0);
+ }
+ if (in0.isZeros()) {
+ return Self::VectorCast(in1);
+ }
+ if (in0.isOnes() && in1.isOnes()) {
+ return Self(2);
+ }
+ return Self("(%s + %s)", in0.c_str(), in1.c_str());
}
-template<>
-inline const char* GrGLSLExpr<4>::CastStr() {
- return "vec4(%s)";
+template<typename Self>
+template<typename T0, typename T1>
+inline Self GrGLSLExpr<Self>::Sub(T0 in0, T1 in1) {
+ if (in1.isZeros()) {
+ return Self::VectorCast(in0);
+ }
+ if (in1.isOnes()) {
+ if (in0.isOnes()) {
+ return Self(0);
+ }
+ }
+
+ return Self("(%s - %s)", in0.c_str(), in1.c_str());
}
-template<>
-inline const char* GrGLSLExpr<4>::CastIntStr() {
- return "vec4(%d)";
+
+template <typename Self>
+template <typename T>
+T GrGLSLExpr<Self>::extractComponents(const char format[]) const {
+ if (this->isZeros()) {
+ return T(0);
+ }
+ if (this->isOnes()) {
+ return T(1);
+ }
+ return T(format, this->c_str());
+}
+
+inline GrGLSLExpr1 GrGLSLExpr1::VectorCast(const GrGLSLExpr1& expr) {
+ return expr;
}
-template<>
-inline const char* GrGLSLExpr<1>::ZerosStr() {
+inline const char* GrGLSLExpr1::ZerosStr() {
return "0";
}
-template<>
-inline const char* GrGLSLExpr<1>::OnesStr() {
- return "1";
+inline const char* GrGLSLExpr1::OnesStr() {
+ return "1.0";
}
-// GrGLSLExpr<1>::ExtractAlphaStr() and GrGLSLExpr<1>::CastStr() are
-// unimplemented because using them is likely an error. This is now caught
-// compile-time.
+// GrGLSLExpr1::CastStr() is unimplemented because using them is likely an
+// error. This is now caught compile-time.
-template<>
-inline const char* GrGLSLExpr<1>::CastIntStr() {
+inline const char* GrGLSLExpr1::CastIntStr() {
return "%d";
}
-template<>
-template<>
-inline GrGLSLExpr<4> GrGLSLExpr<4>::VectorCast(const GrGLSLExpr<4>& expr) {
- return expr;
+inline GrGLSLExpr1 operator*(const GrGLSLExpr1& in0, const GrGLSLExpr1& in1) {
+ return GrGLSLExpr1::Mul(in0, in1);
+}
+
+inline GrGLSLExpr1 operator+(const GrGLSLExpr1& in0, const GrGLSLExpr1& in1) {
+ return GrGLSLExpr1::Add(in0, in1);
+}
+
+inline GrGLSLExpr1 operator-(const GrGLSLExpr1& in0, const GrGLSLExpr1& in1) {
+ return GrGLSLExpr1::Sub(in0, in1);
}
-template<>
-template<>
-inline GrGLSLExpr<1> GrGLSLExpr<1>::VectorCast(const GrGLSLExpr<1>& expr) {
+inline const char* GrGLSLExpr4::ZerosStr() {
+ return "vec4(0)";
+}
+
+inline const char* GrGLSLExpr4::OnesStr() {
+ return "vec4(1)";
+}
+
+inline const char* GrGLSLExpr4::CastStr() {
+ return "vec4(%s)";
+}
+
+inline const char* GrGLSLExpr4::CastIntStr() {
+ return "vec4(%d)";
+}
+
+inline GrGLSLExpr4 GrGLSLExpr4::VectorCast(const GrGLSLExpr1& expr) {
+ return INHERITED::VectorCastImpl(expr);
+}
+
+inline GrGLSLExpr4 GrGLSLExpr4::VectorCast(const GrGLSLExpr4& expr) {
return expr;
}
-template<int N>
-template<int M>
-inline GrGLSLExpr<N> GrGLSLExpr<N>::VectorCast(const GrGLSLExpr<M>& expr) {
- if (expr.isZeros()) {
- return GrGLSLExpr<N>(0);
- }
- if (expr.isOnes()) {
- return GrGLSLExpr<N>(1);
- }
- return GrGLSLExpr<N>(GrGLSLExpr<N>::CastStr(), expr.c_str());
+inline GrGLSLExpr4::AExpr GrGLSLExpr4::a() const {
+ return this->extractComponents<GrGLSLExpr4::AExpr>("%s.a");
}
-template<int N>
-template<int M>
-inline GrGLSLExpr<N> GrGLSLExpr<N>::Mul(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1) {
- SK_COMPILE_ASSERT(N == M || M == 1, binary_op_dimensions_incompatible);
- if (in0.isZeros() || in1.isZeros()) {
- return GrGLSLExpr<N>(0);
- }
- if (in0.isOnes()) {
- return VectorCast<M>(in1);
- }
- if (in1.isOnes()) {
- return in0;
- }
- return GrGLSLExpr<N>("(%s * %s)", in0.c_str(), in1.c_str());
+inline GrGLSLExpr4 operator*(const GrGLSLExpr1& in0, const GrGLSLExpr4& in1) {
+ return GrGLSLExpr4::Mul(in0, in1);
}
-template<int N>
-template<int M>
-inline GrGLSLExpr<N> GrGLSLExpr<N>::Add(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1) {
- SK_COMPILE_ASSERT(N == M || M == 1, binary_op_dimensions_incompatible);
- if (in1.isZeros()) {
- return in0;
- }
- if (in0.isZeros()) {
- return VectorCast<M>(in1);
- }
- if (in0.isOnes() && in1.isOnes()) {
- return GrGLSLExpr<N>(2);
- }
- return GrGLSLExpr<N>("(%s + %s)", in0.c_str(), in1.c_str());
+inline GrGLSLExpr4 operator+(const GrGLSLExpr1& in0, const GrGLSLExpr4& in1) {
+ return GrGLSLExpr4::Add(in0, in1);
}
-template<int N>
-template<int M>
-inline GrGLSLExpr<N> GrGLSLExpr<N>::Sub(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1) {
- SK_COMPILE_ASSERT(N == M || M == 1, binary_op_dimensions_incompatible);
- if (in1.isZeros()) {
- return in0;
- }
- if (in1.isOnes()) {
- if (in0.isOnes()) {
- return GrGLSLExpr<N>(0);
- }
- }
+inline GrGLSLExpr4 operator-(const GrGLSLExpr1& in0, const GrGLSLExpr4& in1) {
+ return GrGLSLExpr4::Sub(in0, in1);
+}
- return GrGLSLExpr<N>("(%s - %s)", in0.c_str(), in1.c_str());
+inline GrGLSLExpr4 operator*(const GrGLSLExpr4& in0, const GrGLSLExpr1& in1) {
+ return GrGLSLExpr4::Mul(in0, in1);
}
-inline GrGLSLExpr<4> GrGLSLExprCast4(const GrGLSLExpr<1>& expr) {
- return GrGLSLExpr<4>::VectorCast(expr);
+inline GrGLSLExpr4 operator+(const GrGLSLExpr4& in0, const GrGLSLExpr1& in1) {
+ return GrGLSLExpr4::Add(in0, in1);
}
-inline GrGLSLExpr<1> GrGLSLExprExtractAlpha(const GrGLSLExpr<4>& expr) {
- if (expr.isZeros()) {
- return GrGLSLExpr<1>(0);
- }
- if (expr.isOnes()) {
- return GrGLSLExpr<1>(1);
- }
- return GrGLSLExpr<1>(GrGLSLExpr<4>::ExtractAlphaStr(), expr.c_str());
+inline GrGLSLExpr4 operator-(const GrGLSLExpr4& in0, const GrGLSLExpr1& in1) {
+ return GrGLSLExpr4::Sub(in0, in1);
+}
+
+inline GrGLSLExpr4 operator*(const GrGLSLExpr4& in0, const GrGLSLExpr4& in1) {
+ return GrGLSLExpr4::Mul(in0, in1);
+}
+
+inline GrGLSLExpr4 operator+(const GrGLSLExpr4& in0, const GrGLSLExpr4& in1) {
+ return GrGLSLExpr4::Add(in0, in1);
+}
+
+inline GrGLSLExpr4 operator-(const GrGLSLExpr4& in0, const GrGLSLExpr4& in1) {
+ return GrGLSLExpr4::Sub(in0, in1);
}
#endif
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 4d8df4e3b7..004fb04357 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -149,22 +149,22 @@ GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu,
const char* name;
fColorUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kVec4f_GrSLType, "Color", &name);
- fInputColor = name;
+ fInputColor = GrGLSLExpr4(name);
} else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fColorInput) {
- fInputColor = GrGLSLExpr<4>(1);
+ fInputColor = GrGLSLExpr4(1);
} else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fColorInput) {
- fInputColor = GrGLSLExpr<4>(0);
+ fInputColor = GrGLSLExpr4(0);
}
if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
const char* name;
fCoverageUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kVec4f_GrSLType, "Coverage", &name);
- fInputCoverage = name;
+ fInputCoverage = GrGLSLExpr4(name);
} else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fCoverageInput) {
- fInputCoverage = GrGLSLExpr<4>(1);
+ fInputCoverage = GrGLSLExpr4(1);
} else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fCoverageInput) {
- fInputCoverage = GrGLSLExpr<4>(0);
+ fInputCoverage = GrGLSLExpr4(0);
}
if (k110_GrGLSLGeneration != fGpu->glslGeneration()) {
@@ -295,7 +295,7 @@ void GrGLShaderBuilder::fsAppendTextureLookupAndModulate(
GrSLType varyingType) {
SkString lookup;
this->appendTextureLookup(&lookup, sampler, coordName, varyingType);
- fFSCode.append((GrGLSLExpr<4>(modulation) * GrGLSLExpr<4>(lookup)).c_str());
+ fFSCode.append((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str());
}
GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture* dstCopy,
@@ -515,11 +515,11 @@ void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programE
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
- GrGLSLExpr<4>* fsInOutColor) {
+ GrGLSLExpr4* fsInOutColor) {
bool effectEmitted = false;
- GrGLSLExpr<4> inColor = *fsInOutColor;
- GrGLSLExpr<4> outColor;
+ GrGLSLExpr4 inColor = *fsInOutColor;
+ GrGLSLExpr4 outColor;
for (int e = 0; e < effectCnt; ++e) {
SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect());
@@ -839,7 +839,7 @@ GrGLProgramEffects* GrGLFullShaderBuilder::createAndEmitEffects(
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
- GrGLSLExpr<4>* inOutFSColor) {
+ GrGLSLExpr4* inOutFSColor) {
GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt);
this->INHERITED::createAndEmitEffects(&programEffectsBuilder,
@@ -954,7 +954,7 @@ GrGLProgramEffects* GrGLFragmentOnlyShaderBuilder::createAndEmitEffects(
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
- GrGLSLExpr<4>* inOutFSColor) {
+ GrGLSLExpr4* inOutFSColor) {
GrGLTexGenProgramEffectsBuilder texGenEffectsBuilder(this, effectCnt);
this->INHERITED::createAndEmitEffects(&texGenEffectsBuilder,
diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h
index 3eff1df050..1218554fea 100644
--- a/src/gpu/gl/GrGLShaderBuilder.h
+++ b/src/gpu/gl/GrGLShaderBuilder.h
@@ -168,10 +168,10 @@ public:
/**
* Interfaces used by GrGLProgram.
*/
- const GrGLSLExpr<4>& getInputColor() const {
+ const GrGLSLExpr4& getInputColor() const {
return fInputColor;
}
- const GrGLSLExpr<4>& getInputCoverage() const {
+ const GrGLSLExpr4& getInputCoverage() const {
return fInputCoverage;
}
@@ -186,7 +186,7 @@ public:
virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
- GrGLSLExpr<4>* inOutFSColor) = 0;
+ GrGLSLExpr4* inOutFSColor) = 0;
const char* getColorOutputName() const;
const char* enableSecondaryOutput();
@@ -211,8 +211,8 @@ public:
protected:
GrGpuGL* gpu() const { return fGpu; }
- void setInputColor(const GrGLSLExpr<4>& inputColor) { fInputColor = inputColor; }
- void setInputCoverage(const GrGLSLExpr<4>& inputCoverage) { fInputCoverage = inputCoverage; }
+ void setInputColor(const GrGLSLExpr4& inputColor) { fInputColor = inputColor; }
+ void setInputCoverage(const GrGLSLExpr4& inputCoverage) { fInputCoverage = inputCoverage; }
/** Add input/output variable declarations (i.e. 'varying') to the fragment shader. */
GrGLShaderVar& fsInputAppend() { return fFSInputs.push_back(); }
@@ -227,7 +227,7 @@ protected:
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
- GrGLSLExpr<4>* inOutFSColor);
+ GrGLSLExpr4* inOutFSColor);
virtual bool compileAndAttachShaders(GrGLuint programId) const;
virtual void bindProgramLocations(GrGLuint programId) const;
@@ -329,8 +329,8 @@ private:
bool fSetupFragPosition;
GrGLUniformManager::UniformHandle fDstCopySamplerUniform;
- GrGLSLExpr<4> fInputColor;
- GrGLSLExpr<4> fInputCoverage;
+ GrGLSLExpr4 fInputColor;
+ GrGLSLExpr4 fInputCoverage;
bool fHasCustomColorOutput;
bool fHasSecondaryOutput;
@@ -396,7 +396,7 @@ public:
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
- GrGLSLExpr<4>* inOutFSColor) SK_OVERRIDE;
+ GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
GrGLUniformManager::UniformHandle getViewMatrixUniform() const {
return fViewMatrixUniform;
@@ -445,7 +445,7 @@ public:
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
- GrGLSLExpr<4>* inOutFSColor) SK_OVERRIDE;
+ GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
private:
int fNumTexCoordSets;
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index 12107f4356..a3cb3bc65d 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -61,9 +61,6 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
currAttribIndex++ :
-1;
- header->fColorFilterXfermode = static_cast<SkXfermode::Mode>(
- random->nextULessThan(SkXfermode::kLastCoeffMode + 1));
-
#if GR_GL_EXPERIMENTAL_GS
header->fExperimentalGS = gpu->caps()->geometryShaderSupport() && random->nextBool();
#endif
diff --git a/tests/GpuColorFilterTest.cpp b/tests/GpuColorFilterTest.cpp
new file mode 100644
index 0000000000..9fb1c770e1
--- /dev/null
+++ b/tests/GpuColorFilterTest.cpp
@@ -0,0 +1,131 @@
+
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#if SK_SUPPORT_GPU
+
+#include "GrContext.h"
+#include "GrContextFactory.h"
+#include "GrEffect.h"
+#include "SkColorFilter.h"
+#include "Test.h"
+#include "SkGr.h"
+
+namespace {
+
+static GrColor filterColor(const GrColor& color, uint32_t flags) {
+ uint32_t mask = 0;
+ if (flags & kR_GrColorComponentFlag) {
+ mask = 0xFF << GrColor_SHIFT_R;
+ }
+ if (flags & kG_GrColorComponentFlag) {
+ mask |= 0xFF << GrColor_SHIFT_G;
+ }
+ if (flags & kB_GrColorComponentFlag) {
+ mask |= 0xFF << GrColor_SHIFT_B;
+ }
+ if (flags & kA_GrColorComponentFlag) {
+ mask |= 0xFF << GrColor_SHIFT_A;
+ }
+ return color & mask;
+}
+
+static void test_getConstantColorComponents(skiatest::Reporter* reporter, GrContext* grContext) {
+ struct GetConstantComponentTestCase {
+ // "Shape drawn with"
+ uint32_t inputComponents; // "rgb of", "red of", "alpha of", ...
+ GrColor inputColor; // "[color]"
+
+ SkColor filterColor; // "with filter color [color]"
+ SkXfermode::Mode filterMode; // "in mode [mode]"
+
+ // "produces"
+ uint32_t outputComponents; // "rgb of", "red of", "alpha of", ...
+ GrColor outputColor; // "[color]"
+ };
+
+ // Shorthands.
+ enum {
+ kR = kR_GrColorComponentFlag,
+ kG = kG_GrColorComponentFlag,
+ kB = kB_GrColorComponentFlag,
+ kA = kA_GrColorComponentFlag,
+ kRGB = kRGB_GrColorComponentFlags,
+ kRGBA = kRGBA_GrColorComponentFlags
+ };
+
+ // Note: below, SkColors are non-premultiplied, where as GrColors are premultiplied.
+
+ const SkColor c1 = SkColorSetARGB(200, 200, 200, 200);
+ const SkColor c2 = SkColorSetARGB(60, 60, 60, 60);
+ const GrColor gr_c1 = SkColor2GrColor(c1);
+ const GrColor gr_c2 = SkColor2GrColor(c2);
+
+ const GrColor gr_black = GrColorPackRGBA(0, 0, 0, 0);
+ const GrColor gr_white = GrColorPackRGBA(255, 255, 255, 255);
+ const GrColor gr_whiteTrans = GrColorPackRGBA(128, 128, 128, 128);
+
+ GetConstantComponentTestCase filterTests[] = {
+ // A color filtered with Clear produces black.
+ { kRGBA, gr_white, SK_ColorBLACK, SkXfermode::kClear_Mode, kRGBA, gr_black },
+ { kRGBA, gr_c1, SK_ColorWHITE, SkXfermode::kClear_Mode, kRGBA, gr_black },
+ { kR, gr_white, c1, SkXfermode::kClear_Mode, kRGBA, gr_black },
+
+ // A color filtered with a color in mode Src, produces the filter color.
+ { kRGBA, gr_c2, c1, SkXfermode::kSrc_Mode, kRGBA, gr_c1 },
+ { kA, gr_c1, c1, SkXfermode::kSrc_Mode, kRGBA, gr_c1 },
+
+ // A color filtered with SrcOver produces a color.
+ { kRGBA, gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kSrcOver_Mode, kRGBA, GrColorPackRGBA(164, 164, 164, 192)},
+ // An unknown color with known alpha filtered with SrcOver produces an unknown color with known alpha.
+ { kA , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kSrcOver_Mode, kA , GrColorPackRGBA(0, 0, 0, 192)},
+ // A color with unknown alpha filtered with SrcOver produces a color with unknown alpha.
+ { kRGB , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kSrcOver_Mode, kRGB, GrColorPackRGBA(164, 164, 164, 0)},
+
+ // A color filtered with DstOver produces a color.
+ { kRGBA, gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kDstOver_Mode, kRGBA, GrColorPackRGBA(178, 178, 178, 192)},
+ // An unknown color with known alpha filtered with DstOver produces an unknown color with known alpha.
+ { kA , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kDstOver_Mode, kA , GrColorPackRGBA(0, 0, 0, 192)},
+ // A color with unknown alpha filtered with DstOver produces an unknown color.
+ { kRGB , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kDstOver_Mode, 0 , gr_black},
+
+ // An unknown color with known alpha and red component filtered with Multiply produces an unknown color with known red and alpha.
+ { kR|kA , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kModulate_Mode, kR|kA, GrColorPackRGBA(50, 0, 0, 64) }
+ };
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(filterTests); ++i) {
+ const GetConstantComponentTestCase& test = filterTests[i];
+ SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(test.filterColor, test.filterMode));
+ SkAutoTUnref<GrEffectRef> grEffect(cf->asNewEffect(grContext));
+ GrColor color = test.inputColor;
+ uint32_t components = test.inputComponents;
+ grEffect->get()->getConstantColorComponents(&color, &components);
+
+ REPORTER_ASSERT(reporter, filterColor(color, components) == test.outputColor);
+ REPORTER_ASSERT(reporter, test.outputComponents == components);
+ }
+}
+
+static void TestGpuColorFilter(skiatest::Reporter* reporter, GrContextFactory* factory) {
+ for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
+ GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
+
+ GrContext* grContext = factory->get(glType);
+ if (NULL == grContext) {
+ continue;
+ }
+
+ test_getConstantColorComponents(reporter, grContext);
+ }
+}
+
+}
+
+#include "TestClassDef.h"
+DEFINE_GPUTESTCLASS("GpuColorFilter", TestGpuColorFilterClass, TestGpuColorFilter)
+
+#endif