1 /*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7 
8 #include "GrFragmentProcessor.h"
9 #include "GrCoordTransform.h"
10 #include "GrInvariantOutput.h"
11 #include "GrPipeline.h"
12 #include "GrProcOptInfo.h"
13 #include "glsl/GrGLSLFragmentProcessor.h"
14 #include "glsl/GrGLSLFragmentShaderBuilder.h"
15 #include "glsl/GrGLSLProgramDataManager.h"
16 #include "glsl/GrGLSLUniformHandler.h"
17 #include "effects/GrConstColorProcessor.h"
18 #include "effects/GrXfermodeFragmentProcessor.h"
19 
~GrFragmentProcessor()20 GrFragmentProcessor::~GrFragmentProcessor() {
21     // If we got here then our ref count must have reached zero, so we will have converted refs
22     // to pending executions for all children.
23     for (int i = 0; i < fChildProcessors.count(); ++i) {
24         fChildProcessors[i]->completedExecution();
25     }
26 }
27 
isEqual(const GrFragmentProcessor & that) const28 bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that) const {
29     if (this->classID() != that.classID() ||
30         !this->hasSameSamplers(that)) {
31         return false;
32     }
33     if (!this->hasSameTransforms(that)) {
34         return false;
35     }
36     if (!this->onIsEqual(that)) {
37         return false;
38     }
39     if (this->numChildProcessors() != that.numChildProcessors()) {
40         return false;
41     }
42     for (int i = 0; i < this->numChildProcessors(); ++i) {
43         if (!this->childProcessor(i).isEqual(that.childProcessor(i))) {
44             return false;
45         }
46     }
47     return true;
48 }
49 
createGLSLInstance() const50 GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const {
51     GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance();
52     glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
53     for (int i = 0; i < fChildProcessors.count(); ++i) {
54         glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLSLInstance();
55     }
56     return glFragProc;
57 }
58 
addTextureAccess(const GrTextureAccess * textureAccess)59 void GrFragmentProcessor::addTextureAccess(const GrTextureAccess* textureAccess) {
60     INHERITED::addTextureAccess(textureAccess);
61 }
62 
addBufferAccess(const GrBufferAccess * bufferAccess)63 void GrFragmentProcessor::addBufferAccess(const GrBufferAccess* bufferAccess) {
64     INHERITED::addBufferAccess(bufferAccess);
65 }
66 
addCoordTransform(const GrCoordTransform * transform)67 void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
68     fCoordTransforms.push_back(transform);
69     fUsesLocalCoords = true;
70     SkDEBUGCODE(transform->setInProcessor();)
71 }
72 
registerChildProcessor(sk_sp<GrFragmentProcessor> child)73 int GrFragmentProcessor::registerChildProcessor(sk_sp<GrFragmentProcessor> child) {
74     this->combineRequiredFeatures(*child);
75 
76     if (child->usesLocalCoords()) {
77         fUsesLocalCoords = true;
78     }
79     if (child->usesDistanceVectorField()) {
80         fUsesDistanceVectorField = true;
81     }
82 
83     int index = fChildProcessors.count();
84     fChildProcessors.push_back(child.release());
85 
86     return index;
87 }
88 
notifyRefCntIsZero() const89 void GrFragmentProcessor::notifyRefCntIsZero() const {
90     // See comment above GrProgramElement for a detailed explanation of why we do this.
91     for (int i = 0; i < fChildProcessors.count(); ++i) {
92         fChildProcessors[i]->addPendingExecution();
93         fChildProcessors[i]->unref();
94     }
95 }
96 
hasSameTransforms(const GrFragmentProcessor & that) const97 bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
98     if (this->numCoordTransforms() != that.numCoordTransforms()) {
99         return false;
100     }
101     int count = this->numCoordTransforms();
102     for (int i = 0; i < count; ++i) {
103         if (this->coordTransform(i) != that.coordTransform(i)) {
104             return false;
105         }
106     }
107     return true;
108 }
109 
MulOutputByInputAlpha(sk_sp<GrFragmentProcessor> fp)110 sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputAlpha(
111     sk_sp<GrFragmentProcessor> fp) {
112     if (!fp) {
113         return nullptr;
114     }
115     return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp),
116                                                              SkXfermode::kDstIn_Mode);
117 }
118 
PremulInput(sk_sp<GrFragmentProcessor> fp)119 sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulInput(sk_sp<GrFragmentProcessor> fp) {
120 
121     class PremulInputFragmentProcessor : public GrFragmentProcessor {
122     public:
123         PremulInputFragmentProcessor() {
124             this->initClassID<PremulInputFragmentProcessor>();
125         }
126 
127         const char* name() const override { return "PremultiplyInput"; }
128 
129     private:
130         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
131             class GLFP : public GrGLSLFragmentProcessor {
132             public:
133                 void emitCode(EmitArgs& args) override {
134                     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
135 
136                     fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
137                     fragBuilder->codeAppendf("%s.rgb *= %s.a;",
138                                              args.fOutputColor, args.fInputColor);
139                 }
140             };
141             return new GLFP;
142         }
143 
144         void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
145 
146         bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
147 
148         void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
149             inout->premulFourChannelColor();
150         }
151     };
152     if (!fp) {
153         return nullptr;
154     }
155     sk_sp<GrFragmentProcessor> fpPipeline[] = { sk_make_sp<PremulInputFragmentProcessor>(), fp};
156     return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
157 }
158 
MulOutputByInputUnpremulColor(sk_sp<GrFragmentProcessor> fp)159 sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputUnpremulColor(
160     sk_sp<GrFragmentProcessor> fp) {
161 
162     class PremulFragmentProcessor : public GrFragmentProcessor {
163     public:
164         PremulFragmentProcessor(sk_sp<GrFragmentProcessor> processor) {
165             this->initClassID<PremulFragmentProcessor>();
166             this->registerChildProcessor(processor);
167         }
168 
169         const char* name() const override { return "Premultiply"; }
170 
171     private:
172         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
173             class GLFP : public GrGLSLFragmentProcessor {
174             public:
175                 void emitCode(EmitArgs& args) override {
176                     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
177                     this->emitChild(0, nullptr, args);
178                     fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
179                                                                 args.fInputColor);
180                     fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
181                 }
182             };
183             return new GLFP;
184         }
185 
186         void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
187 
188         bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
189 
190         void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
191             // TODO: Add a helper to GrInvariantOutput that handles multiplying by color with flags?
192             if (!(inout->validFlags() & kA_GrColorComponentFlag)) {
193                 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
194                 return;
195             }
196 
197             GrInvariantOutput childOutput(GrColor_WHITE, kRGBA_GrColorComponentFlags, false);
198             this->childProcessor(0).computeInvariantOutput(&childOutput);
199 
200             if (0 == GrColorUnpackA(inout->color()) || 0 == GrColorUnpackA(childOutput.color())) {
201                 inout->mulByKnownFourComponents(0x0);
202                 return;
203             }
204             GrColorComponentFlags commonFlags = childOutput.validFlags() & inout->validFlags();
205             GrColor c0 = GrPremulColor(inout->color());
206             GrColor c1 = childOutput.color();
207             GrColor color = 0x0;
208             if (commonFlags & kR_GrColorComponentFlag) {
209                 color |= SkMulDiv255Round(GrColorUnpackR(c0), GrColorUnpackR(c1)) <<
210                     GrColor_SHIFT_R;
211             }
212             if (commonFlags & kG_GrColorComponentFlag) {
213                 color |= SkMulDiv255Round(GrColorUnpackG(c0), GrColorUnpackG(c1)) <<
214                     GrColor_SHIFT_G;
215             }
216             if (commonFlags & kB_GrColorComponentFlag) {
217                 color |= SkMulDiv255Round(GrColorUnpackB(c0), GrColorUnpackB(c1)) <<
218                     GrColor_SHIFT_B;
219             }
220             inout->setToOther(commonFlags, color, GrInvariantOutput::kWill_ReadInput);
221         }
222     };
223     if (!fp) {
224         return nullptr;
225     }
226     return sk_sp<GrFragmentProcessor>(new PremulFragmentProcessor(std::move(fp)));
227 }
228 
229 //////////////////////////////////////////////////////////////////////////////
230 
OverrideInput(sk_sp<GrFragmentProcessor> fp,GrColor4f color)231 sk_sp<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(sk_sp<GrFragmentProcessor> fp,
232                                                               GrColor4f color) {
233     class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
234     public:
235         ReplaceInputFragmentProcessor(sk_sp<GrFragmentProcessor> child, GrColor4f color)
236             : fColor(color) {
237             this->initClassID<ReplaceInputFragmentProcessor>();
238             this->registerChildProcessor(std::move(child));
239         }
240 
241         const char* name() const override { return "Replace Color"; }
242 
243         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
244             class GLFP : public GrGLSLFragmentProcessor {
245             public:
246                 GLFP() : fHaveSetColor(false) {}
247                 void emitCode(EmitArgs& args) override {
248                     const char* colorName;
249                     fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
250                                                                  kVec4f_GrSLType,
251                                                                  kDefault_GrSLPrecision,
252                                                                  "Color", &colorName);
253                     this->emitChild(0, colorName, args);
254                 }
255 
256             private:
257                 void onSetData(const GrGLSLProgramDataManager& pdman,
258                                const GrProcessor& fp) override {
259                     GrColor4f color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
260                     if (!fHaveSetColor || color != fPreviousColor) {
261                         pdman.set4fv(fColorUni, 1, color.fRGBA);
262                         fPreviousColor = color;
263                         fHaveSetColor = true;
264                     }
265                 }
266 
267                 GrGLSLProgramDataManager::UniformHandle fColorUni;
268                 bool      fHaveSetColor;
269                 GrColor4f fPreviousColor;
270             };
271 
272             return new GLFP;
273         }
274 
275     private:
276         void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override
277         {}
278 
279         bool onIsEqual(const GrFragmentProcessor& that) const override {
280             return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
281         }
282 
283         void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
284             inout->setToOther(kRGBA_GrColorComponentFlags, fColor.toGrColor(),
285                               GrInvariantOutput::kWillNot_ReadInput);
286             this->childProcessor(0).computeInvariantOutput(inout);
287         }
288 
289         GrColor4f fColor;
290     };
291 
292     GrInvariantOutput childOut(0x0, kNone_GrColorComponentFlags, false);
293     fp->computeInvariantOutput(&childOut);
294     if (childOut.willUseInputColor()) {
295         return sk_sp<GrFragmentProcessor>(new ReplaceInputFragmentProcessor(std::move(fp), color));
296     } else {
297         return fp;
298     }
299 }
300 
RunInSeries(sk_sp<GrFragmentProcessor> * series,int cnt)301 sk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProcessor>* series,
302                                                             int cnt) {
303     class SeriesFragmentProcessor : public GrFragmentProcessor {
304     public:
305         SeriesFragmentProcessor(sk_sp<GrFragmentProcessor>* children, int cnt){
306             SkASSERT(cnt > 1);
307             this->initClassID<SeriesFragmentProcessor>();
308             for (int i = 0; i < cnt; ++i) {
309                 this->registerChildProcessor(std::move(children[i]));
310             }
311         }
312 
313         const char* name() const override { return "Series"; }
314 
315         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
316             class GLFP : public GrGLSLFragmentProcessor {
317             public:
318                 void emitCode(EmitArgs& args) override {
319                     // First guy's input might be nil.
320                     SkString temp("out0");
321                     this->emitChild(0, args.fInputColor, &temp, args);
322                     SkString input = temp;
323                     for (int i = 1; i < this->numChildProcessors() - 1; ++i) {
324                         temp.printf("out%d", i);
325                         this->emitChild(i, input.c_str(), &temp, args);
326                         input = temp;
327                     }
328                     // Last guy writes to our output variable.
329                     this->emitChild(this->numChildProcessors() - 1, input.c_str(), args);
330                 }
331             };
332             return new GLFP;
333         }
334 
335     private:
336         void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
337 
338         bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
339 
340         void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
341             GrProcOptInfo info;
342             info.calcWithInitialValues(fChildProcessors.begin(), fChildProcessors.count(),
343                                        inout->color(), inout->validFlags(), false, false);
344             for (int i = 0; i < this->numChildProcessors(); ++i) {
345                 this->childProcessor(i).computeInvariantOutput(inout);
346             }
347         }
348     };
349 
350     if (!cnt) {
351         return nullptr;
352     }
353 
354     // Run the through the series, do the invariant output processing, and look for eliminations.
355     GrProcOptInfo info;
356     info.calcWithInitialValues(sk_sp_address_as_pointer_address(series), cnt,
357                                0x0, kNone_GrColorComponentFlags, false, false);
358     if (kRGBA_GrColorComponentFlags == info.validFlags()) {
359         return GrConstColorProcessor::Make(info.color(), GrConstColorProcessor::kIgnore_InputMode);
360     }
361 
362     SkTArray<sk_sp<GrFragmentProcessor>> replacementSeries;
363 
364     int firstIdx = info.firstEffectiveProcessorIndex();
365     cnt -= firstIdx;
366     if (firstIdx > 0 && info.inputColorIsUsed()) {
367         sk_sp<GrFragmentProcessor> colorFP(GrConstColorProcessor::Make(
368             info.inputColorToFirstEffectiveProccesor(), GrConstColorProcessor::kIgnore_InputMode));
369         cnt += 1;
370         replacementSeries.reserve(cnt);
371         replacementSeries.emplace_back(std::move(colorFP));
372         for (int i = 0; i < cnt - 1; ++i) {
373             replacementSeries.emplace_back(std::move(series[firstIdx + i]));
374         }
375         series = replacementSeries.begin();
376     } else {
377         series += firstIdx;
378         cnt -= firstIdx;
379     }
380 
381     if (1 == cnt) {
382         return series[0];
383     }
384     return sk_sp<GrFragmentProcessor>(new SeriesFragmentProcessor(series, cnt));
385 }
386 
387 //////////////////////////////////////////////////////////////////////////////
388 
Iter(const GrPipeline & pipeline)389 GrFragmentProcessor::Iter::Iter(const GrPipeline& pipeline) {
390     for (int i = pipeline.numFragmentProcessors() - 1; i >= 0; --i) {
391         fFPStack.push_back(&pipeline.getFragmentProcessor(i));
392     }
393 }
394 
next()395 const GrFragmentProcessor* GrFragmentProcessor::Iter::next() {
396     if (fFPStack.empty()) {
397         return nullptr;
398     }
399     const GrFragmentProcessor* back = fFPStack.back();
400     fFPStack.pop_back();
401     for (int i = back->numChildProcessors() - 1; i >= 0; --i) {
402         fFPStack.push_back(&back->childProcessor(i));
403     }
404     return back;
405 }
406 
407