1 /*
2 * Copyright 2020 Google LLC
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_DSL_TYPE
9 #define SKSL_DSL_TYPE
10
11 #include "include/sksl/DSLExpression.h"
12 #include "include/sksl/DSLModifiers.h"
13
14 #include <cstdint>
15
16 namespace SkSL {
17
18 class Type;
19
20 namespace dsl {
21
22 class DSLExpression;
23 class DSLField;
24
25 enum TypeConstant : uint8_t {
26 kBool_Type,
27 kBool2_Type,
28 kBool3_Type,
29 kBool4_Type,
30 kHalf_Type,
31 kHalf2_Type,
32 kHalf3_Type,
33 kHalf4_Type,
34 kHalf2x2_Type,
35 kHalf3x2_Type,
36 kHalf4x2_Type,
37 kHalf2x3_Type,
38 kHalf3x3_Type,
39 kHalf4x3_Type,
40 kHalf2x4_Type,
41 kHalf3x4_Type,
42 kHalf4x4_Type,
43 kFloat_Type,
44 kFloat2_Type,
45 kFloat3_Type,
46 kFloat4_Type,
47 kFragmentProcessor_Type,
48 kFloat2x2_Type,
49 kFloat3x2_Type,
50 kFloat4x2_Type,
51 kFloat2x3_Type,
52 kFloat3x3_Type,
53 kFloat4x3_Type,
54 kFloat2x4_Type,
55 kFloat3x4_Type,
56 kFloat4x4_Type,
57 kInt_Type,
58 kInt2_Type,
59 kInt3_Type,
60 kInt4_Type,
61 kShader_Type,
62 kShort_Type,
63 kShort2_Type,
64 kShort3_Type,
65 kShort4_Type,
66 kUInt_Type,
67 kUInt2_Type,
68 kUInt3_Type,
69 kUInt4_Type,
70 kUShort_Type,
71 kUShort2_Type,
72 kUShort3_Type,
73 kUShort4_Type,
74 kVoid_Type,
75 };
76
77 class DSLType {
78 public:
DSLType(TypeConstant tc)79 DSLType(TypeConstant tc)
80 : fTypeConstant(tc) {}
81
DSLType(const SkSL::Type * type)82 DSLType(const SkSL::Type* type)
83 : fSkSLType(type) {}
84
85 /**
86 * Returns true if this type is a bool.
87 */
88 bool isBoolean() const;
89
90 /**
91 * Returns true if this is a numeric scalar type.
92 */
93 bool isNumber() const;
94
95 /**
96 * Returns true if this is a floating-point scalar type (float or half).
97 */
98 bool isFloat() const;
99
100 /**
101 * Returns true if this is a signed scalar type (int or short).
102 */
103 bool isSigned() const;
104
105 /**
106 * Returns true if this is an unsigned scalar type (uint or ushort).
107 */
108 bool isUnsigned() const;
109
110 /**
111 * Returns true if this is a signed or unsigned integer.
112 */
113 bool isInteger() const;
114
115 /**
116 * Returns true if this is a scalar type.
117 */
118 bool isScalar() const;
119
120 /**
121 * Returns true if this is a vector type.
122 */
123 bool isVector() const;
124
125 /**
126 * Returns true if this is a matrix type.
127 */
128 bool isMatrix() const;
129
130 /**
131 * Returns true if this is a array type.
132 */
133 bool isArray() const;
134
135 /**
136 * Returns true if this is a struct type.
137 */
138 bool isStruct() const;
139
140 template<typename... Args>
Construct(DSLType type,Args &&...args)141 static DSLExpression Construct(DSLType type, Args&&... args) {
142 SkTArray<DSLExpression> argArray;
143 argArray.reserve_back(sizeof...(args));
144 CollectArgs(argArray, std::forward<Args>(args)...);
145 return Construct(type, std::move(argArray));
146 }
147
148 static DSLExpression Construct(DSLType type, SkTArray<DSLExpression> argArray);
149
150 private:
151 const SkSL::Type& skslType() const;
152
153 const SkSL::Type* fSkSLType = nullptr;
154
CollectArgs(SkTArray<DSLExpression> & args)155 static void CollectArgs(SkTArray<DSLExpression>& args) {}
156
157 template<class... RemainingArgs>
CollectArgs(SkTArray<DSLExpression> & args,DSLVar & var,RemainingArgs &&...remaining)158 static void CollectArgs(SkTArray<DSLExpression>& args, DSLVar& var,
159 RemainingArgs&&... remaining) {
160 args.push_back(var);
161 CollectArgs(args, std::forward<RemainingArgs>(remaining)...);
162 }
163
164 template<class... RemainingArgs>
CollectArgs(SkTArray<DSLExpression> & args,DSLExpression expr,RemainingArgs &&...remaining)165 static void CollectArgs(SkTArray<DSLExpression>& args, DSLExpression expr,
166 RemainingArgs&&... remaining) {
167 args.push_back(std::move(expr));
168 CollectArgs(args, std::forward<RemainingArgs>(remaining)...);
169 }
170
171 TypeConstant fTypeConstant;
172
173 friend DSLType Array(const DSLType& base, int count);
174 friend DSLType Struct(const char* name, SkTArray<DSLField> fields);
175 friend class DSLFunction;
176 friend class DSLVar;
177 friend class DSLWriter;
178 };
179
180 #define TYPE(T) \
181 template<typename... Args> \
182 DSLExpression T(Args&&... args) { \
183 return DSLType::Construct(k ## T ## _Type, std::forward<Args>(args)...); \
184 }
185
186 #define VECTOR_TYPE(T) \
187 TYPE(T) \
188 TYPE(T ## 2) \
189 TYPE(T ## 3) \
190 TYPE(T ## 4)
191
192 #define MATRIX_TYPE(T) \
193 TYPE(T ## 2x2) \
194 TYPE(T ## 3x2) \
195 TYPE(T ## 4x2) \
196 TYPE(T ## 2x3) \
197 TYPE(T ## 3x3) \
198 TYPE(T ## 4x3) \
199 TYPE(T ## 2x4) \
200 TYPE(T ## 3x4) \
201 TYPE(T ## 4x4)
202
203 VECTOR_TYPE(Bool)
204 VECTOR_TYPE(Float)
205 VECTOR_TYPE(Half)
206 VECTOR_TYPE(Int)
207 VECTOR_TYPE(UInt)
208 VECTOR_TYPE(Short)
209 VECTOR_TYPE(UShort)
210
211 MATRIX_TYPE(Float)
212 MATRIX_TYPE(Half)
213
214 #undef TYPE
215 #undef VECTOR_TYPE
216 #undef MATRIX_TYPE
217
218 DSLType Array(const DSLType& base, int count);
219
220 class DSLField {
221 public:
DSLField(const DSLType type,const char * name)222 DSLField(const DSLType type, const char* name)
223 : DSLField(DSLModifiers(), type, name) {}
224
225 private:
DSLField(DSLModifiers modifiers,const DSLType type,const char * name)226 DSLField(DSLModifiers modifiers, const DSLType type, const char* name)
227 : fModifiers(modifiers)
228 , fType(type)
229 , fName(name) {}
230
231 DSLModifiers fModifiers;
232 const DSLType fType;
233 const char* fName;
234
235 friend DSLType Struct(const char* name, SkTArray<DSLField> fields);
236 };
237
238 DSLType Struct(const char* name, SkTArray<DSLField> fields);
239
240 template<typename... Field>
Struct(const char * name,Field...fields)241 DSLType Struct(const char* name, Field... fields) {
242 SkTArray<DSLField> fieldTypes;
243 fieldTypes.reserve_back(sizeof...(fields));
244 // in C++17, we could just do:
245 // (fieldTypes.push_back(std::move(fields)), ...);
246 int unused[] = {0, (fieldTypes.push_back(std::move(fields)), 0)...};
247 static_cast<void>(unused);
248
249 return Struct(name, std::move(fieldTypes));
250 }
251
252 } // namespace dsl
253
254 } // namespace SkSL
255
256 #endif
257