• 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 "SkSLExpression.h"
12 #include "SkSLFloatLiteral.h"
13 #include "SkSLIntLiteral.h"
14 #include "SkSLIRGenerator.h"
15 
16 namespace SkSL {
17 
18 /**
19  * Represents the construction of a compound type, such as "vec2(x, y)".
20  *
21  * Vector constructors will always consist of either exactly 1 scalar, or a collection of vectors
22  * and scalars totalling exactly the right number of scalar components.
23  *
24  * Matrix constructors will always consist of either exactly 1 scalar, exactly 1 matrix, or a
25  * collection of vectors and scalars totalling exactly the right number of scalar components.
26  */
27 struct Constructor : public Expression {
ConstructorConstructor28     Constructor(Position position, const Type& type,
29                 std::vector<std::unique_ptr<Expression>> arguments)
30     : INHERITED(position, kConstructor_Kind, type)
31     , fArguments(std::move(arguments)) {}
32 
constantPropagateConstructor33     std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
34                                                   const DefinitionMap& definitions) override {
35         if (fArguments.size() == 1 && fArguments[0]->fKind == Expression::kIntLiteral_Kind) {
36             if (fType == *irGenerator.fContext.fFloat_Type) {
37                 // promote float(1) to 1.0
38                 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
39                 return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext,
40                                                                     fPosition,
41                                                                     intValue));
42             } else if (fType == *irGenerator.fContext.fUInt_Type) {
43                 // promote uint(1) to 1u
44                 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
45                 return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
46                                                                   fPosition,
47                                                                   intValue,
48                                                                   &fType));
49             }
50         }
51         return nullptr;
52     }
53 
hasSideEffectsConstructor54     bool hasSideEffects() const override {
55         for (const auto& arg : fArguments) {
56             if (arg->hasSideEffects()) {
57                 return true;
58             }
59         }
60         return false;
61     }
62 
descriptionConstructor63     String description() const override {
64         String result = fType.description() + "(";
65         String separator;
66         for (size_t i = 0; i < fArguments.size(); i++) {
67             result += separator;
68             result += fArguments[i]->description();
69             separator = ", ";
70         }
71         result += ")";
72         return result;
73     }
74 
isConstantConstructor75     bool isConstant() const override {
76         for (size_t i = 0; i < fArguments.size(); i++) {
77             if (!fArguments[i]->isConstant()) {
78                 return false;
79             }
80         }
81         return true;
82     }
83 
compareConstantConstructor84     bool compareConstant(const Context& context, const Expression& other) const override {
85         ASSERT(other.fKind == Expression::kConstructor_Kind && other.fType == fType);
86         Constructor& c = (Constructor&) other;
87         if (c.fType.kind() == Type::kVector_Kind) {
88             for (int i = 0; i < fType.columns(); i++) {
89                 if (!this->getVecComponent(i).compareConstant(context, c.getVecComponent(i))) {
90                     return false;
91                 }
92             }
93             return true;
94         }
95         // shouldn't be possible to have a constant constructor that isn't a vector or matrix;
96         // a constant scalar constructor should have been collapsed down to the appropriate
97         // literal
98         ASSERT(fType.kind() == Type::kMatrix_Kind);
99         const FloatLiteral fzero(context, Position(), 0);
100         const IntLiteral izero(context, Position(), 0);
101         const Expression* zero;
102         if (fType.componentType() == *context.fFloat_Type) {
103             zero = &fzero;
104         } else {
105             ASSERT(fType.componentType() == *context.fInt_Type);
106             zero = &izero;
107         }
108         for (int col = 0; col < fType.columns(); col++) {
109             for (int row = 0; row < fType.rows(); row++) {
110                 const Expression* component1 = getMatComponent(col, row);
111                 const Expression* component2 = c.getMatComponent(col, row);
112                 if (!(component1 ? component1 : zero)->compareConstant(
113                                                                 context,
114                                                                 component2 ? *component2 : *zero)) {
115                     return false;
116                 }
117             }
118         }
119         return true;
120     }
121 
getVecComponentConstructor122     const Expression& getVecComponent(int index) const {
123         ASSERT(fType.kind() == Type::kVector_Kind);
124         if (fArguments.size() == 1 && fArguments[0]->fType.kind() == Type::kScalar_Kind) {
125             return *fArguments[0];
126         }
127         int current = 0;
128         for (const auto& arg : fArguments) {
129             ASSERT(current <= index);
130             if (arg->fType.kind() == Type::kScalar_Kind) {
131                 if (index == current) {
132                     return *arg;
133                 }
134                 current++;
135             } else {
136                 ASSERT(arg->fType.kind() == Type::kVector_Kind);
137                 ASSERT(arg->fKind == Expression::kConstructor_Kind);
138                 if (current + arg->fType.columns() > index) {
139                     return ((const Constructor&) *arg).getVecComponent(index - current);
140                 }
141                 current += arg->fType.columns();
142             }
143         }
144         ABORT("failed to find vector component %d in %s\n", index, description().c_str());
145     }
146 
getFVecComponentConstructor147     double getFVecComponent(int index) const {
148         const Expression& c = this->getVecComponent(index);
149         ASSERT(c.fKind == Expression::kFloatLiteral_Kind);
150         return ((FloatLiteral&) c).fValue;
151     }
152 
getIVecComponentConstructor153     int64_t getIVecComponent(int index) const {
154         const Expression& c = this->getVecComponent(index);
155         ASSERT(c.fKind == Expression::kIntLiteral_Kind);
156         return ((IntLiteral&) c).fValue;
157     }
158 
159     // null return should be interpreted as zero
getMatComponentConstructor160     const Expression* getMatComponent(int col, int row) const {
161         ASSERT(this->isConstant());
162         ASSERT(fType.kind() == Type::kMatrix_Kind);
163         ASSERT(col < fType.columns() && row < fType.rows());
164         if (fArguments.size() == 1) {
165             if (fArguments[0]->fType.kind() == Type::kScalar_Kind) {
166                 // single scalar argument, so matrix is of the form:
167                 // x 0 0
168                 // 0 x 0
169                 // 0 0 x
170                 // return x if col == row
171                 return col == row ? fArguments[0].get() : nullptr;
172             }
173             if (fArguments[0]->fType.kind() == Type::kMatrix_Kind) {
174                 ASSERT(fArguments[0]->fKind == Expression::kConstructor_Kind);
175                 // single matrix argument. make sure we're within the argument's bounds.
176                 const Type& argType = ((Constructor&) *fArguments[0]).fType;
177                 if (col < argType.columns() && row < argType.rows()) {
178                     // within bounds, defer to argument
179                     return ((Constructor&) *fArguments[0]).getMatComponent(col, row);
180                 }
181                 // out of bounds, return 0
182                 return nullptr;
183             }
184         }
185         int currentIndex = 0;
186         int targetIndex = col * fType.rows() + row;
187         for (const auto& arg : fArguments) {
188             ASSERT(targetIndex >= currentIndex);
189             ASSERT(arg->fType.rows() == 1);
190             if (currentIndex + arg->fType.columns() > targetIndex) {
191                 if (arg->fType.columns() == 1) {
192                     return arg.get();
193                 } else {
194                     ASSERT(arg->fType.kind() == Type::kVector_Kind);
195                     ASSERT(arg->fKind == Expression::kConstructor_Kind);
196                     return &((Constructor&) *arg).getVecComponent(targetIndex - currentIndex);
197                 }
198             }
199             currentIndex += arg->fType.columns();
200         }
201         ABORT("can't happen, matrix component out of bounds");
202     }
203 
204     std::vector<std::unique_ptr<Expression>> fArguments;
205 
206     typedef Expression INHERITED;
207 };
208 
209 } // namespace
210 
211 #endif
212