• 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 "GrProcessorAnalysis.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 
instantiate(GrResourceProvider * resourceProvider) const64 bool GrFragmentProcessor::instantiate(GrResourceProvider* resourceProvider) const {
65     if (!INHERITED::instantiate(resourceProvider)) {
66         return false;
67     }
68 
69     for (int i = 0; i < this->numChildProcessors(); ++i) {
70         if (!this->childProcessor(i).instantiate(resourceProvider)) {
71             return false;
72         }
73     }
74 
75     return true;
76 }
77 
registerChildProcessor(sk_sp<GrFragmentProcessor> child)78 int GrFragmentProcessor::registerChildProcessor(sk_sp<GrFragmentProcessor> child) {
79     this->combineRequiredFeatures(*child);
80 
81     if (child->usesLocalCoords()) {
82         fFlags |= kUsesLocalCoords_Flag;
83     }
84 
85     int index = fChildProcessors.count();
86     fChildProcessors.push_back(child.release());
87 
88     return index;
89 }
90 
notifyRefCntIsZero() const91 void GrFragmentProcessor::notifyRefCntIsZero() const {
92     // See comment above GrProgramElement for a detailed explanation of why we do this.
93     for (int i = 0; i < fChildProcessors.count(); ++i) {
94         fChildProcessors[i]->addPendingExecution();
95         fChildProcessors[i]->unref();
96     }
97 }
98 
hasSameTransforms(const GrFragmentProcessor & that) const99 bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
100     if (this->numCoordTransforms() != that.numCoordTransforms()) {
101         return false;
102     }
103     int count = this->numCoordTransforms();
104     for (int i = 0; i < count; ++i) {
105         if (!this->coordTransform(i).hasSameEffectAs(that.coordTransform(i))) {
106             return false;
107         }
108     }
109     return true;
110 }
111 
MulOutputByInputAlpha(sk_sp<GrFragmentProcessor> fp)112 sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputAlpha(
113     sk_sp<GrFragmentProcessor> fp) {
114     if (!fp) {
115         return nullptr;
116     }
117     return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp), SkBlendMode::kDstIn);
118 }
119 
120 namespace {
121 
122 class PremulInputFragmentProcessor : public GrFragmentProcessor {
123 public:
Make()124     static sk_sp<GrFragmentProcessor> Make() {
125         return sk_sp<GrFragmentProcessor>(new PremulInputFragmentProcessor);
126     }
127 
name() const128     const char* name() const override { return "PremultiplyInput"; }
129 
130 private:
PremulInputFragmentProcessor()131     PremulInputFragmentProcessor()
132             : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
133                         kConstantOutputForConstantInput_OptimizationFlag) {
134         this->initClassID<PremulInputFragmentProcessor>();
135     }
136 
onCreateGLSLInstance() const137     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
138         class GLFP : public GrGLSLFragmentProcessor {
139         public:
140             void emitCode(EmitArgs& args) override {
141                 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
142 
143                 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
144                 fragBuilder->codeAppendf("%s.rgb *= %s.a;",
145                                             args.fOutputColor, args.fInputColor);
146             }
147         };
148         return new GLFP;
149     }
150 
onGetGLSLProcessorKey(const GrShaderCaps &,GrProcessorKeyBuilder *) const151     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
152 
onIsEqual(const GrFragmentProcessor &) const153     bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
154 
constantOutputForConstantInput(GrColor4f input) const155     GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
156         return input.premul();
157     }
158 
159     typedef GrFragmentProcessor INHERITED;
160 };
161 
162 class UnpremulInputFragmentProcessor : public GrFragmentProcessor {
163 public:
Make()164     static sk_sp<GrFragmentProcessor> Make() {
165         return sk_sp<GrFragmentProcessor>(new UnpremulInputFragmentProcessor);
166     }
167 
name() const168     const char* name() const override { return "UnpremultiplyInput"; }
169 
170 private:
UnpremulInputFragmentProcessor()171     UnpremulInputFragmentProcessor()
172             : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
173                         kConstantOutputForConstantInput_OptimizationFlag) {
174         this->initClassID<UnpremulInputFragmentProcessor>();
175     }
176 
onCreateGLSLInstance() const177     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
178         class GLFP : public GrGLSLFragmentProcessor {
179         public:
180             void emitCode(EmitArgs& args) override {
181                 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
182 
183                 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
184                 fragBuilder->codeAppendf("float invAlpha = %s.a <= 0.0 ? 0.0 : 1.0 / %s.a;",
185                                          args.fInputColor, args.fInputColor);
186                 fragBuilder->codeAppendf("%s.rgb *= invAlpha;", args.fOutputColor);
187             }
188         };
189         return new GLFP;
190     }
191 
onGetGLSLProcessorKey(const GrShaderCaps &,GrProcessorKeyBuilder *) const192     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
193 
onIsEqual(const GrFragmentProcessor &) const194     bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
195 
constantOutputForConstantInput(GrColor4f input) const196     GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
197         return input.unpremul();
198     }
199 
200     typedef GrFragmentProcessor INHERITED;
201 };
202 
203 }
204 
PremulInput(sk_sp<GrFragmentProcessor> fp)205 sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulInput(sk_sp<GrFragmentProcessor> fp) {
206     if (!fp) {
207         return nullptr;
208     }
209     sk_sp<GrFragmentProcessor> fpPipeline[] = { PremulInputFragmentProcessor::Make(), fp};
210     return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
211 }
212 
PremulOutput(sk_sp<GrFragmentProcessor> fp)213 sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulOutput(sk_sp<GrFragmentProcessor> fp) {
214     if (!fp) {
215         return nullptr;
216     }
217     sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, PremulInputFragmentProcessor::Make() };
218     return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
219 }
220 
UnpremulOutput(sk_sp<GrFragmentProcessor> fp)221 sk_sp<GrFragmentProcessor> GrFragmentProcessor::UnpremulOutput(sk_sp<GrFragmentProcessor> fp) {
222     if (!fp) {
223         return nullptr;
224     }
225     sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, UnpremulInputFragmentProcessor::Make() };
226     return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
227 }
228 
SwizzleOutput(sk_sp<GrFragmentProcessor> fp,const GrSwizzle & swizzle)229 sk_sp<GrFragmentProcessor> GrFragmentProcessor::SwizzleOutput(sk_sp<GrFragmentProcessor> fp,
230                                                               const GrSwizzle& swizzle) {
231     class SwizzleFragmentProcessor : public GrFragmentProcessor {
232     public:
233         static sk_sp<GrFragmentProcessor> Make(const GrSwizzle& swizzle) {
234             return sk_sp<GrFragmentProcessor>(new SwizzleFragmentProcessor(swizzle));
235         }
236 
237         const char* name() const override { return "Swizzle"; }
238         const GrSwizzle& swizzle() const { return fSwizzle; }
239 
240     private:
241         SwizzleFragmentProcessor(const GrSwizzle& swizzle)
242                 : INHERITED(kAll_OptimizationFlags)
243                 , fSwizzle(swizzle) {
244             this->initClassID<SwizzleFragmentProcessor>();
245         }
246 
247         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
248             class GLFP : public GrGLSLFragmentProcessor {
249             public:
250                 void emitCode(EmitArgs& args) override {
251                     const SwizzleFragmentProcessor& sfp = args.fFp.cast<SwizzleFragmentProcessor>();
252                     const GrSwizzle& swizzle = sfp.swizzle();
253                     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
254 
255                     fragBuilder->codeAppendf("%s = %s.%s;",
256                                              args.fOutputColor, args.fInputColor, swizzle.c_str());
257                 }
258             };
259             return new GLFP;
260         }
261 
262         void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
263             b->add32(fSwizzle.asKey());
264         }
265 
266         bool onIsEqual(const GrFragmentProcessor& other) const override {
267             const SwizzleFragmentProcessor& sfp = other.cast<SwizzleFragmentProcessor>();
268             return fSwizzle == sfp.fSwizzle;
269         }
270 
271         GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
272             return fSwizzle.applyTo(input);
273         }
274 
275         GrSwizzle fSwizzle;
276 
277         typedef GrFragmentProcessor INHERITED;
278     };
279 
280     if (!fp) {
281         return nullptr;
282     }
283     if (GrSwizzle::RGBA() == swizzle) {
284         return fp;
285     }
286     sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, SwizzleFragmentProcessor::Make(swizzle) };
287     return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
288 }
289 
MakeInputPremulAndMulByOutput(sk_sp<GrFragmentProcessor> fp)290 sk_sp<GrFragmentProcessor> GrFragmentProcessor::MakeInputPremulAndMulByOutput(
291         sk_sp<GrFragmentProcessor> fp) {
292 
293     class PremulFragmentProcessor : public GrFragmentProcessor {
294     public:
295         static sk_sp<GrFragmentProcessor> Make(sk_sp<GrFragmentProcessor> processor) {
296             return sk_sp<GrFragmentProcessor>(new PremulFragmentProcessor(std::move(processor)));
297         }
298 
299         const char* name() const override { return "Premultiply"; }
300 
301     private:
302         PremulFragmentProcessor(sk_sp<GrFragmentProcessor> processor)
303                 : INHERITED(OptFlags(processor.get())) {
304             this->initClassID<PremulFragmentProcessor>();
305             this->registerChildProcessor(processor);
306         }
307 
308         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
309             class GLFP : public GrGLSLFragmentProcessor {
310             public:
311                 void emitCode(EmitArgs& args) override {
312                     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
313                     this->emitChild(0, args);
314                     fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
315                                                                 args.fInputColor);
316                     fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
317                 }
318             };
319             return new GLFP;
320         }
321 
322         void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
323 
324         bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
325 
326         static OptimizationFlags OptFlags(const GrFragmentProcessor* inner) {
327             OptimizationFlags flags = kNone_OptimizationFlags;
328             if (inner->preservesOpaqueInput()) {
329                 flags |= kPreservesOpaqueInput_OptimizationFlag;
330             }
331             if (inner->hasConstantOutputForConstantInput()) {
332                 flags |= kConstantOutputForConstantInput_OptimizationFlag;
333             }
334             return flags;
335         }
336 
337         GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
338             GrColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0),
339                                                                   GrColor4f::OpaqueWhite());
340             return GrColor4f(input.fRGBA[3] * input.fRGBA[0] * childColor.fRGBA[0],
341                              input.fRGBA[3] * input.fRGBA[1] * childColor.fRGBA[1],
342                              input.fRGBA[3] * input.fRGBA[2] * childColor.fRGBA[2],
343                              input.fRGBA[3] * childColor.fRGBA[3]);
344         }
345 
346         typedef GrFragmentProcessor INHERITED;
347     };
348     if (!fp) {
349         return nullptr;
350     }
351     return PremulFragmentProcessor::Make(std::move(fp));
352 }
353 
354 //////////////////////////////////////////////////////////////////////////////
355 
OverrideInput(sk_sp<GrFragmentProcessor> fp,GrColor4f color)356 sk_sp<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(sk_sp<GrFragmentProcessor> fp,
357                                                               GrColor4f color) {
358     class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
359     public:
360         static sk_sp<GrFragmentProcessor> Make(sk_sp<GrFragmentProcessor> child, GrColor4f color) {
361             return sk_sp<GrFragmentProcessor>(new ReplaceInputFragmentProcessor(std::move(child),
362                                                                                 color));
363         }
364 
365         const char* name() const override { return "Replace Color"; }
366 
367         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
368             class GLFP : public GrGLSLFragmentProcessor {
369             public:
370                 GLFP() : fHaveSetColor(false) {}
371                 void emitCode(EmitArgs& args) override {
372                     const char* colorName;
373                     fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
374                                                                  kVec4f_GrSLType,
375                                                                  kDefault_GrSLPrecision,
376                                                                  "Color", &colorName);
377                     this->emitChild(0, colorName, args);
378                 }
379 
380             private:
381                 void onSetData(const GrGLSLProgramDataManager& pdman,
382                                const GrFragmentProcessor& fp) override {
383                     GrColor4f color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
384                     if (!fHaveSetColor || color != fPreviousColor) {
385                         pdman.set4fv(fColorUni, 1, color.fRGBA);
386                         fPreviousColor = color;
387                         fHaveSetColor = true;
388                     }
389                 }
390 
391                 GrGLSLProgramDataManager::UniformHandle fColorUni;
392                 bool      fHaveSetColor;
393                 GrColor4f fPreviousColor;
394             };
395 
396             return new GLFP;
397         }
398 
399     private:
400         ReplaceInputFragmentProcessor(sk_sp<GrFragmentProcessor> child, GrColor4f color)
401                 : INHERITED(OptFlags(child.get(), color)), fColor(color) {
402             this->initClassID<ReplaceInputFragmentProcessor>();
403             this->registerChildProcessor(std::move(child));
404         }
405 
406         static OptimizationFlags OptFlags(const GrFragmentProcessor* child, GrColor4f color) {
407             OptimizationFlags childFlags = child->optimizationFlags();
408             OptimizationFlags flags = kNone_OptimizationFlags;
409             if (childFlags & kConstantOutputForConstantInput_OptimizationFlag) {
410                 flags |= kConstantOutputForConstantInput_OptimizationFlag;
411             }
412             if ((childFlags & kPreservesOpaqueInput_OptimizationFlag) && color.isOpaque()) {
413                 flags |= kPreservesOpaqueInput_OptimizationFlag;
414             }
415             return flags;
416         }
417 
418         void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override
419         {}
420 
421         bool onIsEqual(const GrFragmentProcessor& that) const override {
422             return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
423         }
424 
425         GrColor4f constantOutputForConstantInput(GrColor4f) const override {
426             return ConstantOutputForConstantInput(this->childProcessor(0), fColor);
427         }
428 
429         GrColor4f fColor;
430 
431         typedef GrFragmentProcessor INHERITED;
432     };
433 
434     if (!fp) {
435         return nullptr;
436     }
437     return ReplaceInputFragmentProcessor::Make(std::move(fp), color);
438 }
439 
RunInSeries(sk_sp<GrFragmentProcessor> * series,int cnt)440 sk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProcessor>* series,
441                                                             int cnt) {
442     class SeriesFragmentProcessor : public GrFragmentProcessor {
443     public:
444         static sk_sp<GrFragmentProcessor> Make(sk_sp<GrFragmentProcessor>* children, int cnt) {
445             return sk_sp<GrFragmentProcessor>(new SeriesFragmentProcessor(children, cnt));
446         }
447 
448         const char* name() const override { return "Series"; }
449 
450         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
451             class GLFP : public GrGLSLFragmentProcessor {
452             public:
453                 void emitCode(EmitArgs& args) override {
454                     // First guy's input might be nil.
455                     SkString temp("out0");
456                     this->emitChild(0, args.fInputColor, &temp, args);
457                     SkString input = temp;
458                     for (int i = 1; i < this->numChildProcessors() - 1; ++i) {
459                         temp.printf("out%d", i);
460                         this->emitChild(i, input.c_str(), &temp, args);
461                         input = temp;
462                     }
463                     // Last guy writes to our output variable.
464                     this->emitChild(this->numChildProcessors() - 1, input.c_str(), args);
465                 }
466             };
467             return new GLFP;
468         }
469     private:
470         SeriesFragmentProcessor(sk_sp<GrFragmentProcessor>* children, int cnt)
471                 : INHERITED(OptFlags(children, cnt)) {
472             SkASSERT(cnt > 1);
473             this->initClassID<SeriesFragmentProcessor>();
474             for (int i = 0; i < cnt; ++i) {
475                 this->registerChildProcessor(std::move(children[i]));
476             }
477         }
478 
479         static OptimizationFlags OptFlags(sk_sp<GrFragmentProcessor>* children, int cnt) {
480             OptimizationFlags flags = kAll_OptimizationFlags;
481             for (int i = 0; i < cnt && flags != kNone_OptimizationFlags; ++i) {
482                 flags &= children[i]->optimizationFlags();
483             }
484             return flags;
485         }
486         void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
487 
488         bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
489 
490         GrColor4f constantOutputForConstantInput(GrColor4f color) const override {
491             int childCnt = this->numChildProcessors();
492             for (int i = 0; i < childCnt; ++i) {
493                 color = ConstantOutputForConstantInput(this->childProcessor(i), color);
494             }
495             return color;
496         }
497 
498         typedef GrFragmentProcessor INHERITED;
499     };
500 
501     if (!cnt) {
502         return nullptr;
503     }
504     if (1 == cnt) {
505         return series[0];
506     }
507     // Run the through the series, do the invariant output processing, and look for eliminations.
508     GrColorFragmentProcessorAnalysis info;
509     info.analyzeProcessors(sk_sp_address_as_pointer_address(series), cnt);
510     SkTArray<sk_sp<GrFragmentProcessor>> replacementSeries;
511     GrColor4f knownColor;
512     int leadingFPsToEliminate = info.initialProcessorsToEliminate(&knownColor);
513     if (leadingFPsToEliminate) {
514         sk_sp<GrFragmentProcessor> colorFP(
515                 GrConstColorProcessor::Make(knownColor, GrConstColorProcessor::kIgnore_InputMode));
516         if (leadingFPsToEliminate == cnt) {
517             return colorFP;
518         }
519         cnt = cnt - leadingFPsToEliminate + 1;
520         replacementSeries.reserve(cnt);
521         replacementSeries.emplace_back(std::move(colorFP));
522         for (int i = 0; i < cnt - 1; ++i) {
523             replacementSeries.emplace_back(std::move(series[leadingFPsToEliminate + i]));
524         }
525         series = replacementSeries.begin();
526     }
527     return SeriesFragmentProcessor::Make(series, cnt);
528 }
529 
530 //////////////////////////////////////////////////////////////////////////////
531 
Iter(const GrPipeline & pipeline)532 GrFragmentProcessor::Iter::Iter(const GrPipeline& pipeline) {
533     for (int i = pipeline.numFragmentProcessors() - 1; i >= 0; --i) {
534         fFPStack.push_back(&pipeline.getFragmentProcessor(i));
535     }
536 }
537 
next()538 const GrFragmentProcessor* GrFragmentProcessor::Iter::next() {
539     if (fFPStack.empty()) {
540         return nullptr;
541     }
542     const GrFragmentProcessor* back = fFPStack.back();
543     fFPStack.pop_back();
544     for (int i = back->numChildProcessors() - 1; i >= 0; --i) {
545         fFPStack.push_back(&back->childProcessor(i));
546     }
547     return back;
548 }
549 
550