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 "src/sksl/SkSLIRGenerator.h" 12 #include "src/sksl/ir/SkSLExpression.h" 13 #include "src/sksl/ir/SkSLFloatLiteral.h" 14 #include "src/sksl/ir/SkSLIntLiteral.h" 15 #include "src/sksl/ir/SkSLPrefixExpression.h" 16 17 namespace SkSL { 18 19 /** 20 * Represents the construction of a compound type, such as "float2(x, y)". 21 * 22 * Vector constructors will always consist of either exactly 1 scalar, or a collection of vectors 23 * and scalars totalling exactly the right number of scalar components. 24 * 25 * Matrix constructors will always consist of either exactly 1 scalar, exactly 1 matrix, or a 26 * collection of vectors and scalars totalling exactly the right number of scalar components. 27 */ 28 struct Constructor : public Expression { ConstructorConstructor29 Constructor(int offset, const Type& type, std::vector<std::unique_ptr<Expression>> arguments) 30 : INHERITED(offset, kConstructor_Kind, type) 31 , fArguments(std::move(arguments)) {} 32 constantPropagateConstructor33 std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator, 34 const DefinitionMap& definitions) override { 35 if (fArguments.size() == 1 && fArguments[0]->fKind == Expression::kIntLiteral_Kind) { 36 if (fType.isFloat()) { 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.isInteger()) { 43 // promote uint(1) to 1u 44 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue; 45 return std::unique_ptr<Expression>(new IntLiteral(fOffset, 46 intValue, 47 &fType)); 48 } 49 } 50 return nullptr; 51 } 52 hasSideEffectsConstructor53 bool hasSideEffects() const override { 54 for (const auto& arg : fArguments) { 55 if (arg->hasSideEffects()) { 56 return true; 57 } 58 } 59 return false; 60 } 61 cloneConstructor62 std::unique_ptr<Expression> clone() const override { 63 std::vector<std::unique_ptr<Expression>> cloned; 64 for (const auto& arg : fArguments) { 65 cloned.push_back(arg->clone()); 66 } 67 return std::unique_ptr<Expression>(new Constructor(fOffset, fType, std::move(cloned))); 68 } 69 descriptionConstructor70 String description() const override { 71 String result = fType.description() + "("; 72 String separator; 73 for (size_t i = 0; i < fArguments.size(); i++) { 74 result += separator; 75 result += fArguments[i]->description(); 76 separator = ", "; 77 } 78 result += ")"; 79 return result; 80 } 81 isConstantConstructor82 bool isConstant() const override { 83 for (size_t i = 0; i < fArguments.size(); i++) { 84 if (!fArguments[i]->isConstant()) { 85 return false; 86 } 87 } 88 return true; 89 } 90 compareConstantConstructor91 bool compareConstant(const Context& context, const Expression& other) const override { 92 SkASSERT(other.fKind == Expression::kConstructor_Kind && other.fType == fType); 93 Constructor& c = (Constructor&) other; 94 if (c.fType.kind() == Type::kVector_Kind) { 95 bool isFloat = c.fType.columns() > 1 ? c.fType.componentType().isFloat() 96 : c.fType.isFloat(); 97 for (int i = 0; i < fType.columns(); i++) { 98 if (isFloat) { 99 if (this->getFVecComponent(i) != c.getFVecComponent(i)) { 100 return false; 101 } 102 } else if (this->getIVecComponent(i) != c.getIVecComponent(i)) { 103 return false; 104 } 105 } 106 return true; 107 } 108 // shouldn't be possible to have a constant constructor that isn't a vector or matrix; 109 // a constant scalar constructor should have been collapsed down to the appropriate 110 // literal 111 SkASSERT(fType.kind() == Type::kMatrix_Kind); 112 for (int col = 0; col < fType.columns(); col++) { 113 for (int row = 0; row < fType.rows(); row++) { 114 if (getMatComponent(col, row) != c.getMatComponent(col, row)) { 115 return false; 116 } 117 } 118 } 119 return true; 120 } 121 122 template<typename type> getVecComponentConstructor123 type getVecComponent(int index) const { 124 SkASSERT(fType.kind() == Type::kVector_Kind); 125 if (fArguments.size() == 1 && fArguments[0]->fType.kind() == Type::kScalar_Kind) { 126 if (std::is_floating_point<type>::value) { 127 return fArguments[0]->getConstantFloat(); 128 } else { 129 return fArguments[0]->getConstantInt(); 130 } 131 } 132 int current = 0; 133 for (const auto& arg : fArguments) { 134 SkASSERT(current <= index); 135 if (arg->fType.kind() == Type::kScalar_Kind) { 136 if (index == current) { 137 if (std::is_floating_point<type>::value) { 138 return arg.get()->getConstantFloat(); 139 } else { 140 return arg.get()->getConstantInt(); 141 } 142 } 143 current++; 144 } else if (arg->fKind == kConstructor_Kind) { 145 if (current + arg->fType.columns() > index) { 146 return ((const Constructor&) *arg).getVecComponent<type>(index - current); 147 } 148 current += arg->fType.columns(); 149 } else { 150 if (current + arg->fType.columns() > index) { 151 SkASSERT(arg->fKind == kPrefix_Kind); 152 const PrefixExpression& p = (PrefixExpression&) *arg; 153 const Constructor& c = (const Constructor&) *p.fOperand; 154 return -c.getVecComponent<type>(index - current); 155 } 156 current += arg->fType.columns(); 157 } 158 } 159 ABORT("failed to find vector component %d in %s\n", index, description().c_str()); 160 } 161 getFVecComponentConstructor162 SKSL_FLOAT getFVecComponent(int n) const override { 163 return this->getVecComponent<SKSL_FLOAT>(n); 164 } 165 166 /** 167 * For a literal vector expression, return the integer value of the n'th vector component. It is 168 * an error to call this method on an expression which is not a literal vector. 169 */ getIVecComponentConstructor170 SKSL_INT getIVecComponent(int n) const override { 171 return this->getVecComponent<SKSL_INT>(n); 172 } 173 getMatComponentConstructor174 SKSL_FLOAT getMatComponent(int col, int row) const override { 175 SkASSERT(this->isConstant()); 176 SkASSERT(fType.kind() == Type::kMatrix_Kind); 177 SkASSERT(col < fType.columns() && row < fType.rows()); 178 if (fArguments.size() == 1) { 179 if (fArguments[0]->fType.kind() == Type::kScalar_Kind) { 180 // single scalar argument, so matrix is of the form: 181 // x 0 0 182 // 0 x 0 183 // 0 0 x 184 // return x if col == row 185 return col == row ? fArguments[0]->getConstantFloat() : 0.0; 186 } 187 if (fArguments[0]->fType.kind() == Type::kMatrix_Kind) { 188 SkASSERT(fArguments[0]->fKind == Expression::kConstructor_Kind); 189 // single matrix argument. make sure we're within the argument's bounds. 190 const Type& argType = ((Constructor&) *fArguments[0]).fType; 191 if (col < argType.columns() && row < argType.rows()) { 192 // within bounds, defer to argument 193 return ((Constructor&) *fArguments[0]).getMatComponent(col, row); 194 } 195 // out of bounds 196 return 0.0; 197 } 198 } 199 int currentIndex = 0; 200 int targetIndex = col * fType.rows() + row; 201 for (const auto& arg : fArguments) { 202 SkASSERT(targetIndex >= currentIndex); 203 SkASSERT(arg->fType.rows() == 1); 204 if (currentIndex + arg->fType.columns() > targetIndex) { 205 if (arg->fType.columns() == 1) { 206 return arg->getConstantFloat(); 207 } else { 208 return arg->getFVecComponent(targetIndex - currentIndex); 209 } 210 } 211 currentIndex += arg->fType.columns(); 212 } 213 ABORT("can't happen, matrix component out of bounds"); 214 } 215 216 std::vector<std::unique_ptr<Expression>> fArguments; 217 218 typedef Expression INHERITED; 219 }; 220 221 } // namespace 222 223 #endif 224