blob: cea5265cea73304444a32d553a6b946e09f5a50b [file] [log] [blame]
ethannicholasb3058bd2016-07-01 08:22:01 -07001/*
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 */
Greg Daniel64773e62016-11-22 09:44:03 -05007
ethannicholasb3058bd2016-07-01 08:22:01 -07008#ifndef SKSL_CONSTRUCTOR
9#define SKSL_CONSTRUCTOR
10
11#include "SkSLExpression.h"
Ethan Nicholas86a43402017-01-19 13:32:00 -050012#include "SkSLFloatLiteral.h"
13#include "SkSLIntLiteral.h"
14#include "SkSLIRGenerator.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070015
16namespace SkSL {
17
18/**
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070019 * Represents the construction of a compound type, such as "float2(x, y)".
Ethan Nicholas84645e32017-02-09 13:57:14 -050020 *
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.
ethannicholasb3058bd2016-07-01 08:22:01 -070026 */
27struct Constructor : public Expression {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070028 Constructor(int offset, const Type& type, std::vector<std::unique_ptr<Expression>> arguments)
29 : INHERITED(offset, kConstructor_Kind, type)
ethannicholasb3058bd2016-07-01 08:22:01 -070030 , fArguments(std::move(arguments)) {}
31
Ethan Nicholascb670962017-04-20 19:31:52 -040032 std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
33 const DefinitionMap& definitions) override {
34 if (fArguments.size() == 1 && fArguments[0]->fKind == Expression::kIntLiteral_Kind) {
Ethan Nicholasf7b88202017-09-18 14:10:39 -040035 if (fType == *irGenerator.fContext.fFloat_Type ||
36 fType == *irGenerator.fContext.fHalf_Type) {
Ethan Nicholascb670962017-04-20 19:31:52 -040037 // promote float(1) to 1.0
38 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
39 return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070040 fOffset,
Ethan Nicholascb670962017-04-20 19:31:52 -040041 intValue));
Ethan Nicholasf7b88202017-09-18 14:10:39 -040042 } else if (fType == *irGenerator.fContext.fUInt_Type ||
43 fType == *irGenerator.fContext.fUShort_Type) {
Ethan Nicholascb670962017-04-20 19:31:52 -040044 // promote uint(1) to 1u
45 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
46 return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070047 fOffset,
Ethan Nicholascb670962017-04-20 19:31:52 -040048 intValue,
49 &fType));
50 }
Ethan Nicholas86a43402017-01-19 13:32:00 -050051 }
52 return nullptr;
53 }
54
Ethan Nicholascb670962017-04-20 19:31:52 -040055 bool hasSideEffects() const override {
56 for (const auto& arg : fArguments) {
57 if (arg->hasSideEffects()) {
58 return true;
59 }
60 }
61 return false;
62 }
63
Ethan Nicholas0df1b042017-03-31 13:56:23 -040064 String description() const override {
65 String result = fType.description() + "(";
66 String separator;
ethannicholasb3058bd2016-07-01 08:22:01 -070067 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
76 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
Ethan Nicholas3deaeb22017-04-25 14:42:11 -040085 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);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700100 const FloatLiteral fzero(context, -1, 0);
101 const IntLiteral izero(context, -1, 0);
Ethan Nicholas3deaeb22017-04-25 14:42:11 -0400102 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
Ethan Nicholascb670962017-04-20 19:31:52 -0400123 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
148 double getFVecComponent(int index) const {
149 const Expression& c = this->getVecComponent(index);
150 ASSERT(c.fKind == Expression::kFloatLiteral_Kind);
151 return ((FloatLiteral&) c).fValue;
152 }
153
154 int64_t getIVecComponent(int index) const {
155 const Expression& c = this->getVecComponent(index);
156 ASSERT(c.fKind == Expression::kIntLiteral_Kind);
157 return ((IntLiteral&) c).fValue;
158 }
159
Ethan Nicholas3deaeb22017-04-25 14:42:11 -0400160 // null return should be interpreted as zero
161 const Expression* getMatComponent(int col, int row) const {
162 ASSERT(this->isConstant());
163 ASSERT(fType.kind() == Type::kMatrix_Kind);
164 ASSERT(col < fType.columns() && row < fType.rows());
165 if (fArguments.size() == 1) {
166 if (fArguments[0]->fType.kind() == Type::kScalar_Kind) {
167 // single scalar argument, so matrix is of the form:
168 // x 0 0
169 // 0 x 0
170 // 0 0 x
171 // return x if col == row
172 return col == row ? fArguments[0].get() : nullptr;
173 }
174 if (fArguments[0]->fType.kind() == Type::kMatrix_Kind) {
175 ASSERT(fArguments[0]->fKind == Expression::kConstructor_Kind);
176 // single matrix argument. make sure we're within the argument's bounds.
177 const Type& argType = ((Constructor&) *fArguments[0]).fType;
178 if (col < argType.columns() && row < argType.rows()) {
179 // within bounds, defer to argument
180 return ((Constructor&) *fArguments[0]).getMatComponent(col, row);
181 }
182 // out of bounds, return 0
183 return nullptr;
184 }
185 }
186 int currentIndex = 0;
187 int targetIndex = col * fType.rows() + row;
188 for (const auto& arg : fArguments) {
189 ASSERT(targetIndex >= currentIndex);
190 ASSERT(arg->fType.rows() == 1);
191 if (currentIndex + arg->fType.columns() > targetIndex) {
192 if (arg->fType.columns() == 1) {
193 return arg.get();
194 } else {
195 ASSERT(arg->fType.kind() == Type::kVector_Kind);
196 ASSERT(arg->fKind == Expression::kConstructor_Kind);
197 return &((Constructor&) *arg).getVecComponent(targetIndex - currentIndex);
198 }
199 }
200 currentIndex += arg->fType.columns();
201 }
202 ABORT("can't happen, matrix component out of bounds");
203 }
204
Ethan Nicholas86a43402017-01-19 13:32:00 -0500205 std::vector<std::unique_ptr<Expression>> fArguments;
ethannicholasb3058bd2016-07-01 08:22:01 -0700206
207 typedef Expression INHERITED;
208};
209
210} // namespace
211
212#endif