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