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.isFloat()) { 36 // promote float(1) to 1.0 37 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue; 38 return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext, 39 fOffset, 40 intValue)); 41 } else if (fType.isInteger()) { 42 // promote uint(1) to 1u 43 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue; 44 return std::unique_ptr<Expression>(new IntLiteral(fOffset, 45 intValue, 46 &fType)); 47 } 48 } 49 return nullptr; 50 } 51 hasSideEffectsConstructor52 bool hasSideEffects() const override { 53 for (const auto& arg : fArguments) { 54 if (arg->hasSideEffects()) { 55 return true; 56 } 57 } 58 return false; 59 } 60 cloneConstructor61 std::unique_ptr<Expression> clone() const override { 62 std::vector<std::unique_ptr<Expression>> cloned; 63 for (const auto& arg : fArguments) { 64 cloned.push_back(arg->clone()); 65 } 66 return std::unique_ptr<Expression>(new Constructor(fOffset, fType, std::move(cloned))); 67 } 68 descriptionConstructor69 String description() const override { 70 String result = fType.description() + "("; 71 String separator; 72 for (size_t i = 0; i < fArguments.size(); i++) { 73 result += separator; 74 result += fArguments[i]->description(); 75 separator = ", "; 76 } 77 result += ")"; 78 return result; 79 } 80 isConstantConstructor81 bool isConstant() const override { 82 for (size_t i = 0; i < fArguments.size(); i++) { 83 if (!fArguments[i]->isConstant()) { 84 return false; 85 } 86 } 87 return true; 88 } 89 compareConstantConstructor90 bool compareConstant(const Context& context, const Expression& other) const override { 91 SkASSERT(other.fKind == Expression::kConstructor_Kind && other.fType == fType); 92 Constructor& c = (Constructor&) other; 93 if (c.fType.kind() == Type::kVector_Kind) { 94 for (int i = 0; i < fType.columns(); i++) { 95 if (!this->getVecComponent(i).compareConstant(context, c.getVecComponent(i))) { 96 return false; 97 } 98 } 99 return true; 100 } 101 // shouldn't be possible to have a constant constructor that isn't a vector or matrix; 102 // a constant scalar constructor should have been collapsed down to the appropriate 103 // literal 104 SkASSERT(fType.kind() == Type::kMatrix_Kind); 105 const FloatLiteral fzero(context, -1, 0); 106 const IntLiteral izero(context, -1, 0); 107 const Expression* zero; 108 if (fType.componentType().isFloat()) { 109 zero = &fzero; 110 } else { 111 SkASSERT(fType.componentType().isInteger()); 112 zero = &izero; 113 } 114 for (int col = 0; col < fType.columns(); col++) { 115 for (int row = 0; row < fType.rows(); row++) { 116 const Expression* component1 = getMatComponent(col, row); 117 const Expression* component2 = c.getMatComponent(col, row); 118 if (!(component1 ? component1 : zero)->compareConstant( 119 context, 120 component2 ? *component2 : *zero)) { 121 return false; 122 } 123 } 124 } 125 return true; 126 } 127 getVecComponentConstructor128 const Expression& getVecComponent(int index) const { 129 SkASSERT(fType.kind() == Type::kVector_Kind); 130 if (fArguments.size() == 1 && fArguments[0]->fType.kind() == Type::kScalar_Kind) { 131 return *fArguments[0]; 132 } 133 int current = 0; 134 for (const auto& arg : fArguments) { 135 SkASSERT(current <= index); 136 if (arg->fType.kind() == Type::kScalar_Kind) { 137 if (index == current) { 138 return *arg; 139 } 140 current++; 141 } else { 142 SkASSERT(arg->fType.kind() == Type::kVector_Kind); 143 SkASSERT(arg->fKind == Expression::kConstructor_Kind); 144 if (current + arg->fType.columns() > index) { 145 return ((const Constructor&) *arg).getVecComponent(index - current); 146 } 147 current += arg->fType.columns(); 148 } 149 } 150 ABORT("failed to find vector component %d in %s\n", index, description().c_str()); 151 } 152 getFVecComponentConstructor153 double getFVecComponent(int index) const { 154 return this->getVecComponent(index).getConstantFloat(); 155 } 156 getIVecComponentConstructor157 int64_t getIVecComponent(int index) const { 158 return this->getVecComponent(index).getConstantInt(); 159 } 160 161 // null return should be interpreted as zero getMatComponentConstructor162 const Expression* getMatComponent(int col, int row) const { 163 SkASSERT(this->isConstant()); 164 SkASSERT(fType.kind() == Type::kMatrix_Kind); 165 SkASSERT(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 SkASSERT(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 SkASSERT(targetIndex >= currentIndex); 191 SkASSERT(arg->fType.rows() == 1); 192 if (currentIndex + arg->fType.columns() > targetIndex) { 193 if (arg->fType.columns() == 1) { 194 return arg.get(); 195 } else { 196 SkASSERT(arg->fType.kind() == Type::kVector_Kind); 197 SkASSERT(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 206 std::vector<std::unique_ptr<Expression>> fArguments; 207 208 typedef Expression INHERITED; 209 }; 210 211 } // namespace 212 213 #endif 214