1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2023 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLBuiltinTypes.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLContext.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLConstructorCompound.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLExpression.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLIndexExpression.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLSwizzle.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLType.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/transform/SkSLTransform.h"
16*c8dee2aaSAndroid Build Coastguard Worker
17*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
18*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
19*c8dee2aaSAndroid Build Coastguard Worker
20*c8dee2aaSAndroid Build Coastguard Worker namespace SkSL {
21*c8dee2aaSAndroid Build Coastguard Worker
RewriteIndexedSwizzle(const Context & context,const IndexExpression & indexExpr)22*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Expression> Transform::RewriteIndexedSwizzle(const Context& context,
23*c8dee2aaSAndroid Build Coastguard Worker const IndexExpression& indexExpr) {
24*c8dee2aaSAndroid Build Coastguard Worker // The index expression _must_ have a swizzle base for this transformation to be valid.
25*c8dee2aaSAndroid Build Coastguard Worker if (!indexExpr.base()->is<Swizzle>()) {
26*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
27*c8dee2aaSAndroid Build Coastguard Worker }
28*c8dee2aaSAndroid Build Coastguard Worker const Swizzle& swizzle = indexExpr.base()->as<Swizzle>();
29*c8dee2aaSAndroid Build Coastguard Worker
30*c8dee2aaSAndroid Build Coastguard Worker // Convert the swizzle components to a literal array.
31*c8dee2aaSAndroid Build Coastguard Worker double vecArray[4];
32*c8dee2aaSAndroid Build Coastguard Worker for (int index = 0; index < swizzle.components().size(); ++index) {
33*c8dee2aaSAndroid Build Coastguard Worker vecArray[index] = swizzle.components()[index];
34*c8dee2aaSAndroid Build Coastguard Worker }
35*c8dee2aaSAndroid Build Coastguard Worker
36*c8dee2aaSAndroid Build Coastguard Worker // Make a compound constructor with the literal array.
37*c8dee2aaSAndroid Build Coastguard Worker const Type& vecType =
38*c8dee2aaSAndroid Build Coastguard Worker context.fTypes.fInt->toCompound(context, swizzle.components().size(), /*rows=*/1);
39*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Expression> vec =
40*c8dee2aaSAndroid Build Coastguard Worker ConstructorCompound::MakeFromConstants(context, indexExpr.fPosition, vecType, vecArray);
41*c8dee2aaSAndroid Build Coastguard Worker
42*c8dee2aaSAndroid Build Coastguard Worker // Create a rewritten inner-expression corresponding to `vec(1,2,3)[originalIndex]`.
43*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Expression> innerExpr = IndexExpression::Make(
44*c8dee2aaSAndroid Build Coastguard Worker context, indexExpr.fPosition, std::move(vec), indexExpr.index()->clone());
45*c8dee2aaSAndroid Build Coastguard Worker
46*c8dee2aaSAndroid Build Coastguard Worker // Return a rewritten outer-expression corresponding to `base[vec(1,2,3)[originalIndex]]`.
47*c8dee2aaSAndroid Build Coastguard Worker return IndexExpression::Make(
48*c8dee2aaSAndroid Build Coastguard Worker context, indexExpr.fPosition, swizzle.base()->clone(), std::move(innerExpr));
49*c8dee2aaSAndroid Build Coastguard Worker }
50*c8dee2aaSAndroid Build Coastguard Worker
51*c8dee2aaSAndroid Build Coastguard Worker } // namespace SkSL
52