blob: 32fc0fb2e77177f6a2176b04e05b0873a088c118 [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) {
Brian Salomon1d816b92017-08-17 11:07:59 -040035 if (fType == *irGenerator.fContext.fFloat_Type) {
Ethan Nicholascb670962017-04-20 19:31:52 -040036 // promote float(1) to 1.0
37 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
38 return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070039 fOffset,
Ethan Nicholascb670962017-04-20 19:31:52 -040040 intValue));
Brian Salomon1d816b92017-08-17 11:07:59 -040041 } else if (fType == *irGenerator.fContext.fUInt_Type) {
Ethan Nicholascb670962017-04-20 19:31:52 -040042 // promote uint(1) to 1u
43 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
44 return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070045 fOffset,
Ethan Nicholascb670962017-04-20 19:31:52 -040046 intValue,
47 &fType));
48 }
Ethan Nicholas86a43402017-01-19 13:32:00 -050049 }
50 return nullptr;
51 }
52
Ethan Nicholascb670962017-04-20 19:31:52 -040053 bool hasSideEffects() const override {
54 for (const auto& arg : fArguments) {
55 if (arg->hasSideEffects()) {
56 return true;
57 }
58 }
59 return false;
60 }
61
Ethan Nicholas0df1b042017-03-31 13:56:23 -040062 String description() const override {
63 String result = fType.description() + "(";
64 String separator;
ethannicholasb3058bd2016-07-01 08:22:01 -070065 for (size_t i = 0; i < fArguments.size(); i++) {
66 result += separator;
67 result += fArguments[i]->description();
68 separator = ", ";
69 }
70 result += ")";
71 return result;
72 }
73
74 bool isConstant() const override {
75 for (size_t i = 0; i < fArguments.size(); i++) {
76 if (!fArguments[i]->isConstant()) {
77 return false;
78 }
79 }
80 return true;
81 }
82
Ethan Nicholas3deaeb22017-04-25 14:42:11 -040083 bool compareConstant(const Context& context, const Expression& other) const override {
84 ASSERT(other.fKind == Expression::kConstructor_Kind && other.fType == fType);
85 Constructor& c = (Constructor&) other;
86 if (c.fType.kind() == Type::kVector_Kind) {
87 for (int i = 0; i < fType.columns(); i++) {
88 if (!this->getVecComponent(i).compareConstant(context, c.getVecComponent(i))) {
89 return false;
90 }
91 }
92 return true;
93 }
94 // shouldn't be possible to have a constant constructor that isn't a vector or matrix;
95 // a constant scalar constructor should have been collapsed down to the appropriate
96 // literal
97 ASSERT(fType.kind() == Type::kMatrix_Kind);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070098 const FloatLiteral fzero(context, -1, 0);
99 const IntLiteral izero(context, -1, 0);
Ethan Nicholas3deaeb22017-04-25 14:42:11 -0400100 const Expression* zero;
101 if (fType.componentType() == *context.fFloat_Type) {
102 zero = &fzero;
103 } else {
104 ASSERT(fType.componentType() == *context.fInt_Type);
105 zero = &izero;
106 }
107 for (int col = 0; col < fType.columns(); col++) {
108 for (int row = 0; row < fType.rows(); row++) {
109 const Expression* component1 = getMatComponent(col, row);
110 const Expression* component2 = c.getMatComponent(col, row);
111 if (!(component1 ? component1 : zero)->compareConstant(
112 context,
113 component2 ? *component2 : *zero)) {
114 return false;
115 }
116 }
117 }
118 return true;
119 }
120
Ethan Nicholascb670962017-04-20 19:31:52 -0400121 const Expression& getVecComponent(int index) const {
122 ASSERT(fType.kind() == Type::kVector_Kind);
123 if (fArguments.size() == 1 && fArguments[0]->fType.kind() == Type::kScalar_Kind) {
124 return *fArguments[0];
125 }
126 int current = 0;
127 for (const auto& arg : fArguments) {
128 ASSERT(current <= index);
129 if (arg->fType.kind() == Type::kScalar_Kind) {
130 if (index == current) {
131 return *arg;
132 }
133 current++;
134 } else {
135 ASSERT(arg->fType.kind() == Type::kVector_Kind);
136 ASSERT(arg->fKind == Expression::kConstructor_Kind);
137 if (current + arg->fType.columns() > index) {
138 return ((const Constructor&) *arg).getVecComponent(index - current);
139 }
140 current += arg->fType.columns();
141 }
142 }
143 ABORT("failed to find vector component %d in %s\n", index, description().c_str());
144 }
145
146 double getFVecComponent(int index) const {
147 const Expression& c = this->getVecComponent(index);
148 ASSERT(c.fKind == Expression::kFloatLiteral_Kind);
149 return ((FloatLiteral&) c).fValue;
150 }
151
152 int64_t getIVecComponent(int index) const {
153 const Expression& c = this->getVecComponent(index);
154 ASSERT(c.fKind == Expression::kIntLiteral_Kind);
155 return ((IntLiteral&) c).fValue;
156 }
157
Ethan Nicholas3deaeb22017-04-25 14:42:11 -0400158 // null return should be interpreted as zero
159 const Expression* getMatComponent(int col, int row) const {
160 ASSERT(this->isConstant());
161 ASSERT(fType.kind() == Type::kMatrix_Kind);
162 ASSERT(col < fType.columns() && row < fType.rows());
163 if (fArguments.size() == 1) {
164 if (fArguments[0]->fType.kind() == Type::kScalar_Kind) {
165 // single scalar argument, so matrix is of the form:
166 // x 0 0
167 // 0 x 0
168 // 0 0 x
169 // return x if col == row
170 return col == row ? fArguments[0].get() : nullptr;
171 }
172 if (fArguments[0]->fType.kind() == Type::kMatrix_Kind) {
173 ASSERT(fArguments[0]->fKind == Expression::kConstructor_Kind);
174 // single matrix argument. make sure we're within the argument's bounds.
175 const Type& argType = ((Constructor&) *fArguments[0]).fType;
176 if (col < argType.columns() && row < argType.rows()) {
177 // within bounds, defer to argument
178 return ((Constructor&) *fArguments[0]).getMatComponent(col, row);
179 }
180 // out of bounds, return 0
181 return nullptr;
182 }
183 }
184 int currentIndex = 0;
185 int targetIndex = col * fType.rows() + row;
186 for (const auto& arg : fArguments) {
187 ASSERT(targetIndex >= currentIndex);
188 ASSERT(arg->fType.rows() == 1);
189 if (currentIndex + arg->fType.columns() > targetIndex) {
190 if (arg->fType.columns() == 1) {
191 return arg.get();
192 } else {
193 ASSERT(arg->fType.kind() == Type::kVector_Kind);
194 ASSERT(arg->fKind == Expression::kConstructor_Kind);
195 return &((Constructor&) *arg).getVecComponent(targetIndex - currentIndex);
196 }
197 }
198 currentIndex += arg->fType.columns();
199 }
200 ABORT("can't happen, matrix component out of bounds");
201 }
202
Ethan Nicholas86a43402017-01-19 13:32:00 -0500203 std::vector<std::unique_ptr<Expression>> fArguments;
ethannicholasb3058bd2016-07-01 08:22:01 -0700204
205 typedef Expression INHERITED;
206};
207
208} // namespace
209
210#endif