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 "include/private/SkSLDefines.h"
12 #include "src/sksl/SkSLContext.h"
13 #include "src/sksl/SkSLIRGenerator.h"
14 #include "src/sksl/SkSLUtil.h"
15 #include "src/sksl/ir/SkSLConstructor.h"
16 #include "src/sksl/ir/SkSLExpression.h"
17 
18 namespace SkSL {
19 
20 /**
21  * Represents a vector swizzle operation such as 'float3(1, 2, 3).zyx'.
22  */
23 struct Swizzle final : public Expression {
24     static constexpr Kind kExpressionKind = Kind::kSwizzle;
25 
Swizzlefinal26     Swizzle(const Context& context, std::unique_ptr<Expression> base,
27             const ComponentArray& components)
28             : INHERITED(base->fOffset, kExpressionKind,
29                         &base->type().componentType().toCompound(context, components.size(), 1))
30             , fBase(std::move(base))
31             , fComponents(components) {
32         SkASSERT(this->components().size() >= 1 && this->components().size() <= 4);
33     }
34 
35     // Swizzle::Convert permits component arrays containing ZERO or ONE, does typechecking, reports
36     // errors via ErrorReporter, and returns an expression that combines constructors and native
37     // swizzles (comprised solely of X/Y/W/Z).
38     static std::unique_ptr<Expression> Convert(const Context& context,
39                                                std::unique_ptr<Expression> base,
40                                                ComponentArray inComponents);
41 
42     // Swizzle::Make does not permit ZERO or ONE in the component array, just X/Y/Z/W; errors are
43     // reported via ASSERT.
44     static std::unique_ptr<Expression> Make(const Context& context,
45                                             std::unique_ptr<Expression> expr,
46                                             ComponentArray inComponents);
47 
basefinal48     std::unique_ptr<Expression>& base() {
49         return fBase;
50     }
51 
basefinal52     const std::unique_ptr<Expression>& base() const {
53         return fBase;
54     }
55 
componentsfinal56     const ComponentArray& components() const {
57         return fComponents;
58     }
59 
hasPropertyfinal60     bool hasProperty(Property property) const override {
61         return this->base()->hasProperty(property);
62     }
63 
clonefinal64     std::unique_ptr<Expression> clone() const override {
65         return std::unique_ptr<Expression>(new Swizzle(&this->type(), this->base()->clone(),
66                                                        this->components()));
67     }
68 
descriptionfinal69     String description() const override {
70         String result = this->base()->description() + ".";
71         for (int x : this->components()) {
72             result += "xyzw"[x];
73         }
74         return result;
75     }
76 
77 private:
Swizzlefinal78     Swizzle(const Type* type, std::unique_ptr<Expression> base, const ComponentArray& components)
79         : INHERITED(base->fOffset, kExpressionKind, type)
80         , fBase(std::move(base))
81         , fComponents(components) {
82         SkASSERT(this->components().size() >= 1 && this->components().size() <= 4);
83     }
84 
85     std::unique_ptr<Expression> fBase;
86     ComponentArray fComponents;
87 
88     using INHERITED = Expression;
89 };
90 
91 }  // namespace SkSL
92 
93 #endif
94