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_SWIZZLE 9 #define SKSL_SWIZZLE 10 11 #include "SkSLConstructor.h" 12 #include "SkSLContext.h" 13 #include "SkSLExpression.h" 14 #include "SkSLIRGenerator.h" 15 #include "SkSLUtil.h" 16 17 namespace SkSL { 18 19 /** 20 * Given a type and a swizzle component count, returns the type that will result from swizzling. For 21 * instance, swizzling a vec3 with two components will result in a vec2. It is possible to swizzle 22 * with more components than the source vector, as in 'vec2(1).xxxx'. 23 */ 24 static const Type& get_type(const Context& context, Expression& value, size_t count) { 25 const Type& base = value.fType.componentType(); 26 if (count == 1) { 27 return base; 28 } 29 if (base == *context.fFloat_Type) { 30 switch (count) { 31 case 2: return *context.fVec2_Type; 32 case 3: return *context.fVec3_Type; 33 case 4: return *context.fVec4_Type; 34 } 35 } else if (base == *context.fDouble_Type) { 36 switch (count) { 37 case 2: return *context.fDVec2_Type; 38 case 3: return *context.fDVec3_Type; 39 case 4: return *context.fDVec4_Type; 40 } 41 } else if (base == *context.fInt_Type) { 42 switch (count) { 43 case 2: return *context.fIVec2_Type; 44 case 3: return *context.fIVec3_Type; 45 case 4: return *context.fIVec4_Type; 46 } 47 } else if (base == *context.fUInt_Type) { 48 switch (count) { 49 case 2: return *context.fUVec2_Type; 50 case 3: return *context.fUVec3_Type; 51 case 4: return *context.fUVec4_Type; 52 } 53 } else if (base == *context.fBool_Type) { 54 switch (count) { 55 case 2: return *context.fBVec2_Type; 56 case 3: return *context.fBVec3_Type; 57 case 4: return *context.fBVec4_Type; 58 } 59 } 60 ABORT("cannot swizzle %s\n", value.description().c_str()); 61 } 62 63 /** 64 * Represents a vector swizzle operation such as 'vec2(1, 2, 3).zyx'. 65 */ 66 struct Swizzle : public Expression { 67 Swizzle(const Context& context, std::unique_ptr<Expression> base, std::vector<int> components) 68 : INHERITED(base->fPosition, kSwizzle_Kind, get_type(context, *base, components.size())) 69 , fBase(std::move(base)) 70 , fComponents(std::move(components)) { 71 ASSERT(fComponents.size() >= 1 && fComponents.size() <= 4); 72 } 73 74 std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator, 75 const DefinitionMap& definitions) override { 76 if (fBase->fKind == Expression::kConstructor_Kind && fBase->isConstant()) { 77 // we're swizzling a constant vector, e.g. vec4(1).x. Simplify it. 78 ASSERT(fBase->fKind == Expression::kConstructor_Kind); 79 if (fType == *irGenerator.fContext.fInt_Type) { 80 ASSERT(fComponents.size() == 1); 81 int64_t value = ((Constructor&) *fBase).getIVecComponent(fComponents[0]); 82 return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext, 83 Position(), 84 value)); 85 } else if (fType == *irGenerator.fContext.fFloat_Type) { 86 ASSERT(fComponents.size() == 1); 87 double value = ((Constructor&) *fBase).getFVecComponent(fComponents[0]); 88 return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext, 89 Position(), 90 value)); 91 } 92 } 93 return nullptr; 94 } 95 96 bool hasSideEffects() const override { 97 return fBase->hasSideEffects(); 98 } 99 100 String description() const override { 101 String result = fBase->description() + "."; 102 for (int x : fComponents) { 103 result += "xyzw"[x]; 104 } 105 return result; 106 } 107 108 std::unique_ptr<Expression> fBase; 109 const std::vector<int> fComponents; 110 111 typedef Expression INHERITED; 112 }; 113 114 } // namespace 115 116 #endif 117