Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Unified Diff: src/effects/SkColorFilters.cpp

Issue 1334293003: Create fragment processor for performing input color blend with child processor (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/effects/SkColorCubeFilter.cpp ('k') | src/effects/SkColorMatrixFilter.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
}
« no previous file with comments | « src/effects/SkColorCubeFilter.cpp ('k') | src/effects/SkColorMatrixFilter.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698