Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / sksl / ir / SkSLBinaryExpression.cpp
1 /*
2  * Copyright 2021 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
8 #include "include/sksl/SkSLErrorReporter.h"
9 #include "src/sksl/SkSLAnalysis.h"
10 #include "src/sksl/SkSLConstantFolder.h"
11 #include "src/sksl/SkSLProgramSettings.h"
12 #include "src/sksl/ir/SkSLBinaryExpression.h"
13 #include "src/sksl/ir/SkSLIndexExpression.h"
14 #include "src/sksl/ir/SkSLLiteral.h"
15 #include "src/sksl/ir/SkSLSetting.h"
16 #include "src/sksl/ir/SkSLSwizzle.h"
17 #include "src/sksl/ir/SkSLTernaryExpression.h"
18 #include "src/sksl/ir/SkSLType.h"
19 #include "src/sksl/ir/SkSLVariableReference.h"
20
21 namespace SkSL {
22
23 static bool is_low_precision_matrix_vector_multiply(const Expression& left,
24                                                     const Operator& op,
25                                                     const Expression& right,
26                                                     const Type& resultType) {
27     return !resultType.highPrecision() &&
28            op.kind() == Operator::Kind::STAR &&
29            left.type().isMatrix() &&
30            right.type().isVector() &&
31            left.type().rows() == right.type().columns() &&
32            Analysis::IsTrivialExpression(left) &&
33            Analysis::IsTrivialExpression(right);
34 }
35
36 static std::unique_ptr<Expression> rewrite_matrix_vector_multiply(const Context& context,
37                                                                   Position pos,
38                                                                   const Expression& left,
39                                                                   const Operator& op,
40                                                                   const Expression& right,
41                                                                   const Type& resultType) {
42     // Rewrite m33 * v3 as (m[0] * v[0] + m[1] * v[1] + m[2] * v[2])
43     std::unique_ptr<Expression> sum;
44     for (int n = 0; n < left.type().rows(); ++n) {
45         // Get mat[N] with an index expression.
46         std::unique_ptr<Expression> matN = IndexExpression::Make(
47                 context, pos, left.clone(), Literal::MakeInt(context, left.fPosition, n));
48         // Get vec[N] with a swizzle expression.
49         std::unique_ptr<Expression> vecN = Swizzle::Make(context,
50                 left.fPosition.rangeThrough(right.fPosition), right.clone(),
51                 ComponentArray{(SkSL::SwizzleComponent::Type)n});
52         // Multiply them together.
53         const Type* matNType = &matN->type();
54         std::unique_ptr<Expression> product =
55                 BinaryExpression::Make(context, pos, std::move(matN), op, std::move(vecN),
56                                        matNType);
57         // Sum all the components together.
58         if (!sum) {
59             sum = std::move(product);
60         } else {
61             sum = BinaryExpression::Make(context,
62                                          pos,
63                                          std::move(sum),
64                                          Operator(Operator::Kind::PLUS),
65                                          std::move(product),
66                                          matNType);
67         }
68     }
69
70     return sum;
71 }
72
73 std::unique_ptr<Expression> BinaryExpression::Convert(const Context& context,
74                                                       Position pos,
75                                                       std::unique_ptr<Expression> left,
76                                                       Operator op,
77                                                       std::unique_ptr<Expression> right) {
78     if (!left || !right) {
79         return nullptr;
80     }
81     const Type* rawLeftType = (left->isIntLiteral() && right->type().isInteger())
82             ? &right->type()
83             : &left->type();
84     const Type* rawRightType = (right->isIntLiteral() && left->type().isInteger())
85             ? &left->type()
86             : &right->type();
87
88     bool isAssignment = op.isAssignment();
89     if (isAssignment &&
90         !Analysis::UpdateVariableRefKind(left.get(),
91                                          op.kind() != Operator::Kind::EQ
92                                                  ? VariableReference::RefKind::kReadWrite
93                                                  : VariableReference::RefKind::kWrite,
94                                          context.fErrors)) {
95         return nullptr;
96     }
97
98     const Type* leftType;
99     const Type* rightType;
100     const Type* resultType;
101     if (!op.determineBinaryType(context, *rawLeftType, *rawRightType,
102                                 &leftType, &rightType, &resultType)) {
103         context.fErrors->error(pos, "type mismatch: '" + std::string(op.tightOperatorName()) +
104                 "' cannot operate on '" + left->type().displayName() + "', '" +
105                 right->type().displayName() + "'");
106         return nullptr;
107     }
108
109     if (isAssignment && leftType->componentType().isOpaque()) {
110         context.fErrors->error(pos, "assignments to opaque type '" + left->type().displayName() +
111                 "' are not permitted");
112         return nullptr;
113     }
114     if (context.fConfig->strictES2Mode()) {
115         if (!op.isAllowedInStrictES2Mode()) {
116             context.fErrors->error(pos, "operator '" + std::string(op.tightOperatorName()) +
117                     "' is not allowed");
118             return nullptr;
119         }
120         if (leftType->isOrContainsArray()) {
121             // Most operators are already rejected on arrays, but GLSL ES 1.0 is very explicit that
122             // the *only* operator allowed on arrays is subscripting (and the rules against
123             // assignment, comparison, and even sequence apply to structs containing arrays as well)
124             context.fErrors->error(pos, "operator '" + std::string(op.tightOperatorName()) +
125                     "' can not operate on arrays (or structs containing arrays)");
126             return nullptr;
127         }
128     }
129
130     left = leftType->coerceExpression(std::move(left), context);
131     right = rightType->coerceExpression(std::move(right), context);
132     if (!left || !right) {
133         return nullptr;
134     }
135
136     return BinaryExpression::Make(context, pos, std::move(left), op, std::move(right), resultType);
137 }
138
139 std::unique_ptr<Expression> BinaryExpression::Make(const Context& context,
140                                                    Position pos,
141                                                    std::unique_ptr<Expression> left,
142                                                    Operator op,
143                                                    std::unique_ptr<Expression> right) {
144     // Determine the result type of the binary expression.
145     const Type* leftType;
146     const Type* rightType;
147     const Type* resultType;
148     SkAssertResult(op.determineBinaryType(context, left->type(), right->type(),
149                                           &leftType, &rightType, &resultType));
150
151     return BinaryExpression::Make(context, pos, std::move(left), op, std::move(right), resultType);
152 }
153
154 std::unique_ptr<Expression> BinaryExpression::Make(const Context& context,
155                                                    Position pos,
156                                                    std::unique_ptr<Expression> left,
157                                                    Operator op,
158                                                    std::unique_ptr<Expression> right,
159                                                    const Type* resultType) {
160     // We should have detected non-ES2 compliant behavior in Convert.
161     SkASSERT(!context.fConfig->strictES2Mode() || op.isAllowedInStrictES2Mode());
162     SkASSERT(!context.fConfig->strictES2Mode() || !left->type().isOrContainsArray());
163
164     // We should have detected non-assignable assignment expressions in Convert.
165     SkASSERT(!op.isAssignment() || Analysis::IsAssignable(*left));
166     SkASSERT(!op.isAssignment() || !left->type().componentType().isOpaque());
167
168     // For simple assignments, detect and report out-of-range literal values.
169     if (op.kind() == Operator::Kind::EQ) {
170         left->type().checkForOutOfRangeLiteral(context, *right);
171     }
172
173     // Perform constant-folding on the expression.
174     if (std::unique_ptr<Expression> result = ConstantFolder::Simplify(context, pos, *left,
175                                                                       op, *right, *resultType)) {
176         return result;
177     }
178
179     if (context.fConfig->fSettings.fOptimize) {
180         // When sk_Caps.rewriteMatrixVectorMultiply is set, we rewrite medium-precision
181         // matrix * vector multiplication as:
182         //   (sk_Caps.rewriteMatrixVectorMultiply ? (mat[0]*vec[0] + ... + mat[N]*vec[N])
183         //                                        : mat * vec)
184         if (is_low_precision_matrix_vector_multiply(*left, op, *right, *resultType)) {
185             // Look up `sk_Caps.rewriteMatrixVectorMultiply`.
186             auto caps = Setting::Convert(context, pos, "rewriteMatrixVectorMultiply");
187
188             bool capsBitIsTrue = caps->isBoolLiteral() && caps->as<Literal>().boolValue();
189             if (capsBitIsTrue || !caps->isBoolLiteral()) {
190                 // Rewrite the multiplication as a sum of vector-scalar products.
191                 std::unique_ptr<Expression> rewrite =
192                         rewrite_matrix_vector_multiply(context, pos, *left, op, *right,
193                                                        *resultType);
194
195                 // If we know the caps bit is true, return the rewritten expression directly.
196                 if (capsBitIsTrue) {
197                     return rewrite;
198                 }
199
200                 // Return a ternary expression:
201                 //     sk_Caps.rewriteMatrixVectorMultiply ? (rewrite) : (mat * vec)
202                 return TernaryExpression::Make(
203                         context,
204                         pos,
205                         std::move(caps),
206                         std::move(rewrite),
207                         std::make_unique<BinaryExpression>(pos, std::move(left), op,
208                                                            std::move(right), resultType));
209             }
210         }
211     }
212
213     return std::make_unique<BinaryExpression>(pos, std::move(left), op,
214                                               std::move(right), resultType);
215 }
216
217 bool BinaryExpression::CheckRef(const Expression& expr) {
218     switch (expr.kind()) {
219         case Expression::Kind::kFieldAccess:
220             return CheckRef(*expr.as<FieldAccess>().base());
221
222         case Expression::Kind::kIndex:
223             return CheckRef(*expr.as<IndexExpression>().base());
224
225         case Expression::Kind::kSwizzle:
226             return CheckRef(*expr.as<Swizzle>().base());
227
228         case Expression::Kind::kTernary: {
229             const TernaryExpression& t = expr.as<TernaryExpression>();
230             return CheckRef(*t.ifTrue()) && CheckRef(*t.ifFalse());
231         }
232         case Expression::Kind::kVariableReference: {
233             const VariableReference& ref = expr.as<VariableReference>();
234             return ref.refKind() == VariableRefKind::kWrite ||
235                    ref.refKind() == VariableRefKind::kReadWrite;
236         }
237         default:
238             return false;
239     }
240 }
241
242 std::unique_ptr<Expression> BinaryExpression::clone(Position pos) const {
243     return std::make_unique<BinaryExpression>(pos,
244                                               this->left()->clone(),
245                                               this->getOperator(),
246                                               this->right()->clone(),
247                                               &this->type());
248 }
249
250 std::string BinaryExpression::description() const {
251     return "(" + this->left()->description() +
252                  this->getOperator().operatorName() +
253                  this->right()->description() + ")";
254 }
255
256 }  // namespace SkSL