Flutter Engine
The Flutter Engine
SkSLReturnsInputAlpha.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2023 Google LLC
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
29
30#include <memory>
31
32using namespace skia_private;
33
34namespace SkSL {
35namespace {
36
37class ReturnsInputAlphaVisitor : public ProgramVisitor {
38public:
39 ReturnsInputAlphaVisitor(const ProgramUsage& u) : fUsage(u) {}
40
41 bool visitProgramElement(const ProgramElement& pe) override {
42 const FunctionDeclaration& decl = pe.as<FunctionDefinition>().declaration();
43 SkSpan<Variable* const> parameters = decl.parameters();
44
45 // We expect a color filter to have a single half4 input.
46 if (parameters.size() != 1 ||
47 parameters[0]->type().columns() != 4 ||
48 !parameters[0]->type().componentType().isFloat()) {
49 // This doesn't look like a color filter.
50 return true;
51 }
52 fInputVar = parameters[0];
53
54 // If the input variable has been written-to, then returning `input.a` isn't sufficient to
55 // guarantee that alpha is preserved.
56 ProgramUsage::VariableCounts counts = fUsage.get(*fInputVar);
57 if (counts.fWrite != 0) {
58 return true;
59 }
60
62 }
63
64 bool isInputVar(const Expression& expr) {
65 return expr.is<VariableReference>() && expr.as<VariableReference>().variable() == fInputVar;
66 }
67
68 bool isInputSwizzleEndingWithAlpha(const Expression& expr) {
69 if (!expr.is<Swizzle>()) {
70 return false;
71 }
72 const Swizzle& swizzle = expr.as<Swizzle>();
73 return this->isInputVar(*swizzle.base()) && swizzle.components().back() == 3;
74 }
75
76 bool returnsInputAlpha(const Expression& expr) {
77 if (this->isInputVar(expr)) {
78 // This expression returns the input value as-is.
79 return true;
80 }
81 if (expr.is<Swizzle>()) {
82 // It's a swizzle: check for `input.___a`.
83 return this->isInputSwizzleEndingWithAlpha(expr);
84 }
85 if (expr.is<ConstructorSplat>() || expr.is<ConstructorCompound>()) {
86 // This is a splat or compound constructor; check for `input.a` as its final component.
87 const AnyConstructor& ctor = expr.asAnyConstructor();
88 return this->returnsInputAlpha(*ctor.argumentSpan().back());
89 }
90 if (expr.is<ConstructorCompoundCast>()) {
91 // Ignore typecasts between float and half.
92 const Expression& arg = *expr.as<ConstructorCompoundCast>().argument();
93 return arg.type().componentType().isFloat() && this->returnsInputAlpha(arg);
94 }
95 if (expr.is<TernaryExpression>()) {
96 // Both sides of the ternary must preserve input alpha.
97 const TernaryExpression& ternary = expr.as<TernaryExpression>();
98 return this->returnsInputAlpha(*ternary.ifTrue()) &&
99 this->returnsInputAlpha(*ternary.ifFalse());
100 }
101 // We weren't able to pattern-match here.
102 return false;
103 }
104
105 bool visitStatement(const Statement& s) override {
106 if (s.is<ReturnStatement>()) {
107 return !this->returnsInputAlpha(*s.as<ReturnStatement>().expression());
108 }
110 }
111
112 bool visitExpression(const Expression& e) override {
113 // No need to recurse into expressions; these can never contain return statements.
114 return false;
115 }
116
117private:
118 const ProgramUsage& fUsage;
119 const Variable* fInputVar = nullptr;
120
121 using INHERITED = ProgramVisitor;
122};
123
124} // namespace
125
127 ReturnsInputAlphaVisitor visitor{usage};
128 return !visitor.visitProgramElement(function);
129}
130
131} // namespace SkSL
#define INHERITED(method,...)
Definition: SkRecorder.cpp:128
virtual bool visitStatement(typename T::Statement &statement)
virtual bool visitProgramElement(typename T::ProgramElement &programElement)
constexpr size_t size() const
Definition: SkSpan_impl.h:95
struct MyStruct s
Dart_NativeFunction function
Definition: fuchsia.cc:51
bool ReturnsInputAlpha(const FunctionDefinition &function, const ProgramUsage &usage)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core counts
Definition: switches.h:239
static void usage(char *argv0)