• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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 #ifndef SKSL_CONSTRUCTOR
9 #define SKSL_CONSTRUCTOR
10 
11 #include "include/core/SkSpan.h"
12 #include "src/sksl/ir/SkSLExpression.h"
13 
14 namespace SkSL {
15 
16 /**
17  * Base class representing a constructor with unknown arguments.
18  */
19 class AnyConstructor : public Expression {
20 public:
AnyConstructor(int line,Kind kind,const Type * type)21     AnyConstructor(int line, Kind kind, const Type* type)
22             : INHERITED(line, kind, type) {}
23 
24     virtual SkSpan<std::unique_ptr<Expression>> argumentSpan() = 0;
25     virtual SkSpan<const std::unique_ptr<Expression>> argumentSpan() const = 0;
26 
hasProperty(Property property)27     bool hasProperty(Property property) const override {
28         for (const std::unique_ptr<Expression>& arg : this->argumentSpan()) {
29             if (arg->hasProperty(property)) {
30                 return true;
31             }
32         }
33         return false;
34     }
35 
description()36     std::string description() const override {
37         std::string result = this->type().description() + "(";
38         const char* separator = "";
39         for (const std::unique_ptr<Expression>& arg : this->argumentSpan()) {
40             result += separator;
41             result += arg->description();
42             separator = ", ";
43         }
44         result += ")";
45         return result;
46     }
47 
componentType()48     const Type& componentType() const {
49         return this->type().componentType();
50     }
51 
isCompileTimeConstant()52     bool isCompileTimeConstant() const override {
53         for (const std::unique_ptr<Expression>& arg : this->argumentSpan()) {
54             if (!arg->isCompileTimeConstant()) {
55                 return false;
56             }
57         }
58         return true;
59     }
60 
isConstantOrUniform()61     bool isConstantOrUniform() const override {
62         for (const std::unique_ptr<Expression>& arg : this->argumentSpan()) {
63             if (!arg->isConstantOrUniform()) {
64                 return false;
65             }
66         }
67         return true;
68     }
69 
supportsConstantValues()70     bool supportsConstantValues() const override { return true; }
71     std::optional<double> getConstantValue(int n) const override;
72 
73     ComparisonResult compareConstant(const Expression& other) const override;
74 
75 private:
76     using INHERITED = Expression;
77 };
78 
79 /**
80  * Base class representing a constructor that takes a single argument.
81  */
82 class SingleArgumentConstructor : public AnyConstructor {
83 public:
SingleArgumentConstructor(int line,Kind kind,const Type * type,std::unique_ptr<Expression> argument)84     SingleArgumentConstructor(int line, Kind kind, const Type* type,
85                               std::unique_ptr<Expression> argument)
86             : INHERITED(line, kind, type)
87             , fArgument(std::move(argument)) {}
88 
argument()89     std::unique_ptr<Expression>& argument() {
90         return fArgument;
91     }
92 
argument()93     const std::unique_ptr<Expression>& argument() const {
94         return fArgument;
95     }
96 
argumentSpan()97     SkSpan<std::unique_ptr<Expression>> argumentSpan() final {
98         return {&fArgument, 1};
99     }
100 
argumentSpan()101     SkSpan<const std::unique_ptr<Expression>> argumentSpan() const final {
102         return {&fArgument, 1};
103     }
104 
105 private:
106     std::unique_ptr<Expression> fArgument;
107 
108     using INHERITED = AnyConstructor;
109 };
110 
111 /**
112  * Base class representing a constructor that takes an array of arguments.
113  */
114 class MultiArgumentConstructor : public AnyConstructor {
115 public:
MultiArgumentConstructor(int line,Kind kind,const Type * type,ExpressionArray arguments)116     MultiArgumentConstructor(int line, Kind kind, const Type* type, ExpressionArray arguments)
117             : INHERITED(line, kind, type)
118             , fArguments(std::move(arguments)) {}
119 
arguments()120     ExpressionArray& arguments() {
121         return fArguments;
122     }
123 
arguments()124     const ExpressionArray& arguments() const {
125         return fArguments;
126     }
127 
argumentSpan()128     SkSpan<std::unique_ptr<Expression>> argumentSpan() final {
129         return {&fArguments.front(), fArguments.size()};
130     }
131 
argumentSpan()132     SkSpan<const std::unique_ptr<Expression>> argumentSpan() const final {
133         return {&fArguments.front(), fArguments.size()};
134     }
135 
136 private:
137     ExpressionArray fArguments;
138 
139     using INHERITED = AnyConstructor;
140 };
141 
142 /**
143  * Converts any GLSL constructor, such as `float2(x, y)` or `mat3x3(otherMat)` or `int[2](0, i)`, to
144  * an SkSL expression.
145  *
146  * Vector constructors must always consist of either exactly 1 scalar, or a collection of vectors
147  * and scalars totaling exactly the right number of scalar components.
148  *
149  * Matrix constructors must always consist of either exactly 1 scalar, exactly 1 matrix, or a
150  * collection of vectors and scalars totaling exactly the right number of scalar components.
151  *
152  * Array constructors must always contain the proper number of array elements (matching the Type).
153  */
154 namespace Constructor {
155     // Creates, typechecks and simplifies constructor expressions. Reports errors via the
156     // ErrorReporter. This can return null on error, so be careful. There are several different
157     // Constructor expression types; this class chooses the proper one based on context, e.g.
158     // `ConstructorCompound`, `ConstructorScalarCast`, or `ConstructorMatrixResize`.
159     std::unique_ptr<Expression> Convert(const Context& context,
160                                         int line,
161                                         const Type& type,
162                                         ExpressionArray args);
163 };
164 
165 }  // namespace SkSL
166 
167 #endif
168