• 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 "src/gpu/GrFragmentProcessor.h"
9 #include "src/gpu/GrPipeline.h"
10 #include "src/gpu/GrProcessorAnalysis.h"
11 #include "src/gpu/effects/GrBlendFragmentProcessor.h"
12 #include "src/gpu/effects/GrSkSLFP.h"
13 #include "src/gpu/effects/generated/GrClampFragmentProcessor.h"
14 #include "src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h"
15 #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
16 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
17 #include "src/gpu/glsl/GrGLSLProgramDataManager.h"
18 #include "src/gpu/glsl/GrGLSLUniformHandler.h"
19 
isEqual(const GrFragmentProcessor & that) const20 bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that) const {
21     if (this->classID() != that.classID()) {
22         return false;
23     }
24     if (this->usesVaryingCoordsDirectly() != that.usesVaryingCoordsDirectly()) {
25         return false;
26     }
27     if (!this->onIsEqual(that)) {
28         return false;
29     }
30     if (this->numChildProcessors() != that.numChildProcessors()) {
31         return false;
32     }
33     for (int i = 0; i < this->numChildProcessors(); ++i) {
34         auto thisChild = this->childProcessor(i),
35              thatChild = that .childProcessor(i);
36         if (SkToBool(thisChild) != SkToBool(thatChild)) {
37             return false;
38         }
39         if (thisChild && !thisChild->isEqual(*thatChild)) {
40             return false;
41         }
42     }
43     return true;
44 }
45 
visitProxies(const GrOp::VisitProxyFunc & func) const46 void GrFragmentProcessor::visitProxies(const GrOp::VisitProxyFunc& func) const {
47     this->visitTextureEffects([&func](const GrTextureEffect& te) {
48         func(te.view().proxy(), te.samplerState().mipmapped());
49     });
50 }
51 
visitTextureEffects(const std::function<void (const GrTextureEffect &)> & func) const52 void GrFragmentProcessor::visitTextureEffects(
53         const std::function<void(const GrTextureEffect&)>& func) const {
54     if (auto* te = this->asTextureEffect()) {
55         func(*te);
56     }
57     for (auto& child : fChildProcessors) {
58         if (child) {
59             child->visitTextureEffects(func);
60         }
61     }
62 }
63 
asTextureEffect()64 GrTextureEffect* GrFragmentProcessor::asTextureEffect() {
65     if (this->classID() == kGrTextureEffect_ClassID) {
66         return static_cast<GrTextureEffect*>(this);
67     }
68     return nullptr;
69 }
70 
asTextureEffect() const71 const GrTextureEffect* GrFragmentProcessor::asTextureEffect() const {
72     if (this->classID() == kGrTextureEffect_ClassID) {
73         return static_cast<const GrTextureEffect*>(this);
74     }
75     return nullptr;
76 }
77 
78 #if GR_TEST_UTILS
recursive_dump_tree_info(const GrFragmentProcessor & fp,SkString indent,SkString * text)79 static void recursive_dump_tree_info(const GrFragmentProcessor& fp,
80                                      SkString indent,
81                                      SkString* text) {
82     for (int index = 0; index < fp.numChildProcessors(); ++index) {
83         text->appendf("\n%s(#%d) -> ", indent.c_str(), index);
84         if (const GrFragmentProcessor* childFP = fp.childProcessor(index)) {
85             text->append(childFP->dumpInfo());
86             indent.append("\t");
87             recursive_dump_tree_info(*childFP, indent, text);
88         } else {
89             text->append("null");
90         }
91     }
92 }
93 
dumpTreeInfo() const94 SkString GrFragmentProcessor::dumpTreeInfo() const {
95     SkString text = this->dumpInfo();
96     recursive_dump_tree_info(*this, SkString("\t"), &text);
97     text.append("\n");
98     return text;
99 }
100 #endif
101 
makeProgramImpl() const102 std::unique_ptr<GrGLSLFragmentProcessor> GrFragmentProcessor::makeProgramImpl() const {
103     std::unique_ptr<GrGLSLFragmentProcessor> glFragProc = this->onMakeProgramImpl();
104     glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
105     for (int i = 0; i < fChildProcessors.count(); ++i) {
106         glFragProc->fChildProcessors[i] = fChildProcessors[i]
107                                                   ? fChildProcessors[i]->makeProgramImpl()
108                                                   : nullptr;
109     }
110     return glFragProc;
111 }
112 
addAndPushFlagToChildren(PrivateFlags flag)113 void GrFragmentProcessor::addAndPushFlagToChildren(PrivateFlags flag) {
114     // This propagates down, so if we've already marked it, all our children should have it too
115     if (!(fFlags & flag)) {
116         fFlags |= flag;
117         for (auto& child : fChildProcessors) {
118             if (child) {
119                 child->addAndPushFlagToChildren(flag);
120             }
121         }
122     }
123 #ifdef SK_DEBUG
124     for (auto& child : fChildProcessors) {
125         SkASSERT(!child || (child->fFlags & flag));
126     }
127 #endif
128 }
129 
numNonNullChildProcessors() const130 int GrFragmentProcessor::numNonNullChildProcessors() const {
131     return std::count_if(fChildProcessors.begin(), fChildProcessors.end(),
132                          [](const auto& c) { return c != nullptr; });
133 }
134 
135 #ifdef SK_DEBUG
isInstantiated() const136 bool GrFragmentProcessor::isInstantiated() const {
137     bool result = true;
138     this->visitTextureEffects([&result](const GrTextureEffect& te) {
139         if (!te.texture()) {
140             result = false;
141         }
142     });
143     return result;
144 }
145 #endif
146 
registerChild(std::unique_ptr<GrFragmentProcessor> child,SkSL::SampleUsage sampleUsage)147 void GrFragmentProcessor::registerChild(std::unique_ptr<GrFragmentProcessor> child,
148                                         SkSL::SampleUsage sampleUsage) {
149     if (!child) {
150         fChildProcessors.push_back(nullptr);
151         return;
152     }
153 
154     // The child should not have been attached to another FP already and not had any sampling
155     // strategy set on it.
156     SkASSERT(!child->fParent && !child->sampleUsage().isSampled() &&
157              !child->isSampledWithExplicitCoords() && !child->hasPerspectiveTransform());
158 
159     // Configure child's sampling state first
160     child->fUsage = sampleUsage;
161 
162     if (sampleUsage.isExplicit()) {
163         child->addAndPushFlagToChildren(kSampledWithExplicitCoords_Flag);
164     }
165 
166     // Push perspective matrix type to children
167     if (sampleUsage.fHasPerspective) {
168         child->addAndPushFlagToChildren(kNetTransformHasPerspective_Flag);
169     }
170 
171     // If the child is not sampled explicitly and not already accessing sample coords directly
172     // (through reference or variable matrix expansion), then mark that this FP tree relies on
173     // coordinates at a lower level. If the child is sampled with explicit coordinates and
174     // there isn't any other direct reference to the sample coords, we halt the upwards propagation
175     // because it means this FP is determining coordinates on its own.
176     if (!child->isSampledWithExplicitCoords()) {
177         if ((child->fFlags & kUsesSampleCoordsDirectly_Flag ||
178              child->fFlags & kUsesSampleCoordsIndirectly_Flag)) {
179             fFlags |= kUsesSampleCoordsIndirectly_Flag;
180         }
181     }
182 
183     fRequestedFeatures |= child->fRequestedFeatures;
184 
185     // Record that the child is attached to us; this FP is the source of any uniform data needed
186     // to evaluate the child sample matrix.
187     child->fParent = this;
188     fChildProcessors.push_back(std::move(child));
189 
190     // Validate: our sample strategy comes from a parent we shouldn't have yet.
191     SkASSERT(!this->isSampledWithExplicitCoords() && !this->hasPerspectiveTransform() &&
192              !fUsage.isSampled() && !fParent);
193 }
194 
cloneAndRegisterAllChildProcessors(const GrFragmentProcessor & src)195 void GrFragmentProcessor::cloneAndRegisterAllChildProcessors(const GrFragmentProcessor& src) {
196     for (int i = 0; i < src.numChildProcessors(); ++i) {
197         if (auto fp = src.childProcessor(i)) {
198             this->registerChild(fp->clone(), fp->sampleUsage());
199         } else {
200             this->registerChild(nullptr);
201         }
202     }
203 }
204 
MakeColor(SkPMColor4f color)205 std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MakeColor(SkPMColor4f color) {
206     // Use ColorFilter signature/factory to get the constant output for constant input optimization
207     static constexpr char kCode[] = R"(
208         uniform half4 color;
209         half4 main(half4 inColor) { return color; }
210     )";
211     auto builder = GrRuntimeFPBuilder::Make<kCode, SkRuntimeEffect::MakeForColorFilter>();
212     builder.uniform("color") = color;
213     return builder.makeFP();
214 }
215 
MulChildByInputAlpha(std::unique_ptr<GrFragmentProcessor> fp)216 std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MulChildByInputAlpha(
217         std::unique_ptr<GrFragmentProcessor> fp) {
218     if (!fp) {
219         return nullptr;
220     }
221     return GrBlendFragmentProcessor::Make(/*src=*/nullptr, std::move(fp), SkBlendMode::kDstIn);
222 }
223 
MulInputByChildAlpha(std::unique_ptr<GrFragmentProcessor> fp)224 std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MulInputByChildAlpha(
225         std::unique_ptr<GrFragmentProcessor> fp) {
226     if (!fp) {
227         return nullptr;
228     }
229     return GrBlendFragmentProcessor::Make(/*src=*/nullptr, std::move(fp), SkBlendMode::kSrcIn);
230 }
231 
ModulateAlpha(std::unique_ptr<GrFragmentProcessor> inputFP,const SkPMColor4f & color)232 std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::ModulateAlpha(
233         std::unique_ptr<GrFragmentProcessor> inputFP, const SkPMColor4f& color) {
234     auto colorFP = MakeColor(color);
235     return GrBlendFragmentProcessor::Make(
236             std::move(colorFP), std::move(inputFP), SkBlendMode::kSrcIn,
237             GrBlendFragmentProcessor::BlendBehavior::kSkModeBehavior);
238 }
239 
ModulateRGBA(std::unique_ptr<GrFragmentProcessor> inputFP,const SkPMColor4f & color)240 std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::ModulateRGBA(
241         std::unique_ptr<GrFragmentProcessor> inputFP, const SkPMColor4f& color) {
242     auto colorFP = MakeColor(color);
243     return GrBlendFragmentProcessor::Make(
244             std::move(colorFP), std::move(inputFP), SkBlendMode::kModulate,
245             GrBlendFragmentProcessor::BlendBehavior::kSkModeBehavior);
246 }
247 
ClampPremulOutput(std::unique_ptr<GrFragmentProcessor> fp)248 std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::ClampPremulOutput(
249         std::unique_ptr<GrFragmentProcessor> fp) {
250     if (!fp) {
251         return nullptr;
252     }
253     return GrClampFragmentProcessor::Make(std::move(fp), /*clampToPremul=*/true);
254 }
255 
SwizzleOutput(std::unique_ptr<GrFragmentProcessor> fp,const GrSwizzle & swizzle)256 std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::SwizzleOutput(
257         std::unique_ptr<GrFragmentProcessor> fp, const GrSwizzle& swizzle) {
258     class SwizzleFragmentProcessor : public GrFragmentProcessor {
259     public:
260         static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp,
261                                                          const GrSwizzle& swizzle) {
262             return std::unique_ptr<GrFragmentProcessor>(
263                     new SwizzleFragmentProcessor(std::move(fp), swizzle));
264         }
265 
266         const char* name() const override { return "Swizzle"; }
267         const GrSwizzle& swizzle() const { return fSwizzle; }
268 
269         std::unique_ptr<GrFragmentProcessor> clone() const override {
270             return Make(this->childProcessor(0)->clone(), fSwizzle);
271         }
272 
273     private:
274         SwizzleFragmentProcessor(std::unique_ptr<GrFragmentProcessor> fp, const GrSwizzle& swizzle)
275                 : INHERITED(kSwizzleFragmentProcessor_ClassID, ProcessorOptimizationFlags(fp.get()))
276                 , fSwizzle(swizzle) {
277             this->registerChild(std::move(fp));
278         }
279 
280         std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const override {
281             class GLFP : public GrGLSLFragmentProcessor {
282             public:
283                 void emitCode(EmitArgs& args) override {
284                     SkString childColor = this->invokeChild(0, args);
285 
286                     const SwizzleFragmentProcessor& sfp = args.fFp.cast<SwizzleFragmentProcessor>();
287                     const GrSwizzle& swizzle = sfp.swizzle();
288                     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
289 
290                     fragBuilder->codeAppendf("return %s.%s;",
291                                              childColor.c_str(), swizzle.asString().c_str());
292                 }
293             };
294             return std::make_unique<GLFP>();
295         }
296 
297         void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
298             b->add32(fSwizzle.asKey());
299         }
300 
301         bool onIsEqual(const GrFragmentProcessor& other) const override {
302             const SwizzleFragmentProcessor& sfp = other.cast<SwizzleFragmentProcessor>();
303             return fSwizzle == sfp.fSwizzle;
304         }
305 
306         SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
307             return fSwizzle.applyTo(ConstantOutputForConstantInput(this->childProcessor(0), input));
308         }
309 
310         GrSwizzle fSwizzle;
311 
312         using INHERITED = GrFragmentProcessor;
313     };
314 
315     if (!fp) {
316         return nullptr;
317     }
318     if (GrSwizzle::RGBA() == swizzle) {
319         return fp;
320     }
321     return SwizzleFragmentProcessor::Make(std::move(fp), swizzle);
322 }
323 
MakeInputPremulAndMulByOutput(std::unique_ptr<GrFragmentProcessor> fp)324 std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MakeInputPremulAndMulByOutput(
325         std::unique_ptr<GrFragmentProcessor> fp) {
326     class PremulFragmentProcessor : public GrFragmentProcessor {
327     public:
328         static std::unique_ptr<GrFragmentProcessor> Make(
329                 std::unique_ptr<GrFragmentProcessor> processor) {
330             return std::unique_ptr<GrFragmentProcessor>(
331                     new PremulFragmentProcessor(std::move(processor)));
332         }
333 
334         const char* name() const override { return "Premultiply"; }
335 
336         std::unique_ptr<GrFragmentProcessor> clone() const override {
337             return Make(this->childProcessor(0)->clone());
338         }
339 
340     private:
341         PremulFragmentProcessor(std::unique_ptr<GrFragmentProcessor> processor)
342                 : INHERITED(kPremulFragmentProcessor_ClassID, OptFlags(processor.get())) {
343             this->registerChild(std::move(processor));
344         }
345 
346         std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const override {
347             class GLFP : public GrGLSLFragmentProcessor {
348             public:
349                 void emitCode(EmitArgs& args) override {
350                     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
351                     SkString temp = this->invokeChild(/*childIndex=*/0, "half4(1)", args);
352                     fragBuilder->codeAppendf("half4 color = %s;", temp.c_str());
353                     fragBuilder->codeAppendf("color.rgb *= %s.rgb;", args.fInputColor);
354                     fragBuilder->codeAppendf("return color * %s.a;", args.fInputColor);
355                 }
356             };
357             return std::make_unique<GLFP>();
358         }
359 
360         void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
361 
362         bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
363 
364         static OptimizationFlags OptFlags(const GrFragmentProcessor* inner) {
365             OptimizationFlags flags = kNone_OptimizationFlags;
366             if (inner->preservesOpaqueInput()) {
367                 flags |= kPreservesOpaqueInput_OptimizationFlag;
368             }
369             if (inner->hasConstantOutputForConstantInput()) {
370                 flags |= kConstantOutputForConstantInput_OptimizationFlag;
371             }
372             return flags;
373         }
374 
375         SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
376             SkPMColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0),
377                                                                     SK_PMColor4fWHITE);
378             SkPMColor4f premulInput = SkColor4f{ input.fR, input.fG, input.fB, input.fA }.premul();
379             return premulInput * childColor;
380         }
381 
382         using INHERITED = GrFragmentProcessor;
383     };
384     if (!fp) {
385         return nullptr;
386     }
387     return PremulFragmentProcessor::Make(std::move(fp));
388 }
389 
390 //////////////////////////////////////////////////////////////////////////////
391 
OverrideInput(std::unique_ptr<GrFragmentProcessor> fp,const SkPMColor4f & color,bool useUniform)392 std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(
393         std::unique_ptr<GrFragmentProcessor> fp, const SkPMColor4f& color, bool useUniform) {
394     if (!fp) {
395         return nullptr;
396     }
397     return GrOverrideInputFragmentProcessor::Make(std::move(fp), color, useUniform);
398 }
399 
400 //////////////////////////////////////////////////////////////////////////////
401 
Compose(std::unique_ptr<GrFragmentProcessor> f,std::unique_ptr<GrFragmentProcessor> g)402 std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::Compose(
403         std::unique_ptr<GrFragmentProcessor> f, std::unique_ptr<GrFragmentProcessor> g) {
404     class ComposeProcessor : public GrFragmentProcessor {
405     public:
406         static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> f,
407                                                          std::unique_ptr<GrFragmentProcessor> g) {
408             return std::unique_ptr<GrFragmentProcessor>(new ComposeProcessor(std::move(f),
409                                                                              std::move(g)));
410         }
411 
412         const char* name() const override { return "Compose"; }
413 
414         std::unique_ptr<GrFragmentProcessor> clone() const override {
415             return std::unique_ptr<GrFragmentProcessor>(new ComposeProcessor(*this));
416         }
417 
418     private:
419         std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const override {
420             class GLFP : public GrGLSLFragmentProcessor {
421             public:
422                 void emitCode(EmitArgs& args) override {
423                     SkString result = this->invokeChild(1, args);         // g(x)
424                     result = this->invokeChild(0, result.c_str(), args);  // f(g(x))
425                     args.fFragBuilder->codeAppendf("return %s;", result.c_str());
426                 }
427             };
428             return std::make_unique<GLFP>();
429         }
430 
431         ComposeProcessor(std::unique_ptr<GrFragmentProcessor> f,
432                          std::unique_ptr<GrFragmentProcessor> g)
433                 : INHERITED(kSeriesFragmentProcessor_ClassID,
434                             f->optimizationFlags() & g->optimizationFlags()) {
435             this->registerChild(std::move(f));
436             this->registerChild(std::move(g));
437         }
438 
439         ComposeProcessor(const ComposeProcessor& that)
440                 : INHERITED(kSeriesFragmentProcessor_ClassID, that.optimizationFlags()) {
441             this->cloneAndRegisterAllChildProcessors(that);
442         }
443 
444         void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
445 
446         bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
447 
448         SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
449             SkPMColor4f color = inColor;
450             color = ConstantOutputForConstantInput(this->childProcessor(1), color);
451             color = ConstantOutputForConstantInput(this->childProcessor(0), color);
452             return color;
453         }
454 
455         using INHERITED = GrFragmentProcessor;
456     };
457 
458     // Allow either of the composed functions to be null.
459     if (f == nullptr) {
460         return g;
461     }
462     if (g == nullptr) {
463         return f;
464     }
465 
466     // Run an optimization pass on this composition.
467     GrProcessorAnalysisColor inputColor;
468     inputColor.setToUnknown();
469 
470     std::unique_ptr<GrFragmentProcessor> series[2] = {std::move(g), std::move(f)};
471     GrColorFragmentProcessorAnalysis info(inputColor, series, SK_ARRAY_COUNT(series));
472 
473     SkPMColor4f knownColor;
474     int leadingFPsToEliminate = info.initialProcessorsToEliminate(&knownColor);
475     switch (leadingFPsToEliminate) {
476         default:
477             // We shouldn't eliminate more than we started with.
478             SkASSERT(leadingFPsToEliminate <= 2);
479             [[fallthrough]];
480         case 0:
481             // Compose the two processors as requested.
482             return ComposeProcessor::Make(/*f=*/std::move(series[1]), /*g=*/std::move(series[0]));
483         case 1:
484             // Replace the first processor with a constant color.
485             return ComposeProcessor::Make(/*f=*/std::move(series[1]),
486                                           /*g=*/MakeColor(knownColor));
487         case 2:
488             // Replace the entire composition with a constant color.
489             return MakeColor(knownColor);
490     }
491 }
492 
493 //////////////////////////////////////////////////////////////////////////////
494 
CIter(const GrPaint & paint)495 GrFragmentProcessor::CIter::CIter(const GrPaint& paint) {
496     if (paint.hasCoverageFragmentProcessor()) {
497         fFPStack.push_back(paint.getCoverageFragmentProcessor());
498     }
499     if (paint.hasColorFragmentProcessor()) {
500         fFPStack.push_back(paint.getColorFragmentProcessor());
501     }
502 }
503 
CIter(const GrPipeline & pipeline)504 GrFragmentProcessor::CIter::CIter(const GrPipeline& pipeline) {
505     for (int i = pipeline.numFragmentProcessors() - 1; i >= 0; --i) {
506         fFPStack.push_back(&pipeline.getFragmentProcessor(i));
507     }
508 }
509 
operator ++()510 GrFragmentProcessor::CIter& GrFragmentProcessor::CIter::operator++() {
511     SkASSERT(!fFPStack.empty());
512     const GrFragmentProcessor* back = fFPStack.back();
513     fFPStack.pop_back();
514     for (int i = back->numChildProcessors() - 1; i >= 0; --i) {
515         if (auto child = back->childProcessor(i)) {
516             fFPStack.push_back(child);
517         }
518     }
519     return *this;
520 }
521 
522