| Index: src/effects/SkColorFilters.cpp
|
| diff --git a/src/effects/SkColorFilters.cpp b/src/effects/SkColorFilters.cpp
|
| index 41a201ef39559fc232e10319c3a9e65f20c39c8c..9bc3e853025293da225c54dbe3f87bb15f570c51 100644
|
| --- a/src/effects/SkColorFilters.cpp
|
| +++ b/src/effects/SkColorFilters.cpp
|
| @@ -11,6 +11,7 @@
|
| #include "SkColorFilter.h"
|
| #include "SkColorPriv.h"
|
| #include "SkFlattenableBuffers.h"
|
| +#include "SkGr.h"
|
| #include "SkUtils.h"
|
| #include "SkString.h"
|
|
|
| @@ -85,6 +86,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 +121,248 @@ private:
|
| typedef SkColorFilter INHERITED;
|
| };
|
|
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +#if SK_SUPPORT_GPU
|
| +#include "GrEffect.h"
|
| +#include "GrEffectUnitTest.h"
|
| +#include "GrTBackendEffectFactory.h"
|
| +#include "gl/GrGLEffect.h"
|
| +#include "gl/GrGLEffectMatrix.h"
|
| +
|
| +namespace {
|
| +
|
| +/**
|
| + * 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 = "";
|
| + //SkASSERT(NULL == dst);
|
| + break;
|
| + case SkXfermode::kOne_Coeff: /** 1 */
|
| + *str = value;
|
| + //SkASSERT(NULL == dst);
|
| + break;
|
| + case SkXfermode::kSC_Coeff:
|
| + str->printf("(%s * %s)", src, value);
|
| + //SkASSERT(NULL == dst);
|
| + break;
|
| + case SkXfermode::kISC_Coeff:
|
| + str->printf("((%s - %s) * %s)", GrGLSLExpr<4>::onesStr(), src, value);
|
| + //SkASSERT(NULL == dst);
|
| + break;
|
| + case SkXfermode::kDC_Coeff:
|
| + str->printf("(%s * %s)", dst, value);
|
| + break;
|
| + case SkXfermode::kIDC_Coeff:
|
| + str->printf("((%s - %s) * %s)", GrGLSLExpr<4>::onesStr(), dst, value);
|
| + break;
|
| + case SkXfermode::kSA_Coeff: /** src alpha */
|
| + str->printf("(%s.a * %s)", src, value);
|
| + //SkASSERT(NULL == dst);
|
| + break;
|
| + case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */
|
| + str->printf("((1.0 - %s.a) * %s)", src, value);
|
| + //SkASSERT(NULL == dst);
|
| + 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.
|
| + */
|
| +GrGLSLExpr<4> add_color_filter(SkXfermode::Mode mode,
|
| + const char* filterColor,
|
| + const char* inColor) {
|
| + SkXfermode::Coeff colorCoeff;
|
| + SkXfermode::Coeff filterColorCoeff;
|
| + SkAssertResult(SkXfermode::ModeAsCoeff(mode, &filterColorCoeff, &colorCoeff));
|
| +
|
| + SkString colorStr, constStr;
|
| + blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor);
|
| + blend_term_string(&constStr, filterColorCoeff, filterColor, inColor, filterColor);
|
| +
|
| + SkASSERT(!(colorStr.isEmpty() && constStr.isEmpty()));
|
| +
|
| + if (colorStr.isEmpty()) {
|
| + return constStr;
|
| + } else if (constStr.isEmpty()) {
|
| + return colorStr;
|
| + }
|
| + return GrGLSLAddf<4,4>(colorStr, constStr);
|
| +}
|
| +}
|
| +
|
| +/**
|
| + */
|
| +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 {
|
| + if (SkXfermode::kDst_Mode != fMode) {
|
| + *validFlags = 0;
|
| + }
|
| + }
|
| +
|
| + virtual bool getWillUseInputColor() const {
|
| + SkXfermode::Coeff dstCoeff;
|
| + SkXfermode::Coeff srcCoeff;
|
| + SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
|
| +
|
| + 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:
|
| + return true;
|
| + default:
|
| + return false;
|
| + }
|
| + }
|
| + return true;
|
| + }
|
| +
|
| + bool getWillUseFilterColor() const {
|
| + SkXfermode::Coeff dstCoeff;
|
| + SkXfermode::Coeff srcCoeff;
|
| + SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
|
| + 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:
|
| + return true;
|
| + default:
|
| + return false;
|
| + }
|
| + }
|
| + 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&)
|
| + : GrGLEffect(factory) {
|
| + }
|
| +
|
| + virtual void emitCode(GrGLShaderBuilder* builder,
|
| + const GrDrawEffect& drawEffect,
|
| + EffectKey key,
|
| + const char* outputColor,
|
| + const char* inputColor,
|
| + const TextureSamplerArray& samplers) SK_OVERRIDE {
|
| + SkXfermode::Mode mode = drawEffect.castEffect<ModeColorFilterEffect>().mode();
|
| +
|
| + if (SkXfermode::kDst_Mode != mode) {
|
| + const char* colorFilterColorUniName = NULL;
|
| + if (drawEffect.castEffect<ModeColorFilterEffect>().getWillUseFilterColor()) {
|
| + fFilterColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
|
| + kVec4f_GrSLType, "FilterColor",
|
| + &colorFilterColorUniName);
|
| + }
|
| +
|
| + const char* color;
|
| + // FIXME: special case for black and white.
|
| + color = inputColor;
|
| + GrGLSLExpr<4> filter = add_color_filter(mode, colorFilterColorUniName, color);
|
| + builder->fsCodeAppendf("\t%s = %s;\n", outputColor, filter.c_str());
|
| + } else {
|
| + builder->fsCodeAppendf("\t%s = %s;\n", outputColor, inputColor);
|
| + }
|
| + }
|
| +
|
| + static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
|
| + const ModeColorFilterEffect& colorModeFilter = drawEffect.castEffect<ModeColorFilterEffect>();
|
| +
|
| + 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:
|
| +
|
| + static const GrEffect::CoordsType kCoordsType = GrEffect::kLocal_CoordsType;
|
| + GrGLUniformManager::UniformHandle fFilterColorUni;
|
| + typedef GrGLEffect INHERITED;
|
| + };
|
| +
|
| + GR_DECLARE_EFFECT_TEST;
|
| +
|
| +private:
|
| + ModeColorFilterEffect(GrColor color, SkXfermode::Mode mode)
|
| + : fMode(mode),
|
| + fColor(color) {
|
| + }
|
| +
|
| + 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;
|
| +};
|
| +
|
| +GR_DEFINE_EFFECT_TEST(ModeColorFilterEffect);
|
| +GrEffectRef* ModeColorFilterEffect::TestCreate(SkRandom* rand,
|
| + GrContext*,
|
| + const GrDrawTargetCaps&,
|
| + GrTexture*[]) {
|
| + int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
|
| + GrColor color = rand->nextU();
|
| + static AutoEffectUnref gEffect(SkNEW_ARGS(ModeColorFilterEffect, (color, static_cast<SkXfermode::Mode>(mode))));
|
| + return CreateEffectRef(gEffect);
|
| +}
|
| +
|
| +#endif
|
| +
|
| +GrEffectRef* SkModeColorFilter::asNewEffect(GrContext*) const {
|
| + return ModeColorFilterEffect::Create(SkColor2GrColor(fColor), fMode);
|
| +}
|
| +
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +
|
| class Src_SkModeColorFilter : public SkModeColorFilter {
|
| public:
|
| Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {}
|
|
|