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 "src/sksl/SkSLContext.h"
12 #include "src/sksl/SkSLIRGenerator.h"
13 #include "src/sksl/SkSLUtil.h"
14 #include "src/sksl/ir/SkSLConstructor.h"
15 #include "src/sksl/ir/SkSLExpression.h"
16 
17 namespace SkSL {
18 
19 /**
20  * Represents a vector swizzle operation such as 'float2(1, 2, 3).zyx'.
21  */
22 struct Swizzle final : public Expression {
23     static constexpr Kind kExpressionKind = Kind::kSwizzle;
24 
Swizzlefinal25     Swizzle(const Context& context, std::unique_ptr<Expression> base,
26             const ComponentArray& components)
27             : INHERITED(base->fOffset, kExpressionKind,
28                         &base->type().componentType().toCompound(context, components.size(), 1))
29             , fBase(std::move(base))
30             , fComponents(components) {
31         SkASSERT(this->components().size() >= 1 && this->components().size() <= 4);
32     }
33 
basefinal34     std::unique_ptr<Expression>& base() {
35         return fBase;
36     }
37 
basefinal38     const std::unique_ptr<Expression>& base() const {
39         return fBase;
40     }
41 
componentsfinal42     const ComponentArray& components() const {
43         return fComponents;
44     }
45 
constantPropagatefinal46     std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
47                                                   const DefinitionMap& definitions) override {
48         if (this->base()->is<Constructor>()) {
49             Constructor& constructor = this->base()->as<Constructor>();
50             if (constructor.isCompileTimeConstant()) {
51                 // we're swizzling a constant vector, e.g. float4(1).x. Simplify it.
52                 const Type& type = this->type();
53                 if (type.isInteger()) {
54                     SkASSERT(this->components().size() == 1);
55                     int64_t value = constructor.getIVecComponent(this->components()[0]);
56                     return std::make_unique<IntLiteral>(irGenerator.fContext, constructor.fOffset,
57                                                         value);
58                 } else if (type.isFloat()) {
59                     SkASSERT(this->components().size() == 1);
60                     SKSL_FLOAT value = constructor.getFVecComponent(this->components()[0]);
61                     return std::make_unique<FloatLiteral>(irGenerator.fContext, constructor.fOffset,
62                                                           value);
63                 }
64             }
65         }
66         return nullptr;
67     }
68 
hasPropertyfinal69     bool hasProperty(Property property) const override {
70         return this->base()->hasProperty(property);
71     }
72 
clonefinal73     std::unique_ptr<Expression> clone() const override {
74         return std::unique_ptr<Expression>(new Swizzle(&this->type(), this->base()->clone(),
75                                                        this->components()));
76     }
77 
descriptionfinal78     String description() const override {
79         String result = this->base()->description() + ".";
80         for (int x : this->components()) {
81             result += "xyzw"[x];
82         }
83         return result;
84     }
85 
86 private:
Swizzlefinal87     Swizzle(const Type* type, std::unique_ptr<Expression> base, const ComponentArray& components)
88         : INHERITED(base->fOffset, kExpressionKind, type)
89         , fBase(std::move(base))
90         , fComponents(components) {
91         SkASSERT(this->components().size() >= 1 && this->components().size() <= 4);
92     }
93 
94     std::unique_ptr<Expression> fBase;
95     ComponentArray fComponents;
96 
97     using INHERITED = Expression;
98 };
99 
100 }  // namespace SkSL
101 
102 #endif
103