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 "src/sksl/SkSLIRGenerator.h"
12#include "src/sksl/ir/SkSLExpression.h"
13#include "src/sksl/ir/SkSLFloatLiteral.h"
14#include "src/sksl/ir/SkSLIntLiteral.h"
15#include "src/sksl/ir/SkSLPrefixExpression.h"
16
17namespace SkSL {
18
19/**
20 * Represents the construction of a compound type, such as "float2(x, y)".
21 *
22 * Vector constructors will always consist of either exactly 1 scalar, or a collection of vectors
23 * and scalars totalling exactly the right number of scalar components.
24 *
25 * Matrix constructors will always consist of either exactly 1 scalar, exactly 1 matrix, or a
26 * collection of vectors and scalars totalling exactly the right number of scalar components.
27 */
28struct Constructor : public Expression {
29 Constructor(int offset, const Type& type, std::vector<std::unique_ptr<Expression>> arguments)
30 : INHERITED(offset, kConstructor_Kind, type)
31 , fArguments(std::move(arguments)) {}
32
33 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.isFloat()) {
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.isInteger()) {
43 // promote uint(1) to 1u
44 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
45 return std::unique_ptr<Expression>(new IntLiteral(fOffset,
46 intValue,
47 &fType));
48 }
49 }
50 return nullptr;
51 }
52
53 bool hasProperty(Property property) const override {
54 for (const auto& arg : fArguments) {
55 if (arg->hasProperty(property)) {
56 return true;
57 }
58 }
59 return false;
60 }
61
62 int nodeCount() const override {
63 int result = 1;
64 for (const auto& a : fArguments) {
65 result += a->nodeCount();
66 }
67 return result;
68 }
69
70 std::unique_ptr<Expression> clone() const override {
71 std::vector<std::unique_ptr<Expression>> cloned;
72 for (const auto& arg : fArguments) {
73 cloned.push_back(arg->clone());
74 }
75 return std::unique_ptr<Expression>(new Constructor(fOffset, fType, std::move(cloned)));
76 }
77
78 String description() const override {
79 String result = fType.description() + "(";
80 String separator;
81 for (size_t i = 0; i < fArguments.size(); i++) {
82 result += separator;
83 result += fArguments[i]->description();
84 separator = ", ";
85 }
86 result += ")";
87 return result;
88 }
89
90 bool isCompileTimeConstant() const override {
91 for (size_t i = 0; i < fArguments.size(); i++) {
92 if (!fArguments[i]->isCompileTimeConstant()) {
93 return false;
94 }
95 }
96 return true;
97 }
98
99 bool isConstantOrUniform() const override {
100 for (size_t i = 0; i < fArguments.size(); i++) {
101 if (!fArguments[i]->isConstantOrUniform()) {
102 return false;
103 }
104 }
105 return true;
106 }
107
108 bool compareConstant(const Context& context, const Expression& other) const override {
109 SkASSERT(other.fKind == Expression::kConstructor_Kind && other.fType == fType);
110 Constructor& c = (Constructor&) other;
111 if (c.fType.kind() == Type::kVector_Kind) {
112 bool isFloat = c.fType.columns() > 1 ? c.fType.componentType().isFloat()
113 : c.fType.isFloat();
114 for (int i = 0; i < fType.columns(); i++) {
115 if (isFloat) {
116 if (this->getFVecComponent(i) != c.getFVecComponent(i)) {
117 return false;
118 }
119 } else if (this->getIVecComponent(i) != c.getIVecComponent(i)) {
120 return false;
121 }
122 }
123 return true;
124 }
125 // shouldn't be possible to have a constant constructor that isn't a vector or matrix;
126 // a constant scalar constructor should have been collapsed down to the appropriate
127 // literal
128 SkASSERT(fType.kind() == Type::kMatrix_Kind);
129 for (int col = 0; col < fType.columns(); col++) {
130 for (int row = 0; row < fType.rows(); row++) {
131 if (getMatComponent(col, row) != c.getMatComponent(col, row)) {
132 return false;
133 }
134 }
135 }
136 return true;
137 }
138
139 template<typename type>
140 type getVecComponent(int index) const {
141 SkASSERT(fType.kind() == Type::kVector_Kind);
142 if (fArguments.size() == 1 && fArguments[0]->fType.kind() == Type::kScalar_Kind) {
143 if (std::is_floating_point<type>::value) {
144 return fArguments[0]->getConstantFloat();
145 } else {
146 return fArguments[0]->getConstantInt();
147 }
148 }
149 int current = 0;
150 for (const auto& arg : fArguments) {
151 SkASSERT(current <= index);
152 if (arg->fType.kind() == Type::kScalar_Kind) {
153 if (index == current) {
154 if (std::is_floating_point<type>::value) {
155 return arg.get()->getConstantFloat();
156 } else {
157 return arg.get()->getConstantInt();
158 }
159 }
160 current++;
161 } else if (arg->fKind == kConstructor_Kind) {
162 if (current + arg->fType.columns() > index) {
163 return ((const Constructor&) *arg).getVecComponent<type>(index - current);
164 }
165 current += arg->fType.columns();
166 } else {
167 if (current + arg->fType.columns() > index) {
168 SkASSERT(arg->fKind == kPrefix_Kind);
169 const PrefixExpression& p = (PrefixExpression&) *arg;
170 const Constructor& c = (const Constructor&) *p.fOperand;
171 return -c.getVecComponent<type>(index - current);
172 }
173 current += arg->fType.columns();
174 }
175 }
176#ifdef SK_DEBUG
177 ABORT("failed to find vector component %d in %s\n", index, description().c_str());
178#endif
179 return -1;
180 }
181
182 SKSL_FLOAT getFVecComponent(int n) const override {
183 return this->getVecComponent<SKSL_FLOAT>(n);
184 }
185
186 /**
187 * For a literal vector expression, return the integer value of the n'th vector component. It is
188 * an error to call this method on an expression which is not a literal vector.
189 */
190 SKSL_INT getIVecComponent(int n) const override {
191 return this->getVecComponent<SKSL_INT>(n);
192 }
193
194 SKSL_FLOAT getMatComponent(int col, int row) const override {
195 SkASSERT(this->isCompileTimeConstant());
196 SkASSERT(fType.kind() == Type::kMatrix_Kind);
197 SkASSERT(col < fType.columns() && row < fType.rows());
198 if (fArguments.size() == 1) {
199 if (fArguments[0]->fType.kind() == Type::kScalar_Kind) {
200 // single scalar argument, so matrix is of the form:
201 // x 0 0
202 // 0 x 0
203 // 0 0 x
204 // return x if col == row
205 return col == row ? fArguments[0]->getConstantFloat() : 0.0;
206 }
207 if (fArguments[0]->fType.kind() == Type::kMatrix_Kind) {
208 SkASSERT(fArguments[0]->fKind == Expression::kConstructor_Kind);
209 // single matrix argument. make sure we're within the argument's bounds.
210 const Type& argType = ((Constructor&) *fArguments[0]).fType;
211 if (col < argType.columns() && row < argType.rows()) {
212 // within bounds, defer to argument
213 return ((Constructor&) *fArguments[0]).getMatComponent(col, row);
214 }
215 // out of bounds
216 return 0.0;
217 }
218 }
219 int currentIndex = 0;
220 int targetIndex = col * fType.rows() + row;
221 for (const auto& arg : fArguments) {
222 SkASSERT(targetIndex >= currentIndex);
223 SkASSERT(arg->fType.rows() == 1);
224 if (currentIndex + arg->fType.columns() > targetIndex) {
225 if (arg->fType.columns() == 1) {
226 return arg->getConstantFloat();
227 } else {
228 return arg->getFVecComponent(targetIndex - currentIndex);
229 }
230 }
231 currentIndex += arg->fType.columns();
232 }
233 ABORT("can't happen, matrix component out of bounds");
234 }
235
236 std::vector<std::unique_ptr<Expression>> fArguments;
237
238 typedef Expression INHERITED;
239};
240
241} // namespace SkSL
242
243#endif
244