blob: 8f963e68eb0ad0488ab7d851bb2965ecaec9dd5c [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 Nicholas5af9ea32017-07-28 15:19:46 -040019 * Represents the construction of a compound type, such as "float2x, 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 {
Greg Daniel64773e62016-11-22 09:44:03 -050028 Constructor(Position position, const Type& type,
ethannicholasb3058bd2016-07-01 08:22:01 -070029 std::vector<std::unique_ptr<Expression>> arguments)
ethannicholasd598f792016-07-25 10:08:54 -070030 : INHERITED(position, kConstructor_Kind, type)
ethannicholasb3058bd2016-07-01 08:22:01 -070031 , fArguments(std::move(arguments)) {}
32
Ethan Nicholascb670962017-04-20 19:31:52 -040033 std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
34 const DefinitionMap& definitions) override {
35 if (fArguments.size() == 1 && fArguments[0]->fKind == Expression::kIntLiteral_Kind) {
Ethan Nicholas88d99c62017-08-16 16:41:30 -040036 if (fType == *irGenerator.fContext.fFloat_Type ||
37 fType == *irGenerator.fContext.fHalf_Type) {
Ethan Nicholascb670962017-04-20 19:31:52 -040038 // promote float(1) to 1.0
39 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
40 return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext,
41 fPosition,
42 intValue));
Ethan Nicholas88d99c62017-08-16 16:41:30 -040043 } else if (fType == *irGenerator.fContext.fUInt_Type ||
44 fType == *irGenerator.fContext.fUShort_Type) {
Ethan Nicholascb670962017-04-20 19:31:52 -040045 // promote uint(1) to 1u
46 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
47 return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
48 fPosition,
49 intValue,
50 &fType));
51 }
Ethan Nicholas86a43402017-01-19 13:32:00 -050052 }
53 return nullptr;
54 }
55
Ethan Nicholascb670962017-04-20 19:31:52 -040056 bool hasSideEffects() const override {
57 for (const auto& arg : fArguments) {
58 if (arg->hasSideEffects()) {
59 return true;
60 }
61 }
62 return false;
63 }
64
Ethan Nicholas0df1b042017-03-31 13:56:23 -040065 String description() const override {
66 String result = fType.description() + "(";
67 String separator;
ethannicholasb3058bd2016-07-01 08:22:01 -070068 for (size_t i = 0; i < fArguments.size(); i++) {
69 result += separator;
70 result += fArguments[i]->description();
71 separator = ", ";
72 }
73 result += ")";
74 return result;
75 }
76
77 bool isConstant() const override {
78 for (size_t i = 0; i < fArguments.size(); i++) {
79 if (!fArguments[i]->isConstant()) {
80 return false;
81 }
82 }
83 return true;
84 }
85
Ethan Nicholas3deaeb22017-04-25 14:42:11 -040086 bool compareConstant(const Context& context, const Expression& other) const override {
87 ASSERT(other.fKind == Expression::kConstructor_Kind && other.fType == fType);
88 Constructor& c = (Constructor&) other;
89 if (c.fType.kind() == Type::kVector_Kind) {
90 for (int i = 0; i < fType.columns(); i++) {
91 if (!this->getVecComponent(i).compareConstant(context, c.getVecComponent(i))) {
92 return false;
93 }
94 }
95 return true;
96 }
97 // shouldn't be possible to have a constant constructor that isn't a vector or matrix;
98 // a constant scalar constructor should have been collapsed down to the appropriate
99 // literal
100 ASSERT(fType.kind() == Type::kMatrix_Kind);
101 const FloatLiteral fzero(context, Position(), 0);
102 const IntLiteral izero(context, Position(), 0);
103 const Expression* zero;
104 if (fType.componentType() == *context.fFloat_Type) {
105 zero = &fzero;
106 } else {
107 ASSERT(fType.componentType() == *context.fInt_Type);
108 zero = &izero;
109 }
110 for (int col = 0; col < fType.columns(); col++) {
111 for (int row = 0; row < fType.rows(); row++) {
112 const Expression* component1 = getMatComponent(col, row);
113 const Expression* component2 = c.getMatComponent(col, row);
114 if (!(component1 ? component1 : zero)->compareConstant(
115 context,
116 component2 ? *component2 : *zero)) {
117 return false;
118 }
119 }
120 }
121 return true;
122 }
123
Ethan Nicholascb670962017-04-20 19:31:52 -0400124 const Expression& getVecComponent(int index) const {
125 ASSERT(fType.kind() == Type::kVector_Kind);
126 if (fArguments.size() == 1 && fArguments[0]->fType.kind() == Type::kScalar_Kind) {
127 return *fArguments[0];
128 }
129 int current = 0;
130 for (const auto& arg : fArguments) {
131 ASSERT(current <= index);
132 if (arg->fType.kind() == Type::kScalar_Kind) {
133 if (index == current) {
134 return *arg;
135 }
136 current++;
137 } else {
138 ASSERT(arg->fType.kind() == Type::kVector_Kind);
139 ASSERT(arg->fKind == Expression::kConstructor_Kind);
140 if (current + arg->fType.columns() > index) {
141 return ((const Constructor&) *arg).getVecComponent(index - current);
142 }
143 current += arg->fType.columns();
144 }
145 }
146 ABORT("failed to find vector component %d in %s\n", index, description().c_str());
147 }
148
149 double getFVecComponent(int index) const {
150 const Expression& c = this->getVecComponent(index);
151 ASSERT(c.fKind == Expression::kFloatLiteral_Kind);
152 return ((FloatLiteral&) c).fValue;
153 }
154
155 int64_t getIVecComponent(int index) const {
156 const Expression& c = this->getVecComponent(index);
157 ASSERT(c.fKind == Expression::kIntLiteral_Kind);
158 return ((IntLiteral&) c).fValue;
159 }
160
Ethan Nicholas3deaeb22017-04-25 14:42:11 -0400161 // null return should be interpreted as zero
162 const Expression* getMatComponent(int col, int row) const {
163 ASSERT(this->isConstant());
164 ASSERT(fType.kind() == Type::kMatrix_Kind);
165 ASSERT(col < fType.columns() && row < fType.rows());
166 if (fArguments.size() == 1) {
167 if (fArguments[0]->fType.kind() == Type::kScalar_Kind) {
168 // single scalar argument, so matrix is of the form:
169 // x 0 0
170 // 0 x 0
171 // 0 0 x
172 // return x if col == row
173 return col == row ? fArguments[0].get() : nullptr;
174 }
175 if (fArguments[0]->fType.kind() == Type::kMatrix_Kind) {
176 ASSERT(fArguments[0]->fKind == Expression::kConstructor_Kind);
177 // single matrix argument. make sure we're within the argument's bounds.
178 const Type& argType = ((Constructor&) *fArguments[0]).fType;
179 if (col < argType.columns() && row < argType.rows()) {
180 // within bounds, defer to argument
181 return ((Constructor&) *fArguments[0]).getMatComponent(col, row);
182 }
183 // out of bounds, return 0
184 return nullptr;
185 }
186 }
187 int currentIndex = 0;
188 int targetIndex = col * fType.rows() + row;
189 for (const auto& arg : fArguments) {
190 ASSERT(targetIndex >= currentIndex);
191 ASSERT(arg->fType.rows() == 1);
192 if (currentIndex + arg->fType.columns() > targetIndex) {
193 if (arg->fType.columns() == 1) {
194 return arg.get();
195 } else {
196 ASSERT(arg->fType.kind() == Type::kVector_Kind);
197 ASSERT(arg->fKind == Expression::kConstructor_Kind);
198 return &((Constructor&) *arg).getVecComponent(targetIndex - currentIndex);
199 }
200 }
201 currentIndex += arg->fType.columns();
202 }
203 ABORT("can't happen, matrix component out of bounds");
204 }
205
Ethan Nicholas86a43402017-01-19 13:32:00 -0500206 std::vector<std::unique_ptr<Expression>> fArguments;
ethannicholasb3058bd2016-07-01 08:22:01 -0700207
208 typedef Expression INHERITED;
209};
210
211} // namespace
212
213#endif