• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3 * Copyright 2015 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8 
9 #include "GrFragmentProcessor.h"
10 #include "GrCoordTransform.h"
11 #include "GrInvariantOutput.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,bool ignoreCoordTransforms) const28 bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that,
29                                   bool ignoreCoordTransforms) const {
30     if (this->classID() != that.classID() ||
31         !this->hasSameTextureAccesses(that)) {
32         return false;
33     }
34     if (ignoreCoordTransforms) {
35         if (this->numTransforms() != that.numTransforms()) {
36             return false;
37         }
38     } else if (!this->hasSameTransforms(that)) {
39         return false;
40     }
41     if (!this->onIsEqual(that)) {
42         return false;
43     }
44     if (this->numChildProcessors() != that.numChildProcessors()) {
45         return false;
46     }
47     for (int i = 0; i < this->numChildProcessors(); ++i) {
48         if (!this->childProcessor(i).isEqual(that.childProcessor(i), ignoreCoordTransforms)) {
49             return false;
50         }
51     }
52     return true;
53 }
54 
createGLSLInstance() const55 GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const {
56     GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance();
57     glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
58     for (int i = 0; i < fChildProcessors.count(); ++i) {
59         glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLSLInstance();
60     }
61     return glFragProc;
62 }
63 
addTextureAccess(const GrTextureAccess * textureAccess)64 void GrFragmentProcessor::addTextureAccess(const GrTextureAccess* textureAccess) {
65     // Can't add texture accesses after registering any children since their texture accesses have
66     // already been bubbled up into our fTextureAccesses array
67     SkASSERT(fChildProcessors.empty());
68 
69     INHERITED::addTextureAccess(textureAccess);
70     fNumTexturesExclChildren++;
71 }
72 
addCoordTransform(const GrCoordTransform * transform)73 void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
74     // Can't add transforms after registering any children since their transforms have already been
75     // bubbled up into our fCoordTransforms array
76     SkASSERT(fChildProcessors.empty());
77 
78     fCoordTransforms.push_back(transform);
79     fUsesLocalCoords = fUsesLocalCoords || transform->sourceCoords() == kLocal_GrCoordSet;
80     SkDEBUGCODE(transform->setInProcessor();)
81     fNumTransformsExclChildren++;
82 }
83 
registerChildProcessor(const GrFragmentProcessor * child)84 int GrFragmentProcessor::registerChildProcessor(const GrFragmentProcessor* child) {
85     // Append the child's transforms to our transforms array and the child's textures array to our
86     // textures array
87     if (!child->fCoordTransforms.empty()) {
88         fCoordTransforms.push_back_n(child->fCoordTransforms.count(),
89                                      child->fCoordTransforms.begin());
90     }
91     if (!child->fTextureAccesses.empty()) {
92         fTextureAccesses.push_back_n(child->fTextureAccesses.count(),
93                                      child->fTextureAccesses.begin());
94     }
95 
96     int index = fChildProcessors.count();
97     fChildProcessors.push_back(SkRef(child));
98 
99     if (child->willReadFragmentPosition()) {
100         this->setWillReadFragmentPosition();
101     }
102 
103     if (child->usesLocalCoords()) {
104         fUsesLocalCoords = true;
105     }
106 
107     return index;
108 }
109 
notifyRefCntIsZero() const110 void GrFragmentProcessor::notifyRefCntIsZero() const {
111     // See comment above GrProgramElement for a detailed explanation of why we do this.
112     for (int i = 0; i < fChildProcessors.count(); ++i) {
113         fChildProcessors[i]->addPendingExecution();
114         fChildProcessors[i]->unref();
115     }
116 }
117 
hasSameTransforms(const GrFragmentProcessor & that) const118 bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
119     if (this->numTransforms() != that.numTransforms()) {
120         return false;
121     }
122     int count = this->numTransforms();
123     for (int i = 0; i < count; ++i) {
124         if (this->coordTransform(i) != that.coordTransform(i)) {
125             return false;
126         }
127     }
128     return true;
129 }
130 
MulOutputByInputAlpha(const GrFragmentProcessor * fp)131 const GrFragmentProcessor* GrFragmentProcessor::MulOutputByInputAlpha(
132     const GrFragmentProcessor* fp) {
133     if (!fp) {
134         return nullptr;
135     }
136     return GrXfermodeFragmentProcessor::CreateFromDstProcessor(fp, SkXfermode::kDstIn_Mode);
137 }
138 
MulOutputByInputUnpremulColor(const GrFragmentProcessor * fp)139 const GrFragmentProcessor* GrFragmentProcessor::MulOutputByInputUnpremulColor(
140     const GrFragmentProcessor* fp) {
141 
142     class PremulFragmentProcessor : public GrFragmentProcessor {
143     public:
144         PremulFragmentProcessor(const GrFragmentProcessor* processor) {
145             this->initClassID<PremulFragmentProcessor>();
146             this->registerChildProcessor(processor);
147         }
148 
149         const char* name() const override { return "Premultiply"; }
150 
151     private:
152         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
153             class GLFP : public GrGLSLFragmentProcessor {
154             public:
155                 void emitCode(EmitArgs& args) override {
156                     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
157                     this->emitChild(0, nullptr, args);
158                     fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
159                                                                 args.fInputColor);
160                     fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
161                 }
162             };
163             return new GLFP;
164         }
165 
166         void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
167 
168         bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
169 
170         void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
171             // TODO: Add a helper to GrInvariantOutput that handles multiplying by color with flags?
172             if (!(inout->validFlags() & kA_GrColorComponentFlag)) {
173                 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
174                 return;
175             }
176 
177             GrInvariantOutput childOutput(GrColor_WHITE, kRGBA_GrColorComponentFlags, false);
178             this->childProcessor(0).computeInvariantOutput(&childOutput);
179 
180             if (0 == GrColorUnpackA(inout->color()) || 0 == GrColorUnpackA(childOutput.color())) {
181                 inout->mulByKnownFourComponents(0x0);
182                 return;
183             }
184             GrColorComponentFlags commonFlags = childOutput.validFlags() & inout->validFlags();
185             GrColor c0 = GrPremulColor(inout->color());
186             GrColor c1 = childOutput.color();
187             GrColor color = 0x0;
188             if (commonFlags & kR_GrColorComponentFlag) {
189                 color |= SkMulDiv255Round(GrColorUnpackR(c0), GrColorUnpackR(c1)) <<
190                     GrColor_SHIFT_R;
191             }
192             if (commonFlags & kG_GrColorComponentFlag) {
193                 color |= SkMulDiv255Round(GrColorUnpackG(c0), GrColorUnpackG(c1)) <<
194                     GrColor_SHIFT_G;
195             }
196             if (commonFlags & kB_GrColorComponentFlag) {
197                 color |= SkMulDiv255Round(GrColorUnpackB(c0), GrColorUnpackB(c1)) <<
198                     GrColor_SHIFT_B;
199             }
200             inout->setToOther(commonFlags, color, GrInvariantOutput::kWill_ReadInput);
201         }
202     };
203     if (!fp) {
204         return nullptr;
205     }
206     return new PremulFragmentProcessor(fp);
207 }
208 
209 //////////////////////////////////////////////////////////////////////////////
210 
OverrideInput(const GrFragmentProcessor * fp,GrColor color)211 const GrFragmentProcessor* GrFragmentProcessor::OverrideInput(const GrFragmentProcessor* fp,
212                                                               GrColor color) {
213     class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
214     public:
215         ReplaceInputFragmentProcessor(const GrFragmentProcessor* child, GrColor color)
216             : fColor(color) {
217             this->initClassID<ReplaceInputFragmentProcessor>();
218             this->registerChildProcessor(child);
219         }
220 
221         const char* name() const override { return "Replace Color"; }
222 
223         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
224             class GLFP : public GrGLSLFragmentProcessor {
225             public:
226                 GLFP() : fHaveSetColor(false) {}
227                 void emitCode(EmitArgs& args) override {
228                     const char* colorName;
229                     fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
230                                                                  kVec4f_GrSLType,
231                                                                  kDefault_GrSLPrecision,
232                                                                  "Color", &colorName);
233                     this->emitChild(0, colorName, args);
234                 }
235 
236             private:
237                 void onSetData(const GrGLSLProgramDataManager& pdman,
238                                const GrProcessor& fp) override {
239                     GrColor color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
240                     if (!fHaveSetColor || color != fPreviousColor) {
241                         static const float scale = 1.f / 255.f;
242                         float floatColor[4] = {
243                             GrColorUnpackR(color) * scale,
244                             GrColorUnpackG(color) * scale,
245                             GrColorUnpackB(color) * scale,
246                             GrColorUnpackA(color) * scale,
247                         };
248                         pdman.set4fv(fColorUni, 1, floatColor);
249                         fPreviousColor = color;
250                         fHaveSetColor = true;
251                     }
252                 }
253 
254                 GrGLSLProgramDataManager::UniformHandle fColorUni;
255                 bool    fHaveSetColor;
256                 GrColor fPreviousColor;
257             };
258 
259             return new GLFP;
260         }
261 
262     private:
263         void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override
264         {}
265 
266         bool onIsEqual(const GrFragmentProcessor& that) const override {
267             return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
268         }
269 
270         void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
271             inout->setToOther(kRGBA_GrColorComponentFlags, fColor,
272                               GrInvariantOutput::kWillNot_ReadInput);
273             this->childProcessor(0).computeInvariantOutput(inout);
274         }
275 
276         GrColor fColor;
277     };
278 
279     GrInvariantOutput childOut(0x0, kNone_GrColorComponentFlags, false);
280     fp->computeInvariantOutput(&childOut);
281     if (childOut.willUseInputColor()) {
282         return new ReplaceInputFragmentProcessor(fp, color);
283     } else {
284         return SkRef(fp);
285     }
286 }
287 
RunInSeries(const GrFragmentProcessor * series[],int cnt)288 const GrFragmentProcessor* GrFragmentProcessor::RunInSeries(const GrFragmentProcessor* series[],
289                                                             int cnt) {
290     class SeriesFragmentProcessor : public GrFragmentProcessor {
291     public:
292         SeriesFragmentProcessor(const GrFragmentProcessor* children[], int cnt){
293             SkASSERT(cnt > 1);
294             this->initClassID<SeriesFragmentProcessor>();
295             for (int i = 0; i < cnt; ++i) {
296                 this->registerChildProcessor(children[i]);
297             }
298         }
299 
300         const char* name() const override { return "Series"; }
301 
302         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
303             class GLFP : public GrGLSLFragmentProcessor {
304             public:
305                 void emitCode(EmitArgs& args) override {
306                     SkString input(args.fInputColor);
307                     for (int i = 0; i < this->numChildProcessors() - 1; ++i) {
308                         SkString temp;
309                         temp.printf("out%d", i);
310                         this->emitChild(i, input.c_str(), &temp, args);
311                         input = temp;
312                     }
313                     // Last guy writes to our output variable.
314                     this->emitChild(this->numChildProcessors() - 1, input.c_str(), args);
315                 }
316             };
317             return new GLFP;
318         }
319 
320     private:
321         void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
322 
323         bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
324 
325         void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
326             GrProcOptInfo info;
327             SkTDArray<const GrFragmentProcessor*> children;
328             children.setCount(this->numChildProcessors());
329             for (int i = 0; i < children.count(); ++i) {
330                 children[i] = &this->childProcessor(i);
331             }
332             info.calcWithInitialValues(children.begin(), children.count(), inout->color(),
333                                        inout->validFlags(), false, false);
334             for (int i = 0; i < this->numChildProcessors(); ++i) {
335                 this->childProcessor(i).computeInvariantOutput(inout);
336             }
337         }
338     };
339 
340     if (!cnt) {
341         return nullptr;
342     }
343 
344     // Run the through the series, do the invariant output processing, and look for eliminations.
345     SkTDArray<const GrFragmentProcessor*> replacementSeries;
346     SkAutoTUnref<const GrFragmentProcessor> colorFP;
347     GrProcOptInfo info;
348 
349     info.calcWithInitialValues(series, cnt, 0x0, kNone_GrColorComponentFlags, false, false);
350     if (kRGBA_GrColorComponentFlags == info.validFlags()) {
351         return GrConstColorProcessor::Create(info.color(),
352                                              GrConstColorProcessor::kIgnore_InputMode);
353     } else {
354         int firstIdx = info.firstEffectiveProcessorIndex();
355         cnt -= firstIdx;
356         if (firstIdx > 0 && info.inputColorIsUsed()) {
357             colorFP.reset(GrConstColorProcessor::Create(info.inputColorToFirstEffectiveProccesor(),
358                                                         GrConstColorProcessor::kIgnore_InputMode));
359             cnt += 1;
360             replacementSeries.setCount(cnt);
361             replacementSeries[0] = colorFP;
362             for (int i = 0; i < cnt - 1; ++i) {
363                 replacementSeries[i + 1] = series[firstIdx + i];
364             }
365             series = replacementSeries.begin();
366         } else {
367             series += firstIdx;
368             cnt -= firstIdx;
369         }
370     }
371 
372     if (1 == cnt) {
373         return SkRef(series[0]);
374     } else {
375         return new SeriesFragmentProcessor(series, cnt);
376     }
377 }
378 
379