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