• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "GrPipeline.h"
11 #include "GrPipelineAnalysis.h"
12 #include "effects/GrConstColorProcessor.h"
13 #include "effects/GrXfermodeFragmentProcessor.h"
14 #include "glsl/GrGLSLFragmentProcessor.h"
15 #include "glsl/GrGLSLFragmentShaderBuilder.h"
16 #include "glsl/GrGLSLProgramDataManager.h"
17 #include "glsl/GrGLSLUniformHandler.h"
18 
~GrFragmentProcessor()19 GrFragmentProcessor::~GrFragmentProcessor() {
20     // If we got here then our ref count must have reached zero, so we will have converted refs
21     // to pending executions for all children.
22     for (int i = 0; i < fChildProcessors.count(); ++i) {
23         fChildProcessors[i]->completedExecution();
24     }
25 }
26 
isEqual(const GrFragmentProcessor & that) const27 bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that) const {
28     if (this->classID() != that.classID() ||
29         !this->hasSameSamplersAndAccesses(that)) {
30         return false;
31     }
32     if (!this->hasSameTransforms(that)) {
33         return false;
34     }
35     if (!this->onIsEqual(that)) {
36         return false;
37     }
38     if (this->numChildProcessors() != that.numChildProcessors()) {
39         return false;
40     }
41     for (int i = 0; i < this->numChildProcessors(); ++i) {
42         if (!this->childProcessor(i).isEqual(that.childProcessor(i))) {
43             return false;
44         }
45     }
46     return true;
47 }
48 
createGLSLInstance() const49 GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const {
50     GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance();
51     glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
52     for (int i = 0; i < fChildProcessors.count(); ++i) {
53         glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLSLInstance();
54     }
55     return glFragProc;
56 }
57 
addCoordTransform(const GrCoordTransform * transform)58 void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
59     fCoordTransforms.push_back(transform);
60     fFlags |= kUsesLocalCoords_Flag;
61     SkDEBUGCODE(transform->setInProcessor();)
62 }
63 
registerChildProcessor(sk_sp<GrFragmentProcessor> child)64 int GrFragmentProcessor::registerChildProcessor(sk_sp<GrFragmentProcessor> child) {
65     this->combineRequiredFeatures(*child);
66 
67     if (child->usesLocalCoords()) {
68         fFlags |= kUsesLocalCoords_Flag;
69     }
70     if (child->usesDistanceVectorField()) {
71         fFlags |= kUsesDistanceVectorField_Flag;
72     }
73 
74     int index = fChildProcessors.count();
75     fChildProcessors.push_back(child.release());
76 
77     return index;
78 }
79 
notifyRefCntIsZero() const80 void GrFragmentProcessor::notifyRefCntIsZero() const {
81     // See comment above GrProgramElement for a detailed explanation of why we do this.
82     for (int i = 0; i < fChildProcessors.count(); ++i) {
83         fChildProcessors[i]->addPendingExecution();
84         fChildProcessors[i]->unref();
85     }
86 }
87 
hasSameTransforms(const GrFragmentProcessor & that) const88 bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
89     if (this->numCoordTransforms() != that.numCoordTransforms()) {
90         return false;
91     }
92     int count = this->numCoordTransforms();
93     for (int i = 0; i < count; ++i) {
94         if (!this->coordTransform(i).hasSameEffectAs(that.coordTransform(i))) {
95             return false;
96         }
97     }
98     return true;
99 }
100 
MulOutputByInputAlpha(sk_sp<GrFragmentProcessor> fp)101 sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputAlpha(
102     sk_sp<GrFragmentProcessor> fp) {
103     if (!fp) {
104         return nullptr;
105     }
106     return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp), SkBlendMode::kDstIn);
107 }
108 
109 namespace {
110 
111 class PremulInputFragmentProcessor : public GrFragmentProcessor {
112 public:
PremulInputFragmentProcessor()113     PremulInputFragmentProcessor()
114             : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
115                         kConstantOutputForConstantInput_OptimizationFlag) {
116         this->initClassID<PremulInputFragmentProcessor>();
117     }
118 
name() const119     const char* name() const override { return "PremultiplyInput"; }
120 
121 private:
onCreateGLSLInstance() const122     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
123         class GLFP : public GrGLSLFragmentProcessor {
124         public:
125             void emitCode(EmitArgs& args) override {
126                 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
127 
128                 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
129                 fragBuilder->codeAppendf("%s.rgb *= %s.a;",
130                                             args.fOutputColor, args.fInputColor);
131             }
132         };
133         return new GLFP;
134     }
135 
onGetGLSLProcessorKey(const GrShaderCaps &,GrProcessorKeyBuilder *) const136     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
137 
onIsEqual(const GrFragmentProcessor &) const138     bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
139 
constantOutputForConstantInput(GrColor4f input) const140     GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
141         return input.premul();
142     }
143 
144     typedef GrFragmentProcessor INHERITED;
145 };
146 
147 class UnpremulInputFragmentProcessor : public GrFragmentProcessor {
148 public:
UnpremulInputFragmentProcessor()149     UnpremulInputFragmentProcessor()
150             : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
151                         kConstantOutputForConstantInput_OptimizationFlag) {
152         this->initClassID<UnpremulInputFragmentProcessor>();
153     }
154 
name() const155     const char* name() const override { return "UnpremultiplyInput"; }
156 
157 private:
onCreateGLSLInstance() const158     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
159         class GLFP : public GrGLSLFragmentProcessor {
160         public:
161             void emitCode(EmitArgs& args) override {
162                 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
163 
164                 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
165                 fragBuilder->codeAppendf("float invAlpha = %s.a <= 0.0 ? 0.0 : 1.0 / %s.a;",
166                                          args.fInputColor, args.fInputColor);
167                 fragBuilder->codeAppendf("%s.rgb *= invAlpha;", args.fOutputColor);
168             }
169         };
170         return new GLFP;
171     }
172 
onGetGLSLProcessorKey(const GrShaderCaps &,GrProcessorKeyBuilder *) const173     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
174 
onIsEqual(const GrFragmentProcessor &) const175     bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
176 
constantOutputForConstantInput(GrColor4f input) const177     GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
178         return input.unpremul();
179     }
180 
181     typedef GrFragmentProcessor INHERITED;
182 };
183 
184 }
185 
PremulInput(sk_sp<GrFragmentProcessor> fp)186 sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulInput(sk_sp<GrFragmentProcessor> fp) {
187     if (!fp) {
188         return nullptr;
189     }
190     sk_sp<GrFragmentProcessor> fpPipeline[] = { sk_make_sp<PremulInputFragmentProcessor>(), fp};
191     return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
192 }
193 
PremulOutput(sk_sp<GrFragmentProcessor> fp)194 sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulOutput(sk_sp<GrFragmentProcessor> fp) {
195     if (!fp) {
196         return nullptr;
197     }
198     sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, sk_make_sp<PremulInputFragmentProcessor>() };
199     return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
200 }
201 
UnpremulOutput(sk_sp<GrFragmentProcessor> fp)202 sk_sp<GrFragmentProcessor> GrFragmentProcessor::UnpremulOutput(sk_sp<GrFragmentProcessor> fp) {
203     if (!fp) {
204         return nullptr;
205     }
206     sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, sk_make_sp<UnpremulInputFragmentProcessor>() };
207     return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
208 }
209 
SwizzleOutput(sk_sp<GrFragmentProcessor> fp,const GrSwizzle & swizzle)210 sk_sp<GrFragmentProcessor> GrFragmentProcessor::SwizzleOutput(sk_sp<GrFragmentProcessor> fp,
211                                                               const GrSwizzle& swizzle) {
212     class SwizzleFragmentProcessor : public GrFragmentProcessor {
213     public:
214         SwizzleFragmentProcessor(const GrSwizzle& swizzle)
215                 : INHERITED(kAll_OptimizationFlags)
216                 , fSwizzle(swizzle) {
217             this->initClassID<SwizzleFragmentProcessor>();
218         }
219 
220         const char* name() const override { return "Swizzle"; }
221         const GrSwizzle& swizzle() const { return fSwizzle; }
222 
223     private:
224         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
225             class GLFP : public GrGLSLFragmentProcessor {
226             public:
227                 void emitCode(EmitArgs& args) override {
228                     const SwizzleFragmentProcessor& sfp = args.fFp.cast<SwizzleFragmentProcessor>();
229                     const GrSwizzle& swizzle = sfp.swizzle();
230                     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
231 
232                     fragBuilder->codeAppendf("%s = %s.%s;",
233                                              args.fOutputColor, args.fInputColor, swizzle.c_str());
234                 }
235             };
236             return new GLFP;
237         }
238 
239         void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
240             b->add32(fSwizzle.asKey());
241         }
242 
243         bool onIsEqual(const GrFragmentProcessor& other) const override {
244             const SwizzleFragmentProcessor& sfp = other.cast<SwizzleFragmentProcessor>();
245             return fSwizzle == sfp.fSwizzle;
246         }
247 
248         GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
249             return fSwizzle.applyTo(input);
250         }
251 
252         GrSwizzle fSwizzle;
253 
254         typedef GrFragmentProcessor INHERITED;
255     };
256 
257     if (!fp) {
258         return nullptr;
259     }
260     if (GrSwizzle::RGBA() == swizzle) {
261         return fp;
262     }
263     sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, sk_make_sp<SwizzleFragmentProcessor>(swizzle) };
264     return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
265 }
266 
MakeInputPremulAndMulByOutput(sk_sp<GrFragmentProcessor> fp)267 sk_sp<GrFragmentProcessor> GrFragmentProcessor::MakeInputPremulAndMulByOutput(
268         sk_sp<GrFragmentProcessor> fp) {
269 
270     class PremulFragmentProcessor : public GrFragmentProcessor {
271     public:
272         PremulFragmentProcessor(sk_sp<GrFragmentProcessor> processor)
273                 : INHERITED(OptFlags(processor.get())) {
274             this->initClassID<PremulFragmentProcessor>();
275             this->registerChildProcessor(processor);
276         }
277 
278         const char* name() const override { return "Premultiply"; }
279 
280     private:
281         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
282             class GLFP : public GrGLSLFragmentProcessor {
283             public:
284                 void emitCode(EmitArgs& args) override {
285                     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
286                     this->emitChild(0, nullptr, args);
287                     fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
288                                                                 args.fInputColor);
289                     fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
290                 }
291             };
292             return new GLFP;
293         }
294 
295         void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
296 
297         bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
298 
299         static OptimizationFlags OptFlags(const GrFragmentProcessor* inner) {
300             OptimizationFlags flags = kNone_OptimizationFlags;
301             if (inner->preservesOpaqueInput()) {
302                 flags |= kPreservesOpaqueInput_OptimizationFlag;
303             }
304             if (inner->hasConstantOutputForConstantInput()) {
305                 flags |= kConstantOutputForConstantInput_OptimizationFlag;
306             }
307             return flags;
308         }
309 
310         GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
311             GrColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0),
312                                                                   GrColor4f::OpaqueWhite());
313             return GrColor4f(input.fRGBA[3] * input.fRGBA[0] * childColor.fRGBA[0],
314                              input.fRGBA[3] * input.fRGBA[1] * childColor.fRGBA[1],
315                              input.fRGBA[3] * input.fRGBA[2] * childColor.fRGBA[2],
316                              input.fRGBA[3] * childColor.fRGBA[3]);
317         }
318 
319         typedef GrFragmentProcessor INHERITED;
320     };
321     if (!fp) {
322         return nullptr;
323     }
324     return sk_sp<GrFragmentProcessor>(new PremulFragmentProcessor(std::move(fp)));
325 }
326 
327 //////////////////////////////////////////////////////////////////////////////
328 
OverrideInput(sk_sp<GrFragmentProcessor> fp,GrColor4f color)329 sk_sp<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(sk_sp<GrFragmentProcessor> fp,
330                                                               GrColor4f color) {
331     class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
332     public:
333         ReplaceInputFragmentProcessor(sk_sp<GrFragmentProcessor> child, GrColor4f color)
334                 : INHERITED(OptFlags(child.get(), color)), fColor(color) {
335             this->initClassID<ReplaceInputFragmentProcessor>();
336             this->registerChildProcessor(std::move(child));
337         }
338 
339         const char* name() const override { return "Replace Color"; }
340 
341         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
342             class GLFP : public GrGLSLFragmentProcessor {
343             public:
344                 GLFP() : fHaveSetColor(false) {}
345                 void emitCode(EmitArgs& args) override {
346                     const char* colorName;
347                     fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
348                                                                  kVec4f_GrSLType,
349                                                                  kDefault_GrSLPrecision,
350                                                                  "Color", &colorName);
351                     this->emitChild(0, colorName, args);
352                 }
353 
354             private:
355                 void onSetData(const GrGLSLProgramDataManager& pdman,
356                                const GrProcessor& fp) override {
357                     GrColor4f color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
358                     if (!fHaveSetColor || color != fPreviousColor) {
359                         pdman.set4fv(fColorUni, 1, color.fRGBA);
360                         fPreviousColor = color;
361                         fHaveSetColor = true;
362                     }
363                 }
364 
365                 GrGLSLProgramDataManager::UniformHandle fColorUni;
366                 bool      fHaveSetColor;
367                 GrColor4f fPreviousColor;
368             };
369 
370             return new GLFP;
371         }
372 
373     private:
374         static OptimizationFlags OptFlags(const GrFragmentProcessor* child, GrColor4f color) {
375             OptimizationFlags childFlags = child->optimizationFlags();
376             OptimizationFlags flags = kNone_OptimizationFlags;
377             if (childFlags & kConstantOutputForConstantInput_OptimizationFlag) {
378                 flags |= kConstantOutputForConstantInput_OptimizationFlag;
379             }
380             if ((childFlags & kPreservesOpaqueInput_OptimizationFlag) && color.isOpaque()) {
381                 flags |= kPreservesOpaqueInput_OptimizationFlag;
382             }
383             return flags;
384         }
385 
386         void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override
387         {}
388 
389         bool onIsEqual(const GrFragmentProcessor& that) const override {
390             return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
391         }
392 
393         GrColor4f constantOutputForConstantInput(GrColor4f) const override {
394             return ConstantOutputForConstantInput(this->childProcessor(0), fColor);
395         }
396 
397         GrColor4f fColor;
398 
399         typedef GrFragmentProcessor INHERITED;
400     };
401 
402     return sk_sp<GrFragmentProcessor>(new ReplaceInputFragmentProcessor(std::move(fp), color));
403 }
404 
RunInSeries(sk_sp<GrFragmentProcessor> * series,int cnt)405 sk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProcessor>* series,
406                                                             int cnt) {
407     class SeriesFragmentProcessor : public GrFragmentProcessor {
408     public:
409         SeriesFragmentProcessor(sk_sp<GrFragmentProcessor>* children, int cnt)
410                 : INHERITED(OptFlags(children, cnt)) {
411             SkASSERT(cnt > 1);
412             this->initClassID<SeriesFragmentProcessor>();
413             for (int i = 0; i < cnt; ++i) {
414                 this->registerChildProcessor(std::move(children[i]));
415             }
416         }
417 
418         const char* name() const override { return "Series"; }
419 
420         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
421             class GLFP : public GrGLSLFragmentProcessor {
422             public:
423                 void emitCode(EmitArgs& args) override {
424                     // First guy's input might be nil.
425                     SkString temp("out0");
426                     this->emitChild(0, args.fInputColor, &temp, args);
427                     SkString input = temp;
428                     for (int i = 1; i < this->numChildProcessors() - 1; ++i) {
429                         temp.printf("out%d", i);
430                         this->emitChild(i, input.c_str(), &temp, args);
431                         input = temp;
432                     }
433                     // Last guy writes to our output variable.
434                     this->emitChild(this->numChildProcessors() - 1, input.c_str(), args);
435                 }
436             };
437             return new GLFP;
438         }
439     private:
440         static OptimizationFlags OptFlags(sk_sp<GrFragmentProcessor>* children, int cnt) {
441             OptimizationFlags flags = kAll_OptimizationFlags;
442             for (int i = 0; i < cnt && flags != kNone_OptimizationFlags; ++i) {
443                 flags &= children[i]->optimizationFlags();
444             }
445             return flags;
446         }
447         void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
448 
449         bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
450 
451         GrColor4f constantOutputForConstantInput(GrColor4f color) const override {
452             int childCnt = this->numChildProcessors();
453             for (int i = 0; i < childCnt; ++i) {
454                 color = ConstantOutputForConstantInput(this->childProcessor(i), color);
455             }
456             return color;
457         }
458 
459         typedef GrFragmentProcessor INHERITED;
460     };
461 
462     if (!cnt) {
463         return nullptr;
464     }
465     if (1 == cnt) {
466         return series[0];
467     }
468     // Run the through the series, do the invariant output processing, and look for eliminations.
469     GrColorFragmentProcessorAnalysis info;
470     info.analyzeProcessors(sk_sp_address_as_pointer_address(series), cnt);
471     SkTArray<sk_sp<GrFragmentProcessor>> replacementSeries;
472     GrColor4f knownColor;
473     int leadingFPsToEliminate = info.initialProcessorsToEliminate(&knownColor);
474     if (leadingFPsToEliminate) {
475         sk_sp<GrFragmentProcessor> colorFP(
476                 GrConstColorProcessor::Make(knownColor, GrConstColorProcessor::kIgnore_InputMode));
477         if (leadingFPsToEliminate == cnt) {
478             return colorFP;
479         }
480         cnt = cnt - leadingFPsToEliminate + 1;
481         replacementSeries.reserve(cnt);
482         replacementSeries.emplace_back(std::move(colorFP));
483         for (int i = 0; i < cnt - 1; ++i) {
484             replacementSeries.emplace_back(std::move(series[leadingFPsToEliminate + i]));
485         }
486         series = replacementSeries.begin();
487     }
488     return sk_sp<GrFragmentProcessor>(new SeriesFragmentProcessor(series, cnt));
489 }
490 
491 //////////////////////////////////////////////////////////////////////////////
492 
Iter(const GrPipeline & pipeline)493 GrFragmentProcessor::Iter::Iter(const GrPipeline& pipeline) {
494     for (int i = pipeline.numFragmentProcessors() - 1; i >= 0; --i) {
495         fFPStack.push_back(&pipeline.getFragmentProcessor(i));
496     }
497 }
498 
next()499 const GrFragmentProcessor* GrFragmentProcessor::Iter::next() {
500     if (fFPStack.empty()) {
501         return nullptr;
502     }
503     const GrFragmentProcessor* back = fFPStack.back();
504     fFPStack.pop_back();
505     for (int i = back->numChildProcessors() - 1; i >= 0; --i) {
506         fFPStack.push_back(&back->childProcessor(i));
507     }
508     return back;
509 }
510 
511