Index: src/gpu/GrFragmentProcessor.cpp |
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp |
index b6a80abf8a778550b4a3f099a9d43dd7d73f1e6c..d1a3fa161e405e96a9572526123d3ebbc3546a18 100644 |
--- a/src/gpu/GrFragmentProcessor.cpp |
+++ b/src/gpu/GrFragmentProcessor.cpp |
@@ -10,6 +10,7 @@ |
#include "GrCoordTransform.h" |
#include "gl/GrGLFragmentProcessor.h" |
#include "gl/builders/GrGLProgramBuilder.h" |
+#include "effects/GrConstColorProcessor.h" |
#include "effects/GrXfermodeFragmentProcessor.h" |
GrFragmentProcessor::~GrFragmentProcessor() { |
@@ -279,3 +280,96 @@ const GrFragmentProcessor* GrFragmentProcessor::OverrideInput(const GrFragmentPr |
return SkRef(fp); |
} |
} |
+ |
+const GrFragmentProcessor* GrFragmentProcessor::RunInSeries(const GrFragmentProcessor* series[], |
+ int cnt) { |
+ class SeriesFragmentProcessor : public GrFragmentProcessor { |
+ public: |
+ SeriesFragmentProcessor(const GrFragmentProcessor* children[], int cnt){ |
+ SkASSERT(cnt > 1); |
+ this->initClassID<SeriesFragmentProcessor>(); |
+ for (int i = 0; i < cnt; ++i) { |
+ this->registerChildProcessor(children[i]); |
+ } |
+ } |
+ |
+ const char* name() const override { return "Series"; } |
+ |
+ GrGLFragmentProcessor* onCreateGLInstance() const override { |
+ class GLFP : public GrGLFragmentProcessor { |
+ public: |
+ GLFP() {} |
+ void emitCode(EmitArgs& args) override { |
+ SkString input(args.fInputColor); |
+ for (int i = 0; i < this->numChildProcessors() - 1; ++i) { |
+ SkString temp; |
+ temp.printf("out%d", i); |
+ this->emitChild(i, input.c_str(), &temp, args); |
+ input = temp; |
+ } |
+ // Last guy writes to our output variable. |
+ this->emitChild(this->numChildProcessors() - 1, input.c_str(), args); |
+ } |
+ }; |
+ return new GLFP; |
+ } |
+ |
+ private: |
+ void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {} |
+ |
+ bool onIsEqual(const GrFragmentProcessor&) const override { return true; } |
+ |
+ void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
+ GrProcOptInfo info; |
+ SkTDArray<const GrFragmentProcessor*> children; |
+ children.setCount(this->numChildProcessors()); |
+ for (int i = 0; i < children.count(); ++i) { |
+ children[i] = &this->childProcessor(i); |
+ } |
+ info.calcWithInitialValues(children.begin(), children.count(), inout->color(), |
+ inout->validFlags(), false, false); |
+ for (int i = 0; i < this->numChildProcessors(); ++i) { |
+ this->childProcessor(i).computeInvariantOutput(inout); |
+ } |
+ } |
+ }; |
+ |
+ if (!cnt) { |
+ return nullptr; |
+ } |
+ |
+ // Run the through the series, do the invariant output processing, and look for eliminations. |
+ SkTDArray<const GrFragmentProcessor*> replacementSeries; |
+ SkAutoTUnref<const GrFragmentProcessor> colorFP; |
+ GrProcOptInfo info; |
+ |
+ info.calcWithInitialValues(series, cnt, 0x0, kNone_GrColorComponentFlags, false, false); |
+ if (kRGBA_GrColorComponentFlags == info.validFlags()) { |
+ return GrConstColorProcessor::Create(info.color(), |
+ GrConstColorProcessor::kIgnore_InputMode); |
+ } else { |
+ int firstIdx = info.firstEffectiveProcessorIndex(); |
+ cnt -= firstIdx; |
+ if (firstIdx > 0 && info.inputColorIsUsed()) { |
+ colorFP.reset(GrConstColorProcessor::Create(info.inputColorToFirstEffectiveProccesor(), |
+ GrConstColorProcessor::kIgnore_InputMode)); |
+ cnt += 1; |
+ replacementSeries.setCount(cnt); |
+ replacementSeries[0] = colorFP; |
+ for (int i = 0; i < cnt - 1; ++i) { |
+ replacementSeries[i + 1] = series[firstIdx + i]; |
+ } |
+ series = replacementSeries.begin(); |
+ } else { |
+ series += firstIdx; |
+ cnt -= firstIdx; |
+ } |
+ } |
+ |
+ if (1 == cnt) { |
+ return SkRef(series[0]); |
+ } else { |
+ return new SeriesFragmentProcessor(series, cnt); |
+ } |
+} |
+ |