Index: src/gpu/GrFragmentProcessor.cpp |
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp |
index fcc9c74fa4ac5778870374f71ff6fbbbb5b1d257..b6a80abf8a778550b4a3f099a9d43dd7d73f1e6c 100644 |
--- a/src/gpu/GrFragmentProcessor.cpp |
+++ b/src/gpu/GrFragmentProcessor.cpp |
@@ -9,6 +9,7 @@ |
#include "GrFragmentProcessor.h" |
#include "GrCoordTransform.h" |
#include "gl/GrGLFragmentProcessor.h" |
+#include "gl/builders/GrGLProgramBuilder.h" |
#include "effects/GrXfermodeFragmentProcessor.h" |
GrFragmentProcessor::~GrFragmentProcessor() { |
@@ -122,8 +123,159 @@ bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) con |
return true; |
} |
-const GrFragmentProcessor* GrFragmentProcessor::MulOuputByInputAlpha( |
+const GrFragmentProcessor* GrFragmentProcessor::MulOutputByInputAlpha( |
const GrFragmentProcessor* fp) { |
+ if (!fp) { |
+ return nullptr; |
+ } |
return GrXfermodeFragmentProcessor::CreateFromDstProcessor(fp, SkXfermode::kDstIn_Mode); |
} |
+const GrFragmentProcessor* GrFragmentProcessor::MulOutputByInputUnpremulColor( |
+ const GrFragmentProcessor* fp) { |
+ |
+ class PremulFragmentProcessor : public GrFragmentProcessor { |
+ public: |
+ PremulFragmentProcessor(const GrFragmentProcessor* processor) { |
+ this->initClassID<PremulFragmentProcessor>(); |
+ this->registerChildProcessor(processor); |
+ } |
+ |
+ const char* name() const override { return "Premultiply"; } |
+ |
+ private: |
+ GrGLFragmentProcessor* onCreateGLInstance() const override { |
+ class GLFP : public GrGLFragmentProcessor { |
+ public: |
+ GLFP() {} |
+ |
+ void emitCode(EmitArgs& args) override { |
+ GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); |
+ this->emitChild(0, nullptr, args); |
+ fsBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor, |
+ args.fInputColor); |
+ fsBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor); |
+ } |
+ }; |
+ return new GLFP; |
+ } |
+ |
+ void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {} |
+ |
+ bool onIsEqual(const GrFragmentProcessor&) const override { return true; } |
+ |
+ void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
+ // TODO: Add a helper to GrInvariantOutput that handles multiplying by color with flags? |
+ if (!(inout->validFlags() & kA_GrColorComponentFlag)) { |
+ inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); |
+ return; |
+ } |
+ |
+ GrInvariantOutput childOutput(GrColor_WHITE, kRGBA_GrColorComponentFlags, false); |
+ this->childProcessor(0).computeInvariantOutput(&childOutput); |
+ |
+ if (0 == GrColorUnpackA(inout->color()) || 0 == GrColorUnpackA(childOutput.color())) { |
+ inout->mulByKnownFourComponents(0x0); |
+ return; |
+ } |
+ GrColorComponentFlags commonFlags = childOutput.validFlags() & inout->validFlags(); |
+ GrColor c0 = GrPremulColor(inout->color()); |
+ GrColor c1 = childOutput.color(); |
+ GrColor color = 0x0; |
+ if (commonFlags & kR_GrColorComponentFlag) { |
+ color |= SkMulDiv255Round(GrColorUnpackR(c0), GrColorUnpackR(c1)) << |
+ GrColor_SHIFT_R; |
+ } |
+ if (commonFlags & kG_GrColorComponentFlag) { |
+ color |= SkMulDiv255Round(GrColorUnpackG(c0), GrColorUnpackG(c1)) << |
+ GrColor_SHIFT_G; |
+ } |
+ if (commonFlags & kB_GrColorComponentFlag) { |
+ color |= SkMulDiv255Round(GrColorUnpackB(c0), GrColorUnpackB(c1)) << |
+ GrColor_SHIFT_B; |
+ } |
+ inout->setToOther(commonFlags, color, GrInvariantOutput::kWill_ReadInput); |
+ } |
+ }; |
+ if (!fp) { |
+ return nullptr; |
+ } |
+ return new PremulFragmentProcessor(fp); |
+} |
+ |
+////////////////////////////////////////////////////////////////////////////// |
+ |
+const GrFragmentProcessor* GrFragmentProcessor::OverrideInput(const GrFragmentProcessor* fp, |
+ GrColor color) { |
+ class ReplaceInputFragmentProcessor : public GrFragmentProcessor { |
+ public: |
+ ReplaceInputFragmentProcessor(const GrFragmentProcessor* child, GrColor color) |
+ : fColor(color) { |
+ this->initClassID<ReplaceInputFragmentProcessor>(); |
+ this->registerChildProcessor(child); |
+ } |
+ |
+ const char* name() const override { return "Replace Color"; } |
+ |
+ GrGLFragmentProcessor* onCreateGLInstance() const override { |
+ class GLFP : public GrGLFragmentProcessor { |
+ public: |
+ GLFP() : fHaveSetColor(false) {} |
+ void emitCode(EmitArgs& args) override { |
+ const char* colorName; |
+ fColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, |
+ kVec4f_GrSLType, kDefault_GrSLPrecision, |
+ "Color", &colorName); |
+ this->emitChild(0, colorName, args); |
+ } |
+ |
+ private: |
+ void onSetData(const GrGLProgramDataManager& pdman, |
+ const GrProcessor& fp) override { |
+ GrColor color = fp.cast<ReplaceInputFragmentProcessor>().fColor; |
+ if (!fHaveSetColor || color != fPreviousColor) { |
+ static const GrGLfloat scale = 1.f / 255.f; |
+ GrGLfloat floatColor[4] = { |
+ GrColorUnpackR(color) * scale, |
+ GrColorUnpackG(color) * scale, |
+ GrColorUnpackB(color) * scale, |
+ GrColorUnpackA(color) * scale, |
+ }; |
+ pdman.set4fv(fColorUni, 1, floatColor); |
+ fPreviousColor = color; |
+ fHaveSetColor = true; |
+ } |
+ } |
+ |
+ GrGLProgramDataManager::UniformHandle fColorUni; |
+ bool fHaveSetColor; |
+ GrColor fPreviousColor; |
+ }; |
+ |
+ return new GLFP; |
+ } |
+ |
+ private: |
+ void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {} |
+ |
+ bool onIsEqual(const GrFragmentProcessor& that) const override { |
+ return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor; |
+ } |
+ |
+ void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
+ inout->setToOther(kRGBA_GrColorComponentFlags, fColor, |
+ GrInvariantOutput::kWillNot_ReadInput); |
+ this->childProcessor(0).computeInvariantOutput(inout); |
+ } |
+ |
+ GrColor fColor; |
+ }; |
+ |
+ GrInvariantOutput childOut(0x0, kNone_GrColorComponentFlags, false); |
+ fp->computeInvariantOutput(&childOut); |
+ if (childOut.willUseInputColor()) { |
+ return new ReplaceInputFragmentProcessor(fp, color); |
+ } else { |
+ return SkRef(fp); |
+ } |
+} |