diff options
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 |