• 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 "float2(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(int offset, const Type& type, std::vector<std::unique_ptr<Expression>> arguments)
29     : INHERITED(offset, kConstructor_Kind, type)
30     , fArguments(std::move(arguments)) {}
31 
constantPropagateConstructor32     std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
33                                                   const DefinitionMap& definitions) override {
34         if (fArguments.size() == 1 && fArguments[0]->fKind == Expression::kIntLiteral_Kind) {
35             if (fType == *irGenerator.fContext.fFloat_Type ||
36                 fType == *irGenerator.fContext.fHalf_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                                                                     fOffset,
41                                                                     intValue));
42             } else if (fType == *irGenerator.fContext.fUInt_Type ||
43                        fType == *irGenerator.fContext.fUShort_Type) {
44                 // promote uint(1) to 1u
45                 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
46                 return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
47                                                                   fOffset,
48                                                                   intValue,
49                                                                   &fType));
50             }
51         }
52         return nullptr;
53     }
54 
hasSideEffectsConstructor55     bool hasSideEffects() const override {
56         for (const auto& arg : fArguments) {
57             if (arg->hasSideEffects()) {
58                 return true;
59             }
60         }
61         return false;
62     }
63 
descriptionConstructor64     String description() const override {
65         String result = fType.description() + "(";
66         String separator;
67         for (size_t i = 0; i < fArguments.size(); i++) {
68             result += separator;
69             result += fArguments[i]->description();
70             separator = ", ";
71         }
72         result += ")";
73         return result;
74     }
75 
isConstantConstructor76     bool isConstant() const override {
77         for (size_t i = 0; i < fArguments.size(); i++) {
78             if (!fArguments[i]->isConstant()) {
79                 return false;
80             }
81         }
82         return true;
83     }
84 
compareConstantConstructor85     bool compareConstant(const Context& context, const Expression& other) const override {
86         ASSERT(other.fKind == Expression::kConstructor_Kind && other.fType == fType);
87         Constructor& c = (Constructor&) other;
88         if (c.fType.kind() == Type::kVector_Kind) {
89             for (int i = 0; i < fType.columns(); i++) {
90                 if (!this->getVecComponent(i).compareConstant(context, c.getVecComponent(i))) {
91                     return false;
92                 }
93             }
94             return true;
95         }
96         // shouldn't be possible to have a constant constructor that isn't a vector or matrix;
97         // a constant scalar constructor should have been collapsed down to the appropriate
98         // literal
99         ASSERT(fType.kind() == Type::kMatrix_Kind);
100         const FloatLiteral fzero(context, -1, 0);
101         const IntLiteral izero(context, -1, 0);
102         const Expression* zero;
103         if (fType.componentType() == *context.fFloat_Type) {
104             zero = &fzero;
105         } else {
106             ASSERT(fType.componentType() == *context.fInt_Type);
107             zero = &izero;
108         }
109         for (int col = 0; col < fType.columns(); col++) {
110             for (int row = 0; row < fType.rows(); row++) {
111                 const Expression* component1 = getMatComponent(col, row);
112                 const Expression* component2 = c.getMatComponent(col, row);
113                 if (!(component1 ? component1 : zero)->compareConstant(
114                                                                 context,
115                                                                 component2 ? *component2 : *zero)) {
116                     return false;
117                 }
118             }
119         }
120         return true;
121     }
122 
getVecComponentConstructor123     const Expression& getVecComponent(int index) const {
124         ASSERT(fType.kind() == Type::kVector_Kind);
125         if (fArguments.size() == 1 && fArguments[0]->fType.kind() == Type::kScalar_Kind) {
126             return *fArguments[0];
127         }
128         int current = 0;
129         for (const auto& arg : fArguments) {
130             ASSERT(current <= index);
131             if (arg->fType.kind() == Type::kScalar_Kind) {
132                 if (index == current) {
133                     return *arg;
134                 }
135                 current++;
136             } else {
137                 ASSERT(arg->fType.kind() == Type::kVector_Kind);
138                 ASSERT(arg->fKind == Expression::kConstructor_Kind);
139                 if (current + arg->fType.columns() > index) {
140                     return ((const Constructor&) *arg).getVecComponent(index - current);
141                 }
142                 current += arg->fType.columns();
143             }
144         }
145         ABORT("failed to find vector component %d in %s\n", index, description().c_str());
146     }
147 
getFVecComponentConstructor148     double getFVecComponent(int index) const {
149         return this->getVecComponent(index).getConstantFloat();
150     }
151 
getIVecComponentConstructor152     int64_t getIVecComponent(int index) const {
153         return this->getVecComponent(index).getConstantInt();
154     }
155 
156     // null return should be interpreted as zero
getMatComponentConstructor157     const Expression* getMatComponent(int col, int row) const {
158         ASSERT(this->isConstant());
159         ASSERT(fType.kind() == Type::kMatrix_Kind);
160         ASSERT(col < fType.columns() && row < fType.rows());
161         if (fArguments.size() == 1) {
162             if (fArguments[0]->fType.kind() == Type::kScalar_Kind) {
163                 // single scalar argument, so matrix is of the form:
164                 // x 0 0
165                 // 0 x 0
166                 // 0 0 x
167                 // return x if col == row
168                 return col == row ? fArguments[0].get() : nullptr;
169             }
170             if (fArguments[0]->fType.kind() == Type::kMatrix_Kind) {
171                 ASSERT(fArguments[0]->fKind == Expression::kConstructor_Kind);
172                 // single matrix argument. make sure we're within the argument's bounds.
173                 const Type& argType = ((Constructor&) *fArguments[0]).fType;
174                 if (col < argType.columns() && row < argType.rows()) {
175                     // within bounds, defer to argument
176                     return ((Constructor&) *fArguments[0]).getMatComponent(col, row);
177                 }
178                 // out of bounds, return 0
179                 return nullptr;
180             }
181         }
182         int currentIndex = 0;
183         int targetIndex = col * fType.rows() + row;
184         for (const auto& arg : fArguments) {
185             ASSERT(targetIndex >= currentIndex);
186             ASSERT(arg->fType.rows() == 1);
187             if (currentIndex + arg->fType.columns() > targetIndex) {
188                 if (arg->fType.columns() == 1) {
189                     return arg.get();
190                 } else {
191                     ASSERT(arg->fType.kind() == Type::kVector_Kind);
192                     ASSERT(arg->fKind == Expression::kConstructor_Kind);
193                     return &((Constructor&) *arg).getVecComponent(targetIndex - currentIndex);
194                 }
195             }
196             currentIndex += arg->fType.columns();
197         }
198         ABORT("can't happen, matrix component out of bounds");
199     }
200 
201     std::vector<std::unique_ptr<Expression>> fArguments;
202 
203     typedef Expression INHERITED;
204 };
205 
206 } // namespace
207 
208 #endif
209