• 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(fOffset,
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 
cloneConstructor63     std::unique_ptr<Expression> clone() const override {
64         std::vector<std::unique_ptr<Expression>> cloned;
65         for (const auto& arg : fArguments) {
66             cloned.push_back(arg->clone());
67         }
68         return std::unique_ptr<Expression>(new Constructor(fOffset, fType, std::move(cloned)));
69     }
70 
descriptionConstructor71     String description() const override {
72         String result = fType.description() + "(";
73         String separator;
74         for (size_t i = 0; i < fArguments.size(); i++) {
75             result += separator;
76             result += fArguments[i]->description();
77             separator = ", ";
78         }
79         result += ")";
80         return result;
81     }
82 
isConstantConstructor83     bool isConstant() const override {
84         for (size_t i = 0; i < fArguments.size(); i++) {
85             if (!fArguments[i]->isConstant()) {
86                 return false;
87             }
88         }
89         return true;
90     }
91 
compareConstantConstructor92     bool compareConstant(const Context& context, const Expression& other) const override {
93         SkASSERT(other.fKind == Expression::kConstructor_Kind && other.fType == fType);
94         Constructor& c = (Constructor&) other;
95         if (c.fType.kind() == Type::kVector_Kind) {
96             for (int i = 0; i < fType.columns(); i++) {
97                 if (!this->getVecComponent(i).compareConstant(context, c.getVecComponent(i))) {
98                     return false;
99                 }
100             }
101             return true;
102         }
103         // shouldn't be possible to have a constant constructor that isn't a vector or matrix;
104         // a constant scalar constructor should have been collapsed down to the appropriate
105         // literal
106         SkASSERT(fType.kind() == Type::kMatrix_Kind);
107         const FloatLiteral fzero(context, -1, 0);
108         const IntLiteral izero(context, -1, 0);
109         const Expression* zero;
110         if (fType.componentType() == *context.fFloat_Type) {
111             zero = &fzero;
112         } else {
113             SkASSERT(fType.componentType() == *context.fInt_Type);
114             zero = &izero;
115         }
116         for (int col = 0; col < fType.columns(); col++) {
117             for (int row = 0; row < fType.rows(); row++) {
118                 const Expression* component1 = getMatComponent(col, row);
119                 const Expression* component2 = c.getMatComponent(col, row);
120                 if (!(component1 ? component1 : zero)->compareConstant(
121                                                                 context,
122                                                                 component2 ? *component2 : *zero)) {
123                     return false;
124                 }
125             }
126         }
127         return true;
128     }
129 
getVecComponentConstructor130     const Expression& getVecComponent(int index) const {
131         SkASSERT(fType.kind() == Type::kVector_Kind);
132         if (fArguments.size() == 1 && fArguments[0]->fType.kind() == Type::kScalar_Kind) {
133             return *fArguments[0];
134         }
135         int current = 0;
136         for (const auto& arg : fArguments) {
137             SkASSERT(current <= index);
138             if (arg->fType.kind() == Type::kScalar_Kind) {
139                 if (index == current) {
140                     return *arg;
141                 }
142                 current++;
143             } else {
144                 SkASSERT(arg->fType.kind() == Type::kVector_Kind);
145                 SkASSERT(arg->fKind == Expression::kConstructor_Kind);
146                 if (current + arg->fType.columns() > index) {
147                     return ((const Constructor&) *arg).getVecComponent(index - current);
148                 }
149                 current += arg->fType.columns();
150             }
151         }
152         ABORT("failed to find vector component %d in %s\n", index, description().c_str());
153     }
154 
getFVecComponentConstructor155     double getFVecComponent(int index) const {
156         return this->getVecComponent(index).getConstantFloat();
157     }
158 
getIVecComponentConstructor159     int64_t getIVecComponent(int index) const {
160         return this->getVecComponent(index).getConstantInt();
161     }
162 
163     // null return should be interpreted as zero
getMatComponentConstructor164     const Expression* getMatComponent(int col, int row) const {
165         SkASSERT(this->isConstant());
166         SkASSERT(fType.kind() == Type::kMatrix_Kind);
167         SkASSERT(col < fType.columns() && row < fType.rows());
168         if (fArguments.size() == 1) {
169             if (fArguments[0]->fType.kind() == Type::kScalar_Kind) {
170                 // single scalar argument, so matrix is of the form:
171                 // x 0 0
172                 // 0 x 0
173                 // 0 0 x
174                 // return x if col == row
175                 return col == row ? fArguments[0].get() : nullptr;
176             }
177             if (fArguments[0]->fType.kind() == Type::kMatrix_Kind) {
178                 SkASSERT(fArguments[0]->fKind == Expression::kConstructor_Kind);
179                 // single matrix argument. make sure we're within the argument's bounds.
180                 const Type& argType = ((Constructor&) *fArguments[0]).fType;
181                 if (col < argType.columns() && row < argType.rows()) {
182                     // within bounds, defer to argument
183                     return ((Constructor&) *fArguments[0]).getMatComponent(col, row);
184                 }
185                 // out of bounds, return 0
186                 return nullptr;
187             }
188         }
189         int currentIndex = 0;
190         int targetIndex = col * fType.rows() + row;
191         for (const auto& arg : fArguments) {
192             SkASSERT(targetIndex >= currentIndex);
193             SkASSERT(arg->fType.rows() == 1);
194             if (currentIndex + arg->fType.columns() > targetIndex) {
195                 if (arg->fType.columns() == 1) {
196                     return arg.get();
197                 } else {
198                     SkASSERT(arg->fType.kind() == Type::kVector_Kind);
199                     SkASSERT(arg->fKind == Expression::kConstructor_Kind);
200                     return &((Constructor&) *arg).getVecComponent(targetIndex - currentIndex);
201                 }
202             }
203             currentIndex += arg->fType.columns();
204         }
205         ABORT("can't happen, matrix component out of bounds");
206     }
207 
208     std::vector<std::unique_ptr<Expression>> fArguments;
209 
210     typedef Expression INHERITED;
211 };
212 
213 } // namespace
214 
215 #endif
216