| Index: src/effects/SkColorFilters.cpp
|
| diff --git a/src/effects/SkColorFilters.cpp b/src/effects/SkColorFilters.cpp
|
| index c38328ccbbd8317c7e36e8e67cf29ddab274d512..ece3295107e58d2beab55fb3341d4ee201837219 100644
|
| --- a/src/effects/SkColorFilters.cpp
|
| +++ b/src/effects/SkColorFilters.cpp
|
| @@ -65,305 +65,36 @@ SkFlattenable* SkModeColorFilter::CreateProc(SkReadBuffer& buffer) {
|
| ///////////////////////////////////////////////////////////////////////////////
|
| #if SK_SUPPORT_GPU
|
| #include "GrBlend.h"
|
| -#include "GrFragmentProcessor.h"
|
| #include "GrInvariantOutput.h"
|
| -#include "GrProcessorUnitTest.h"
|
| +#include "effects/GrXfermodeFragmentProcessor.h"
|
| +#include "effects/GrConstColorProcessor.h"
|
| #include "SkGr.h"
|
| -#include "gl/GrGLFragmentProcessor.h"
|
| -#include "gl/builders/GrGLProgramBuilder.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:
|
| - SkFAIL("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 GrFragmentProcessor {
|
| -public:
|
| - static GrFragmentProcessor* Create(const GrColor& c, SkXfermode::Mode mode) {
|
| - // TODO: Make the effect take the coeffs rather than mode since we already do the
|
| - // conversion here.
|
| - SkXfermode::Coeff srcCoeff, dstCoeff;
|
| - if (!SkXfermode::ModeAsCoeff(mode, &srcCoeff, &dstCoeff)) {
|
| -// SkDebugf("Failing to create color filter for mode %d\n", mode);
|
| - return nullptr;
|
| - }
|
| - return new ModeColorFilterEffect(c, mode);
|
| - }
|
| -
|
| - 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;
|
| - }
|
| -
|
| - const char* name() const override { return "ModeColorFilterEffect"; }
|
| -
|
| - SkXfermode::Mode mode() const { return fMode; }
|
| - GrColor color() const { return fColor; }
|
| -
|
| - class GLProcessor : public GrGLFragmentProcessor {
|
| - public:
|
| - GLProcessor(const GrProcessor&) {
|
| - }
|
| -
|
| - virtual void emitCode(EmitArgs& args) override {
|
| - SkXfermode::Mode mode = args.fFp.cast<ModeColorFilterEffect>().mode();
|
| -
|
| - SkASSERT(SkXfermode::kDst_Mode != mode);
|
| - const char* colorFilterColorUniName = nullptr;
|
| - if (args.fFp.cast<ModeColorFilterEffect>().willUseFilterColor()) {
|
| - fFilterColorUni = args.fBuilder->addUniform(
|
| - GrGLProgramBuilder::kFragment_Visibility,
|
| - kVec4f_GrSLType, kDefault_GrSLPrecision,
|
| - "FilterColor",
|
| - &colorFilterColorUniName);
|
| - }
|
| -
|
| - GrGLSLExpr4 filter =
|
| - color_filter_expression(mode, GrGLSLExpr4(colorFilterColorUniName),
|
| - GrGLSLExpr4(args.fInputColor));
|
| -
|
| - args.fBuilder->getFragmentShaderBuilder()->
|
| - codeAppendf("\t%s = %s;\n", args.fOutputColor, filter.c_str());
|
| - }
|
| -
|
| - static void GenKey(const GrProcessor& fp, const GrGLSLCaps&,
|
| - GrProcessorKeyBuilder* b) {
|
| - const ModeColorFilterEffect& colorModeFilter = fp.cast<ModeColorFilterEffect>();
|
| - // The SL code does not depend on filter color at the moment, so no need to represent it
|
| - // in the key.
|
| - b->add32(colorModeFilter.mode());
|
| - }
|
| -
|
| - protected:
|
| - virtual void onSetData(const GrGLProgramDataManager& pdman,
|
| - const GrProcessor& fp) override {
|
| - if (fFilterColorUni.isValid()) {
|
| - const ModeColorFilterEffect& colorModeFilter = fp.cast<ModeColorFilterEffect>();
|
| - GrGLfloat c[4];
|
| - GrColorToRGBAFloat(colorModeFilter.color(), c);
|
| - pdman.set4fv(fFilterColorUni, 1, c);
|
| - }
|
| - }
|
| -
|
| - private:
|
| -
|
| - GrGLProgramDataManager::UniformHandle fFilterColorUni;
|
| - typedef GrGLFragmentProcessor INHERITED;
|
| - };
|
| -
|
| - GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
|
| -
|
| -private:
|
| - ModeColorFilterEffect(GrColor color, SkXfermode::Mode mode)
|
| - : fMode(mode),
|
| - fColor(color) {
|
| - this->initClassID<ModeColorFilterEffect>();
|
| - }
|
| -
|
| - GrGLFragmentProcessor* onCreateGLInstance() const override { return new GLProcessor(*this); }
|
| -
|
| - virtual void onGetGLProcessorKey(const GrGLSLCaps& caps,
|
| - GrProcessorKeyBuilder* b) const override {
|
| - GLProcessor::GenKey(*this, caps, b);
|
| - }
|
| -
|
| - bool onIsEqual(const GrFragmentProcessor& other) const override {
|
| - const ModeColorFilterEffect& s = other.cast<ModeColorFilterEffect>();
|
| - return fMode == s.fMode && fColor == s.fColor;
|
| - }
|
| -
|
| - void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
|
| -
|
| - SkXfermode::Mode fMode;
|
| - GrColor fColor;
|
| -
|
| - typedef GrFragmentProcessor 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(SkTMax(0.f, SkTMin(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::onComputeInvariantOutput(GrInvariantOutput* inout) const {
|
| - float inputColor[4];
|
| - GrColorToRGBAFloat(inout->color(), inputColor);
|
| - float filterColor[4];
|
| - GrColorToRGBAFloat(fColor, filterColor);
|
| - MaskedColorExpr result =
|
| - color_filter_expression(fMode,
|
| - MaskedColorExpr(filterColor, kRGBA_GrColorComponentFlags),
|
| - MaskedColorExpr(inputColor, inout->validFlags()));
|
| -
|
| - // Check if we will use the input color
|
| - SkXfermode::Coeff dstCoeff;
|
| - SkXfermode::Coeff srcCoeff;
|
| - SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
|
| - GrInvariantOutput::ReadInput readInput = GrInvariantOutput::kWill_ReadInput;
|
| - // These could be calculated from the blend equation with template trickery..
|
| - if (SkXfermode::kZero_Coeff == dstCoeff &&
|
| - !GrBlendCoeffRefsDst(sk_blend_to_grblend(srcCoeff))) {
|
| - readInput = GrInvariantOutput::kWillNot_ReadInput;
|
| - }
|
| - inout->setToOther(result.getValidComponents(), result.getColor(), readInput);
|
| -}
|
| -
|
| -GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ModeColorFilterEffect);
|
| -const GrFragmentProcessor* ModeColorFilterEffect::TestCreate(GrProcessorTestData* d) {
|
| - SkXfermode::Mode mode = SkXfermode::kDst_Mode;
|
| - while (SkXfermode::kDst_Mode == mode) {
|
| - mode = static_cast<SkXfermode::Mode>(d->fRandom->nextRangeU(0, SkXfermode::kLastCoeffMode));
|
| - }
|
| -
|
| - // pick a random premul color
|
| - uint8_t alpha = d->fRandom->nextULessThan(256);
|
| - GrColor color = GrColorPackRGBA(d->fRandom->nextRangeU(0, alpha),
|
| - d->fRandom->nextRangeU(0, alpha),
|
| - d->fRandom->nextRangeU(0, alpha),
|
| - alpha);
|
| - return ModeColorFilterEffect::Create(color, mode);
|
| -}
|
|
|
| bool SkModeColorFilter::asFragmentProcessors(GrContext*, GrProcessorDataManager*,
|
| - SkTDArray<GrFragmentProcessor*>* array) const {
|
| + SkTDArray<const GrFragmentProcessor*>* array) const {
|
| if (SkXfermode::kDst_Mode != fMode) {
|
| - GrFragmentProcessor* frag = ModeColorFilterEffect::Create(SkColor2GrColor(fColor), fMode);
|
| - if (frag) {
|
| + SkAutoTUnref<const GrFragmentProcessor> constFP(
|
| + GrConstColorProcessor::Create(SkColor2GrColor(fColor),
|
| + GrConstColorProcessor::kIgnore_InputMode));
|
| + const GrFragmentProcessor* fp =
|
| + GrXfermodeFragmentProcessor::CreateFromSrcProcessor(constFP, fMode);
|
| + if (fp) {
|
| +#ifdef SK_DEBUG
|
| + // With a solid color input this should always be able to compute the blended color
|
| + // (at least for coeff modes)
|
| + if (fMode <= SkXfermode::kLastCoeffMode) {
|
| + static SkRandom gRand;
|
| + GrInvariantOutput io(GrPremulColor(gRand.nextU()), kRGBA_GrColorComponentFlags,
|
| + false);
|
| + fp->computeInvariantOutput(&io);
|
| + SkASSERT(io.validFlags() == kRGBA_GrColorComponentFlags);
|
| + }
|
| +#endif
|
| if (array) {
|
| - *array->append() = frag;
|
| + *array->append() = fp;
|
| } else {
|
| - frag->unref();
|
| - SkDEBUGCODE(frag = nullptr;)
|
| + fp->unref();
|
| + SkDEBUGCODE(fp = nullptr;)
|
| }
|
| return true;
|
| }
|
|
|