aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-10-23 05:42:03 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-10-23 05:42:03 +0000
commita34995e18b1f0a7d8c9f23451718bb30ff0105b0 (patch)
tree88164026f4b0e31a1acc164ed39191ea34fdee57
parentafba64434d23f135392f0e9e4f00a9c6a077a0ec (diff)
Implement SkColorFilter as a GrGLEffect
Adds GrEffect::willUseInputColor() which indicates whether or not the input color affects the output of the effect. This is needed for certain Xfermodes, such as kSrc_Mode. For these modes the color filter will not use the input color. An effect with GrEffect::willUseInputColor() true will cause all color or coverage effects before it to be discarded, as their computations cannot affect the output. In these cases program is marked as having white input color. This fixes an assert when Skia is compiled in a mode that prefers using uniforms instead of attributes for constants. (Flags GR_GL_USE_NV_PATH_RENDERING or GR_GL_NO_CONSTANT_ATTRIBUTES). Using attributes hides the problem where the fragment shader does not need input color for color filters that ignore DST part of the filter. The assert would be hit when uniform manager tries to bind an uniform which has been optimized away by the shader compiler. Adds specific GrGLSLExpr4 and GrGLSLExpr1 classes. This way the GLSL expressions like "(v - src.a)" can remain somewhat readable in form of "(v - src.a())". The GrGLSLExpr<typename> template implements the generic functionality, GrGLSLExprX is the specialization that exposes the type-safe interface to this functionality. Also adds operators so that GLSL binary operators of the form "(float * vecX)" can be expressed in C++. Before only the equivalent "(vecX * float)" was possible. This reverts the common blending calculations to more conventional order, such as "(1-a) * c" instead of "c * (1-a)". Changes GrGLSLExpr1::OnesStr from 1 to 1.0 in order to preserve the color filter blending formula string the same (with the exception of variable name change). Shaders change in case of input color being needed: - vec4 filteredColor; - filteredColor = (((1.0 - uFilterColor.a) * output_Stage0) + uFilterColor); - fsColorOut = filteredColor; + vec4 output_Stage1; + { // Stage 1: ModeColorFilterEffect + output_Stage1 = (((1.0 - uFilterColor_Stage1.a) * output_Stage0) + uFilterColor_Stage1); + } + fsColorOut = output_Stage1; Shaders change in case of input color being not needed: -uniform vec4 uFilterColor; -in vec4 vColor; +uniform vec4 uFilterColor_Stage0; out vec4 fsColorOut; void main() { - vec4 filteredColor; - filteredColor = uFilterColor; - fsColorOut = filteredColor; + vec4 output_Stage0; + { // Stage 0: ModeColorFilterEffect + output_Stage0 = uFilterColor_Stage0; + } + fsColorOut = output_Stage0; } R=bsalomon@google.com, robertphillips@google.com, jvanverth@google.com Author: kkinnunen@nvidia.com Review URL: https://codereview.chromium.org/25023003 git-svn-id: http://skia.googlecode.com/svn/trunk@11912 2bbb7eff-a529-9590-31e7-b0007b416f81
-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