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_CORE
9 #define SKSL_DSL_CORE
10 
11 #include "include/private/SkSLProgramKind.h"
12 #include "include/private/SkTArray.h"
13 #include "include/sksl/DSLBlock.h"
14 #include "include/sksl/DSLCase.h"
15 #include "include/sksl/DSLErrorHandling.h"
16 #include "include/sksl/DSLExpression.h"
17 #include "include/sksl/DSLFunction.h"
18 #include "include/sksl/DSLStatement.h"
19 #include "include/sksl/DSLType.h"
20 #include "include/sksl/DSLVar.h"
21 #include "include/sksl/DSLWrapper.h"
22 
23 namespace SkSL {
24 
25 class Compiler;
26 
27 namespace dsl {
28 
29 // When users import the DSL namespace via `using namespace SkSL::dsl`, we want the SwizzleComponent
30 // Type enum to come into scope as well, so `Swizzle(var, X, Y, ONE)` can work as expected.
31 // `namespace SkSL::SwizzleComponent` contains only an `enum Type`; this `using namespace` directive
32 // shouldn't pollute the SkSL::dsl namespace with anything else.
33 using namespace SkSL::SwizzleComponent;
34 
35 enum DSLFlag {
36     kNo_Flag               = 0,
37     kMangle_Flag           = 1 << 0,
38     kOptimize_Flag         = 1 << 1,
39     kValidate_Flag         = 1 << 2,
40     kMarkVarsDeclared_Flag = 1 << 3,
41 };
42 
43 constexpr int kDefaultDSLFlags = kMangle_Flag | kOptimize_Flag | kValidate_Flag;
44 
45 /**
46  * Starts DSL output on the current thread using the specified compiler. This must be called
47  * prior to any other DSL functions.
48  */
49 void Start(SkSL::Compiler* compiler, SkSL::ProgramKind kind = SkSL::ProgramKind::kFragment,
50            int flags = kDefaultDSLFlags);
51 
52 /**
53  * Signals the end of DSL output. This must be called sometime between a call to Start() and the
54  * termination of the thread.
55  */
56 void End();
57 
58 /**
59  * Installs an ErrorHandler which will be notified of any errors that occur during DSL calls. If
60  * no ErrorHandler is installed, any errors will be fatal.
61  */
62 void SetErrorHandler(ErrorHandler* errorHandler);
63 
64 DSLVar sk_FragColor();
65 
66 DSLVar sk_FragCoord();
67 
68 /**
69  * break;
70  */
71 DSLStatement Break();
72 
73 /**
74  * continue;
75  */
76 DSLStatement Continue();
77 
78 /**
79  * Creates a variable declaration statement.
80  */
81 DSLStatement Declare(DSLVar& var, PositionInfo pos = PositionInfo());
82 
83 /**
84  * Declares a global variable.
85  */
86 void DeclareGlobal(DSLVar& var, PositionInfo pos = PositionInfo());
87 
88 /**
89  * default: statements
90  */
91 template<class... Statements>
Default(Statements...statements)92 DSLCase Default(Statements... statements) {
93     return DSLCase(DSLExpression(), std::move(statements)...);
94 }
95 
96 /**
97  * discard;
98  */
99 DSLStatement Discard();
100 
101 /**
102  * do stmt; while (test);
103  */
104 DSLStatement Do(DSLStatement stmt, DSLExpression test, PositionInfo pos = PositionInfo());
105 
106 /**
107  * for (initializer; test; next) stmt;
108  */
109 DSLStatement For(DSLStatement initializer, DSLExpression test, DSLExpression next,
110                  DSLStatement stmt, PositionInfo pos = PositionInfo());
111 
112 /**
113  * if (test) ifTrue; [else ifFalse;]
114  */
115 DSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse = DSLStatement(),
116                 PositionInfo pos = PositionInfo());
117 
118 /**
119  * return [value];
120  */
121 DSLStatement Return(DSLExpression value = DSLExpression(), PositionInfo pos = PositionInfo());
122 
123 /**
124  * test ? ifTrue : ifFalse
125  */
126 DSLExpression Select(DSLExpression test, DSLExpression ifTrue, DSLExpression ifFalse,
127                      PositionInfo info = PositionInfo());
128 
129 DSLStatement StaticIf(DSLExpression test, DSLStatement ifTrue,
130                       DSLStatement ifFalse = DSLStatement(), PositionInfo pos = PositionInfo());
131 
132 DSLPossibleStatement StaticSwitch(DSLExpression value, SkTArray<DSLCase> cases);
133 
134 /**
135  * @switch (value) { cases }
136  */
137 template<class... Cases>
StaticSwitch(DSLExpression value,Cases...cases)138 DSLPossibleStatement StaticSwitch(DSLExpression value, Cases... cases) {
139     SkTArray<DSLCase> caseArray;
140     caseArray.reserve_back(sizeof...(cases));
141     (caseArray.push_back(std::move(cases)), ...);
142     return StaticSwitch(std::move(value), std::move(caseArray));
143 }
144 
145 DSLPossibleStatement Switch(DSLExpression value, SkTArray<DSLCase> cases);
146 
147 /**
148  * switch (value) { cases }
149  */
150 template<class... Cases>
Switch(DSLExpression value,Cases...cases)151 DSLPossibleStatement Switch(DSLExpression value, Cases... cases) {
152     SkTArray<DSLCase> caseArray;
153     caseArray.reserve_back(sizeof...(cases));
154     (caseArray.push_back(std::move(cases)), ...);
155     return Switch(std::move(value), std::move(caseArray));
156 }
157 
158 /**
159  * while (test) stmt;
160  */
161 DSLStatement While(DSLExpression test, DSLStatement stmt, PositionInfo info = PositionInfo());
162 
163 /**
164  * expression.xyz1
165  */
166 DSLExpression Swizzle(DSLExpression base,
167                       SkSL::SwizzleComponent::Type a,
168                       PositionInfo pos = PositionInfo());
169 
170 DSLExpression Swizzle(DSLExpression base,
171                       SkSL::SwizzleComponent::Type a,
172                       SkSL::SwizzleComponent::Type b,
173                       PositionInfo pos = PositionInfo());
174 
175 DSLExpression Swizzle(DSLExpression base,
176                       SkSL::SwizzleComponent::Type a,
177                       SkSL::SwizzleComponent::Type b,
178                       SkSL::SwizzleComponent::Type c,
179                       PositionInfo pos = PositionInfo());
180 
181 DSLExpression Swizzle(DSLExpression base,
182                       SkSL::SwizzleComponent::Type a,
183                       SkSL::SwizzleComponent::Type b,
184                       SkSL::SwizzleComponent::Type c,
185                       SkSL::SwizzleComponent::Type d,
186                       PositionInfo pos = PositionInfo());
187 
188 /**
189  * Returns the absolute value of x. If x is a vector, operates componentwise.
190  */
191 DSLExpression Abs(DSLExpression x, PositionInfo pos = PositionInfo());
192 
193 /**
194  * Returns true if all of the components of boolean vector x are true.
195  */
196 DSLExpression All(DSLExpression x, PositionInfo pos = PositionInfo());
197 
198 /**
199  * Returns true if any of the components of boolean vector x are true.
200  */
201 DSLExpression Any(DSLExpression x, PositionInfo pos = PositionInfo());
202 
203 /**
204  * Returns the arctangent of y over x. Operates componentwise on vectors.
205  */
206 DSLExpression Atan(DSLExpression y_over_x, PositionInfo pos = PositionInfo());
207 DSLExpression Atan(DSLExpression y, DSLExpression x, PositionInfo pos = PositionInfo());
208 
209 /**
210  * Returns x rounded towards positive infinity. If x is a vector, operates componentwise.
211  */
212 DSLExpression Ceil(DSLExpression x, PositionInfo pos = PositionInfo());
213 
214 /**
215  * Returns x clamped to between min and max. If x is a vector, operates componentwise.
216  */
217 DSLExpression Clamp(DSLExpression x, DSLExpression min, DSLExpression max,
218                     PositionInfo pos = PositionInfo());
219 
220 /**
221  * Returns the cosine of x. If x is a vector, operates componentwise.
222  */
223 DSLExpression Cos(DSLExpression x, PositionInfo pos = PositionInfo());
224 
225 /**
226  * Returns the cross product of x and y.
227  */
228 DSLExpression Cross(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
229 
230 /**
231  * Returns x converted from radians to degrees. If x is a vector, operates componentwise.
232  */
233 DSLExpression Degrees(DSLExpression x, PositionInfo pos = PositionInfo());
234 
235 /**
236  * Returns the distance between x and y.
237  */
238 DSLExpression Distance(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
239 
240 /**
241  * Returns the dot product of x and y.
242  */
243 DSLExpression Dot(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
244 
245 /**
246  * Returns a boolean vector indicating whether components of x are equal to the corresponding
247  * components of y.
248  */
249 DSLExpression Equal(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
250 
251 /**
252  * Returns e^x. If x is a vector, operates componentwise.
253  */
254 DSLExpression Exp(DSLExpression x, PositionInfo pos = PositionInfo());
255 
256 /**
257  * Returns 2^x. If x is a vector, operates componentwise.
258  */
259 DSLExpression Exp2(DSLExpression x, PositionInfo pos = PositionInfo());
260 
261 /**
262  * If dot(i, nref) >= 0, returns n, otherwise returns -n.
263  */
264 DSLExpression Faceforward(DSLExpression n, DSLExpression i, DSLExpression nref,
265                           PositionInfo pos = PositionInfo());
266 
267 /**
268  * Returns x rounded towards negative infinity. If x is a vector, operates componentwise.
269  */
270 DSLExpression Floor(DSLExpression x, PositionInfo pos = PositionInfo());
271 
272 /**
273  * Returns the fractional part of x. If x is a vector, operates componentwise.
274  */
275 DSLExpression Fract(DSLExpression x, PositionInfo pos = PositionInfo());
276 
277 /**
278  * Returns a boolean vector indicating whether components of x are greater than the corresponding
279  * components of y.
280  */
281 DSLExpression GreaterThan(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
282 
283 /**
284  * Returns a boolean vector indicating whether components of x are greater than or equal to the
285  * corresponding components of y.
286  */
287 DSLExpression GreaterThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
288 
289 /**
290  * Returns the 1/sqrt(x). If x is a vector, operates componentwise.
291  */
292 DSLExpression Inversesqrt(DSLExpression x, PositionInfo pos = PositionInfo());
293 
294 /**
295  * Returns the inverse of the matrix x.
296  */
297 DSLExpression Inverse(DSLExpression x, PositionInfo pos = PositionInfo());
298 
299 /**
300  * Returns the length of the vector x.
301  */
302 DSLExpression Length(DSLExpression x, PositionInfo pos = PositionInfo());
303 
304 /**
305  * Returns a boolean vector indicating whether components of x are less than the corresponding
306  * components of y.
307  */
308 DSLExpression LessThan(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
309 
310 /**
311  * Returns a boolean vector indicating whether components of x are less than or equal to the
312  * corresponding components of y.
313  */
314 DSLExpression LessThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
315 
316 /**
317  * Returns the log base e of x. If x is a vector, operates componentwise.
318  */
319 DSLExpression Log(DSLExpression x, PositionInfo pos = PositionInfo());
320 
321 /**
322  * Returns the log base 2 of x. If x is a vector, operates componentwise.
323  */
324 DSLExpression Log2(DSLExpression x, PositionInfo pos = PositionInfo());
325 
326 /**
327  * Returns the larger (closer to positive infinity) of x and y. If x is a vector, operates
328  * componentwise. y may be either a vector of the same dimensions as x, or a scalar.
329  */
330 DSLExpression Max(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
331 
332 /**
333  * Returns the smaller (closer to negative infinity) of x and y. If x is a vector, operates
334  * componentwise. y may be either a vector of the same dimensions as x, or a scalar.
335  */
336 DSLExpression Min(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
337 
338 /**
339  * Returns a linear intepolation between x and y at position a, where a=0 results in x and a=1
340  * results in y. If x and y are vectors, operates componentwise. a may be either a vector of the
341  * same dimensions as x and y, or a scalar.
342  */
343 DSLExpression Mix(DSLExpression x, DSLExpression y, DSLExpression a,
344                   PositionInfo pos = PositionInfo());
345 
346 /**
347  * Returns x modulo y. If x is a vector, operates componentwise. y may be either a vector of the
348  * same dimensions as x, or a scalar.
349  */
350 DSLExpression Mod(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
351 
352 /**
353  * Returns the vector x normalized to a length of 1.
354  */
355 DSLExpression Normalize(DSLExpression x, PositionInfo pos = PositionInfo());
356 
357 /**
358  * Returns a boolean vector indicating whether components of x are not equal to the corresponding
359  * components of y.
360  */
361 DSLExpression NotEqual(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
362 
363 /**
364  * Returns x raised to the power y. If x is a vector, operates componentwise. y may be either a
365  * vector of the same dimensions as x, or a scalar.
366  */
367 DSLExpression Pow(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
368 
369 /**
370  * Returns x converted from degrees to radians. If x is a vector, operates componentwise.
371  */
372 DSLExpression Radians(DSLExpression x, PositionInfo pos = PositionInfo());
373 
374 /**
375  * Returns i reflected from a surface with normal n.
376  */
377 DSLExpression Reflect(DSLExpression i, DSLExpression n, PositionInfo pos = PositionInfo());
378 
379 /**
380  * Returns i refracted across a surface with normal n and ratio of indices of refraction eta.
381  */
382 DSLExpression Refract(DSLExpression i, DSLExpression n, DSLExpression eta,
383                       PositionInfo pos = PositionInfo());
384 
385 /**
386  * Samples the child processor at the current coordinates.
387  */
388 DSLExpression Sample(DSLExpression fp, PositionInfo pos = PositionInfo());
389 
390 /**
391  * Implements the following functions:
392  *     half4 sample(fragmentProcessor fp, float2 coords);
393  *     half4 sample(fragmentProcessor fp, half4 input);
394  */
395 DSLExpression Sample(DSLExpression target, DSLExpression x, PositionInfo pos = PositionInfo());
396 
397 /**
398  * Implements the following functions:
399  *     half4 sample(fragmentProcessor fp, float2 coords, half4 input);
400  */
401 DSLExpression Sample(DSLExpression childProcessor, DSLExpression x, DSLExpression y,
402                      PositionInfo pos = PositionInfo());
403 
404 /**
405  * Returns x clamped to the range [0, 1]. If x is a vector, operates componentwise.
406  */
407 DSLExpression Saturate(DSLExpression x, PositionInfo pos = PositionInfo());
408 
409 /**
410  * Returns -1, 0, or 1 depending on whether x is negative, zero, or positive, respectively. If x is
411  * a vector, operates componentwise.
412  */
413 DSLExpression Sign(DSLExpression x, PositionInfo pos = PositionInfo());
414 
415 /**
416  * Returns the sine of x. If x is a vector, operates componentwise.
417  */
418 DSLExpression Sin(DSLExpression x, PositionInfo pos = PositionInfo());
419 
420 /**
421  * Returns a smooth interpolation between 0 (at x=edge1) and 1 (at x=edge2). If x is a vector,
422  * operates componentwise. edge1 and edge2 may either be both vectors of the same dimensions as x or
423  * scalars.
424  */
425 DSLExpression Smoothstep(DSLExpression edge1, DSLExpression edge2, DSLExpression x,
426                          PositionInfo pos = PositionInfo());
427 
428 /**
429  * Returns the square root of x. If x is a vector, operates componentwise.
430  */
431 DSLExpression Sqrt(DSLExpression x, PositionInfo pos = PositionInfo());
432 
433 /**
434  * Returns 0 if x < edge or 1 if x >= edge. If x is a vector, operates componentwise. edge may be
435  * either a vector of the same dimensions as x, or a scalar.
436  */
437 DSLExpression Step(DSLExpression edge, DSLExpression x, PositionInfo pos = PositionInfo());
438 
439 /**
440  * Returns the tangent of x. If x is a vector, operates componentwise.
441  */
442 DSLExpression Tan(DSLExpression x, PositionInfo pos = PositionInfo());
443 
444 /**
445  * Returns x converted from premultipled to unpremultiplied alpha.
446  */
447 DSLExpression Unpremul(DSLExpression x, PositionInfo pos = PositionInfo());
448 
449 } // namespace dsl
450 
451 } // namespace SkSL
452 
453 #endif
454