• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "include/sksl/DSLCore.h"
9 
10 #include "include/private/SkSLDefines.h"
11 #include "include/sksl/DSLSymbols.h"
12 #include "include/sksl/DSLVar.h"
13 #include "src/sksl/SkSLCompiler.h"
14 #include "src/sksl/SkSLThreadContext.h"
15 #include "src/sksl/dsl/priv/DSLWriter.h"
16 #include "src/sksl/ir/SkSLBlock.h"
17 #include "src/sksl/ir/SkSLBreakStatement.h"
18 #include "src/sksl/ir/SkSLContinueStatement.h"
19 #include "src/sksl/ir/SkSLDiscardStatement.h"
20 #include "src/sksl/ir/SkSLDoStatement.h"
21 #include "src/sksl/ir/SkSLExtension.h"
22 #include "src/sksl/ir/SkSLField.h"
23 #include "src/sksl/ir/SkSLForStatement.h"
24 #include "src/sksl/ir/SkSLFunctionCall.h"
25 #include "src/sksl/ir/SkSLIfStatement.h"
26 #include "src/sksl/ir/SkSLInterfaceBlock.h"
27 #include "src/sksl/ir/SkSLModifiersDeclaration.h"
28 #include "src/sksl/ir/SkSLReturnStatement.h"
29 #include "src/sksl/ir/SkSLStructDefinition.h"
30 #include "src/sksl/ir/SkSLSwitchStatement.h"
31 #include "src/sksl/ir/SkSLSwizzle.h"
32 #include "src/sksl/ir/SkSLTernaryExpression.h"
33 #include "src/sksl/transform/SkSLTransform.h"
34 
35 namespace SkSL {
36 
37 namespace dsl {
38 
Start(SkSL::Compiler * compiler,ProgramKind kind)39 void Start(SkSL::Compiler* compiler, ProgramKind kind) {
40     Start(compiler, kind, ProgramSettings());
41 }
42 
Start(SkSL::Compiler * compiler,ProgramKind kind,const ProgramSettings & settings)43 void Start(SkSL::Compiler* compiler, ProgramKind kind, const ProgramSettings& settings) {
44     ThreadContext::SetInstance(std::make_unique<ThreadContext>(compiler, kind, settings,
45             compiler->moduleForProgramKind(kind), /*isModule=*/false));
46 }
47 
StartModule(SkSL::Compiler * compiler,ProgramKind kind,const ProgramSettings & settings,SkSL::ParsedModule baseModule)48 void StartModule(SkSL::Compiler* compiler, ProgramKind kind, const ProgramSettings& settings,
49                  SkSL::ParsedModule baseModule) {
50     ThreadContext::SetInstance(std::make_unique<ThreadContext>(compiler, kind, settings,
51             baseModule, /*isModule=*/true));
52 }
53 
End()54 void End() {
55     SkASSERTF(!ThreadContext::InFragmentProcessor(),
56               "more calls to StartFragmentProcessor than to EndFragmentProcessor");
57     ThreadContext::SetInstance(nullptr);
58 }
59 
GetErrorReporter()60 ErrorReporter& GetErrorReporter() {
61     return ThreadContext::GetErrorReporter();
62 }
63 
SetErrorReporter(ErrorReporter * errorReporter)64 void SetErrorReporter(ErrorReporter* errorReporter) {
65     SkASSERT(errorReporter);
66     ThreadContext::SetErrorReporter(errorReporter);
67 }
68 
69 class DSLCore {
70 public:
ReleaseProgram(std::unique_ptr<std::string> source)71     static std::unique_ptr<SkSL::Program> ReleaseProgram(std::unique_ptr<std::string> source) {
72         ThreadContext& instance = ThreadContext::Instance();
73         SkSL::Compiler& compiler = *instance.fCompiler;
74         const SkSL::Context& context = *compiler.fContext;
75         // Variables defined in the pre-includes need their declaring elements added to the program
76         if (!instance.fConfig->fIsBuiltinCode && context.fBuiltins) {
77             Transform::FindAndDeclareBuiltinVariables(context, instance.fConfig->fKind,
78                     instance.fSharedElements);
79         }
80         Pool* pool = instance.fPool.get();
81         auto result = std::make_unique<SkSL::Program>(std::move(source),
82                                                       std::move(instance.fConfig),
83                                                       compiler.fContext,
84                                                       std::move(instance.fProgramElements),
85                                                       std::move(instance.fSharedElements),
86                                                       std::move(instance.fModifiersPool),
87                                                       std::move(compiler.fSymbolTable),
88                                                       std::move(instance.fPool),
89                                                       instance.fInputs);
90         bool success = false;
91         if (!compiler.finalize(*result)) {
92             // Do not return programs that failed to compile.
93         } else if (!compiler.optimize(*result)) {
94             // Do not return programs that failed to optimize.
95         } else {
96             // We have a successful program!
97             success = true;
98         }
99         if (!success) {
100             ThreadContext::ReportErrors(PositionInfo());
101         }
102         if (pool) {
103             pool->detachFromThread();
104         }
105         SkASSERT(instance.fProgramElements.empty());
106         SkASSERT(!ThreadContext::SymbolTable());
107         return success ? std::move(result) : nullptr;
108     }
109 
sk_FragColor()110     static DSLGlobalVar sk_FragColor() {
111         return DSLGlobalVar("sk_FragColor");
112     }
113 
sk_FragCoord()114     static DSLGlobalVar sk_FragCoord() {
115         return DSLGlobalVar("sk_FragCoord");
116     }
117 
sk_Position()118     static DSLExpression sk_Position() {
119         return DSLExpression(Symbol("sk_Position"));
120     }
121 
122     template <typename... Args>
Call(const char * name,Args...args)123     static DSLPossibleExpression Call(const char* name, Args... args) {
124         SkSL::ExpressionArray argArray;
125         argArray.reserve_back(sizeof...(args));
126 
127         // in C++17, we could just do:
128         // (argArray.push_back(args.release()), ...);
129         int unused[] = {0, (static_cast<void>(argArray.push_back(args.release())), 0)...};
130         static_cast<void>(unused);
131 
132         return SkSL::FunctionCall::Convert(ThreadContext::Context(), /*line=*/-1,
133                 ThreadContext::Compiler().convertIdentifier(-1, name), std::move(argArray));
134     }
135 
Break(PositionInfo pos)136     static DSLStatement Break(PositionInfo pos) {
137         return SkSL::BreakStatement::Make(pos.line());
138     }
139 
Continue(PositionInfo pos)140     static DSLStatement Continue(PositionInfo pos) {
141         return SkSL::ContinueStatement::Make(pos.line());
142     }
143 
Declare(const DSLModifiers & modifiers)144     static void Declare(const DSLModifiers& modifiers) {
145         ThreadContext::ProgramElements().push_back(std::make_unique<SkSL::ModifiersDeclaration>(
146                 ThreadContext::Modifiers(modifiers.fModifiers)));
147     }
148 
Declare(DSLVar & var,PositionInfo pos)149     static DSLStatement Declare(DSLVar& var, PositionInfo pos) {
150         if (var.fDeclared) {
151             ThreadContext::ReportError("variable has already been declared", pos);
152         }
153         var.fDeclared = true;
154         return DSLWriter::Declaration(var);
155     }
156 
Declare(SkTArray<DSLVar> & vars,PositionInfo pos)157     static DSLStatement Declare(SkTArray<DSLVar>& vars, PositionInfo pos) {
158         StatementArray statements;
159         for (DSLVar& v : vars) {
160             statements.push_back(Declare(v, pos).release());
161         }
162         return SkSL::Block::MakeUnscoped(pos.line(), std::move(statements));
163     }
164 
Declare(DSLGlobalVar & var,PositionInfo pos)165     static void Declare(DSLGlobalVar& var, PositionInfo pos) {
166         if (var.fDeclared) {
167             ThreadContext::ReportError("variable has already been declared", pos);
168         }
169         var.fDeclared = true;
170         std::unique_ptr<SkSL::Statement> stmt = DSLWriter::Declaration(var);
171         if (stmt) {
172             if (!stmt->isEmpty()) {
173                 ThreadContext::ProgramElements().push_back(
174                         std::make_unique<SkSL::GlobalVarDeclaration>(std::move(stmt)));
175             }
176         } else if (var.fName == SkSL::Compiler::FRAGCOLOR_NAME) {
177             // sk_FragColor can end up with a null declaration despite no error occurring due to
178             // specific treatment in the compiler. Ignore the null and just grab the existing
179             // variable from the symbol table.
180             const SkSL::Symbol* alreadyDeclared = (*ThreadContext::SymbolTable())[var.fName];
181             if (alreadyDeclared && alreadyDeclared->is<Variable>()) {
182                 var.fVar = &alreadyDeclared->as<Variable>();
183                 var.fInitialized = true;
184             }
185         }
186     }
187 
Declare(SkTArray<DSLGlobalVar> & vars,PositionInfo pos)188     static void Declare(SkTArray<DSLGlobalVar>& vars, PositionInfo pos) {
189         for (DSLGlobalVar& v : vars) {
190             Declare(v, pos);
191         }
192     }
193 
Discard(PositionInfo pos)194     static DSLStatement Discard(PositionInfo pos) {
195         return SkSL::DiscardStatement::Make(pos.line());
196     }
197 
Do(DSLStatement stmt,DSLExpression test)198     static DSLPossibleStatement Do(DSLStatement stmt, DSLExpression test) {
199         return DoStatement::Convert(ThreadContext::Context(), stmt.release(), test.release());
200     }
201 
For(DSLStatement initializer,DSLExpression test,DSLExpression next,DSLStatement stmt,PositionInfo pos)202     static DSLPossibleStatement For(DSLStatement initializer, DSLExpression test,
203                                     DSLExpression next, DSLStatement stmt, PositionInfo pos) {
204         return ForStatement::Convert(ThreadContext::Context(), pos.line(),
205                                      initializer.releaseIfPossible(), test.releaseIfPossible(),
206                                      next.releaseIfPossible(), stmt.release(),
207                                      ThreadContext::SymbolTable());
208     }
209 
If(DSLExpression test,DSLStatement ifTrue,DSLStatement ifFalse,bool isStatic)210     static DSLPossibleStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse,
211                                    bool isStatic) {
212         return IfStatement::Convert(ThreadContext::Context(), /*line=*/-1, isStatic, test.release(),
213                                     ifTrue.release(), ifFalse.releaseIfPossible());
214     }
215 
FindRTAdjust(SkSL::InterfaceBlock & intf,PositionInfo pos)216     static void FindRTAdjust(SkSL::InterfaceBlock& intf, PositionInfo pos) {
217         const std::vector<SkSL::Type::Field>& fields =
218                 intf.variable().type().componentType().fields();
219         const Context& context = ThreadContext::Context();
220         for (size_t i = 0; i < fields.size(); ++i) {
221             const SkSL::Type::Field& f = fields[i];
222             if (f.fName == SkSL::Compiler::RTADJUST_NAME) {
223                 if (f.fType->matches(*context.fTypes.fFloat4)) {
224                     ThreadContext::RTAdjustData& rtAdjust = ThreadContext::RTAdjustState();
225                     rtAdjust.fInterfaceBlock = &intf.variable();
226                     rtAdjust.fFieldIndex = i;
227                 } else {
228                     ThreadContext::ReportError("sk_RTAdjust must have type 'float4'", pos);
229                 }
230                 break;
231             }
232         }
233     }
234 
InterfaceBlock(const DSLModifiers & modifiers,std::string_view typeName,SkTArray<DSLField> fields,std::string_view varName,int arraySize,PositionInfo pos)235     static DSLGlobalVar InterfaceBlock(const DSLModifiers& modifiers, std::string_view typeName,
236                                        SkTArray<DSLField> fields, std::string_view varName,
237                                        int arraySize, PositionInfo pos) {
238         // We need to create a new struct type for the interface block, but we don't want it in the
239         // symbol table. Since dsl::Struct automatically sticks it in the symbol table, we create it
240         // the old fashioned way with MakeStructType.
241         std::vector<SkSL::Type::Field> skslFields;
242         skslFields.reserve(fields.count());
243         for (const DSLField& field : fields) {
244             const SkSL::Type* baseType = &field.fType.skslType();
245             if (baseType->isArray()) {
246                 baseType = &baseType->componentType();
247             }
248             SkSL::VarDeclaration::ErrorCheck(ThreadContext::Context(), field.fPosition.line(),
249                     field.fModifiers.fModifiers, baseType, Variable::Storage::kInterfaceBlock);
250             GetErrorReporter().reportPendingErrors(field.fPosition);
251             skslFields.push_back(SkSL::Type::Field(field.fModifiers.fModifiers, field.fName,
252                                                    &field.fType.skslType()));
253         }
254         const SkSL::Type* structType =
255                 ThreadContext::SymbolTable()->takeOwnershipOfSymbol(SkSL::Type::MakeStructType(
256                         pos.line(), typeName, std::move(skslFields), /*interfaceBlock=*/true));
257         DSLType varType = arraySize > 0 ? Array(structType, arraySize) : DSLType(structType);
258         DSLGlobalVar var(modifiers, varType, !varName.empty() ? varName : typeName, DSLExpression(),
259                 pos);
260         // Interface blocks can't be declared, so we always need to mark the var declared ourselves.
261         // We do this only when fDSLMarkVarDeclared is false, so we don't double-declare it.
262         if (!ThreadContext::Settings().fDSLMarkVarsDeclared) {
263             DSLWriter::MarkDeclared(var);
264         }
265         const SkSL::Variable* skslVar = DSLWriter::Var(var);
266         if (skslVar) {
267             auto intf = std::make_unique<SkSL::InterfaceBlock>(pos.line(),
268                     *skslVar, typeName, varName, arraySize, ThreadContext::SymbolTable());
269             FindRTAdjust(*intf, pos);
270             ThreadContext::ProgramElements().push_back(std::move(intf));
271             if (varName.empty()) {
272                 const std::vector<SkSL::Type::Field>& structFields = structType->fields();
273                 for (size_t i = 0; i < structFields.size(); ++i) {
274                     ThreadContext::SymbolTable()->add(std::make_unique<SkSL::Field>(pos.line(),
275                                                                                     skslVar,
276                                                                                     i));
277                 }
278             } else {
279                 AddToSymbolTable(var);
280             }
281         }
282         GetErrorReporter().reportPendingErrors(pos);
283         return var;
284     }
285 
Return(DSLExpression value,PositionInfo pos)286     static DSLStatement Return(DSLExpression value, PositionInfo pos) {
287         // Note that because Return is called before the function in which it resides exists, at
288         // this point we do not know the function's return type. We therefore do not check for
289         // errors, or coerce the value to the correct type, until the return statement is actually
290         // added to a function. (This is done in FunctionDefinition::Convert.)
291         return SkSL::ReturnStatement::Make(pos.line(), value.releaseIfPossible());
292     }
293 
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,PositionInfo pos)294     static DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a,
295                                  PositionInfo pos) {
296         return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(),
297                                               ComponentArray{a}),
298                              pos);
299     }
300 
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,PositionInfo pos)301     static DSLExpression Swizzle(DSLExpression base,
302                                  SkSL::SwizzleComponent::Type a,
303                                  SkSL::SwizzleComponent::Type b,
304                                  PositionInfo pos) {
305         return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(),
306                                               ComponentArray{a, b}),
307                              pos);
308     }
309 
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,SkSL::SwizzleComponent::Type c,PositionInfo pos)310     static DSLExpression Swizzle(DSLExpression base,
311                                  SkSL::SwizzleComponent::Type a,
312                                  SkSL::SwizzleComponent::Type b,
313                                  SkSL::SwizzleComponent::Type c,
314                                  PositionInfo pos) {
315         return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(),
316                                               ComponentArray{a, b, c}),
317                              pos);
318     }
319 
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,SkSL::SwizzleComponent::Type c,SkSL::SwizzleComponent::Type d,PositionInfo pos)320     static DSLExpression Swizzle(DSLExpression base,
321                                  SkSL::SwizzleComponent::Type a,
322                                  SkSL::SwizzleComponent::Type b,
323                                  SkSL::SwizzleComponent::Type c,
324                                  SkSL::SwizzleComponent::Type d,
325                                  PositionInfo pos) {
326         return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(),
327                                               ComponentArray{a,b,c,d}),
328                              pos);
329     }
330 
Select(DSLExpression test,DSLExpression ifTrue,DSLExpression ifFalse)331     static DSLPossibleExpression Select(DSLExpression test, DSLExpression ifTrue,
332                                         DSLExpression ifFalse) {
333         return TernaryExpression::Convert(ThreadContext::Context(), test.release(),
334                                           ifTrue.release(), ifFalse.release());
335     }
336 
Switch(DSLExpression value,SkTArray<DSLCase> cases,bool isStatic)337     static DSLPossibleStatement Switch(DSLExpression value, SkTArray<DSLCase> cases,
338                                        bool isStatic) {
339         ExpressionArray values;
340         values.reserve_back(cases.count());
341         StatementArray caseBlocks;
342         caseBlocks.reserve_back(cases.count());
343         for (DSLCase& c : cases) {
344             values.push_back(c.fValue.releaseIfPossible());
345             caseBlocks.push_back(SkSL::Block::Make(/*line=*/-1,
346                     std::move(c.fStatements), /*symbols=*/nullptr, /*isScope=*/false));
347         }
348         return SwitchStatement::Convert(ThreadContext::Context(), /*line=*/-1, isStatic,
349                 value.release(), std::move(values), std::move(caseBlocks),
350                 ThreadContext::SymbolTable());
351     }
352 
While(DSLExpression test,DSLStatement stmt)353     static DSLPossibleStatement While(DSLExpression test, DSLStatement stmt) {
354         return ForStatement::ConvertWhile(ThreadContext::Context(), /*line=*/-1, test.release(),
355                                           stmt.release(), ThreadContext::SymbolTable());
356     }
357 };
358 
ReleaseProgram(std::unique_ptr<std::string> source)359 std::unique_ptr<SkSL::Program> ReleaseProgram(std::unique_ptr<std::string> source) {
360     return DSLCore::ReleaseProgram(std::move(source));
361 }
362 
sk_FragColor()363 DSLGlobalVar sk_FragColor() {
364     return DSLCore::sk_FragColor();
365 }
366 
sk_FragCoord()367 DSLGlobalVar sk_FragCoord() {
368     return DSLCore::sk_FragCoord();
369 }
370 
sk_Position()371 DSLExpression sk_Position() {
372     return DSLCore::sk_Position();
373 }
374 
AddExtension(std::string_view name,PositionInfo pos)375 void AddExtension(std::string_view name, PositionInfo pos) {
376     ThreadContext::ProgramElements().push_back(std::make_unique<SkSL::Extension>(pos.line(), name));
377     ThreadContext::ReportErrors(pos);
378 }
379 
Break(PositionInfo pos)380 DSLStatement Break(PositionInfo pos) {
381     return DSLCore::Break(pos);
382 }
383 
Continue(PositionInfo pos)384 DSLStatement Continue(PositionInfo pos) {
385     return DSLCore::Continue(pos);
386 }
387 
Declare(const DSLModifiers & modifiers,PositionInfo pos)388 void Declare(const DSLModifiers& modifiers, PositionInfo pos) {
389     SkSL::ProgramKind kind = ThreadContext::GetProgramConfig()->fKind;
390     if (kind != ProgramKind::kFragment &&
391         kind != ProgramKind::kVertex) {
392         ThreadContext::ReportError("layout qualifiers are not allowed in this kind of program",
393                 pos);
394         return;
395     }
396     DSLCore::Declare(modifiers);
397 }
398 
399 // Logically, we'd want the variable's initial value to appear on here in Declare, since that
400 // matches how we actually write code (and in fact that was what our first attempt looked like).
401 // Unfortunately, C++ doesn't guarantee execution order between arguments, and Declare() can appear
402 // as a function argument in constructs like Block(Declare(x, 0), foo(x)). If these are executed out
403 // of order, we will evaluate the reference to x before we evaluate Declare(x, 0), and thus the
404 // variable's initial value is unknown at the point of reference. There are probably some other
405 // issues with this as well, but it is particularly dangerous when x is const, since SkSL will
406 // expect its value to be known when it is referenced and will end up asserting, dereferencing a
407 // null pointer, or possibly doing something else awful.
408 //
409 // So, we put the initial value onto the Var itself instead of the Declare to guarantee that it is
410 // always executed in the correct order.
Declare(DSLVar & var,PositionInfo pos)411 DSLStatement Declare(DSLVar& var, PositionInfo pos) {
412     return DSLCore::Declare(var, pos);
413 }
414 
Declare(SkTArray<DSLVar> & vars,PositionInfo pos)415 DSLStatement Declare(SkTArray<DSLVar>& vars, PositionInfo pos) {
416     return DSLCore::Declare(vars, pos);
417 }
418 
Declare(DSLGlobalVar & var,PositionInfo pos)419 void Declare(DSLGlobalVar& var, PositionInfo pos) {
420     DSLCore::Declare(var, pos);
421 }
422 
Declare(SkTArray<DSLGlobalVar> & vars,PositionInfo pos)423 void Declare(SkTArray<DSLGlobalVar>& vars, PositionInfo pos) {
424     DSLCore::Declare(vars, pos);
425 }
426 
Discard(PositionInfo pos)427 DSLStatement Discard(PositionInfo pos) {
428     if (ThreadContext::GetProgramConfig()->fKind != ProgramKind::kFragment) {
429         ThreadContext::ReportError("discard statement is only permitted in fragment shaders", pos);
430     }
431     return DSLCore::Discard(pos);
432 }
433 
Do(DSLStatement stmt,DSLExpression test,PositionInfo pos)434 DSLStatement Do(DSLStatement stmt, DSLExpression test, PositionInfo pos) {
435     return DSLStatement(DSLCore::Do(std::move(stmt), std::move(test)), pos);
436 }
437 
For(DSLStatement initializer,DSLExpression test,DSLExpression next,DSLStatement stmt,PositionInfo pos)438 DSLStatement For(DSLStatement initializer, DSLExpression test, DSLExpression next,
439                  DSLStatement stmt, PositionInfo pos) {
440     return DSLStatement(DSLCore::For(std::move(initializer), std::move(test), std::move(next),
441                                      std::move(stmt), pos), pos);
442 }
443 
If(DSLExpression test,DSLStatement ifTrue,DSLStatement ifFalse,PositionInfo pos)444 DSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse, PositionInfo pos) {
445     return DSLStatement(DSLCore::If(std::move(test), std::move(ifTrue), std::move(ifFalse),
446                                     /*isStatic=*/false),
447                         pos);
448 }
449 
InterfaceBlock(const DSLModifiers & modifiers,std::string_view typeName,SkTArray<DSLField> fields,std::string_view varName,int arraySize,PositionInfo pos)450 DSLGlobalVar InterfaceBlock(const DSLModifiers& modifiers,  std::string_view typeName,
451                             SkTArray<DSLField> fields, std::string_view varName, int arraySize,
452                             PositionInfo pos) {
453     SkSL::ProgramKind kind = ThreadContext::GetProgramConfig()->fKind;
454     if (kind != ProgramKind::kFragment &&
455         kind != ProgramKind::kVertex) {
456         ThreadContext::ReportError("interface blocks are not allowed in this kind of program", pos);
457         return DSLGlobalVar();
458     }
459     return DSLCore::InterfaceBlock(modifiers, typeName, std::move(fields), varName, arraySize, pos);
460 }
461 
Return(DSLExpression expr,PositionInfo pos)462 DSLStatement Return(DSLExpression expr, PositionInfo pos) {
463     return DSLCore::Return(std::move(expr), pos);
464 }
465 
Select(DSLExpression test,DSLExpression ifTrue,DSLExpression ifFalse,PositionInfo pos)466 DSLExpression Select(DSLExpression test, DSLExpression ifTrue, DSLExpression ifFalse,
467                      PositionInfo pos) {
468     return DSLExpression(DSLCore::Select(std::move(test), std::move(ifTrue), std::move(ifFalse)),
469                          pos);
470 }
471 
StaticIf(DSLExpression test,DSLStatement ifTrue,DSLStatement ifFalse,PositionInfo pos)472 DSLStatement StaticIf(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse,
473                       PositionInfo pos) {
474     return DSLStatement(DSLCore::If(std::move(test), std::move(ifTrue), std::move(ifFalse),
475                                     /*isStatic=*/true),
476                          pos);
477 }
478 
PossibleStaticSwitch(DSLExpression value,SkTArray<DSLCase> cases)479 DSLPossibleStatement PossibleStaticSwitch(DSLExpression value, SkTArray<DSLCase> cases) {
480     return DSLCore::Switch(std::move(value), std::move(cases), /*isStatic=*/true);
481 }
482 
StaticSwitch(DSLExpression value,SkTArray<DSLCase> cases,PositionInfo pos)483 DSLStatement StaticSwitch(DSLExpression value, SkTArray<DSLCase> cases, PositionInfo pos) {
484     return DSLStatement(PossibleStaticSwitch(std::move(value), std::move(cases)), pos);
485 }
486 
PossibleSwitch(DSLExpression value,SkTArray<DSLCase> cases)487 DSLPossibleStatement PossibleSwitch(DSLExpression value, SkTArray<DSLCase> cases) {
488     return DSLCore::Switch(std::move(value), std::move(cases), /*isStatic=*/false);
489 }
490 
Switch(DSLExpression value,SkTArray<DSLCase> cases,PositionInfo pos)491 DSLStatement Switch(DSLExpression value, SkTArray<DSLCase> cases, PositionInfo pos) {
492     return DSLStatement(PossibleSwitch(std::move(value), std::move(cases)), pos);
493 }
494 
While(DSLExpression test,DSLStatement stmt,PositionInfo pos)495 DSLStatement While(DSLExpression test, DSLStatement stmt, PositionInfo pos) {
496     return DSLStatement(DSLCore::While(std::move(test), std::move(stmt)), pos);
497 }
498 
Abs(DSLExpression x,PositionInfo pos)499 DSLExpression Abs(DSLExpression x, PositionInfo pos) {
500     return DSLExpression(DSLCore::Call("abs", std::move(x)), pos);
501 }
502 
All(DSLExpression x,PositionInfo pos)503 DSLExpression All(DSLExpression x, PositionInfo pos) {
504     return DSLExpression(DSLCore::Call("all", std::move(x)), pos);
505 }
506 
Any(DSLExpression x,PositionInfo pos)507 DSLExpression Any(DSLExpression x, PositionInfo pos) {
508     return DSLExpression(DSLCore::Call("any", std::move(x)), pos);
509 }
510 
Atan(DSLExpression y_over_x,PositionInfo pos)511 DSLExpression Atan(DSLExpression y_over_x, PositionInfo pos) {
512     return DSLExpression(DSLCore::Call("atan", std::move(y_over_x)), pos);
513 }
514 
Atan(DSLExpression y,DSLExpression x,PositionInfo pos)515 DSLExpression Atan(DSLExpression y, DSLExpression x, PositionInfo pos) {
516     return DSLExpression(DSLCore::Call("atan", std::move(y), std::move(x)), pos);
517 }
518 
Ceil(DSLExpression x,PositionInfo pos)519 DSLExpression Ceil(DSLExpression x, PositionInfo pos) {
520     return DSLExpression(DSLCore::Call("ceil", std::move(x)), pos);
521 }
522 
Clamp(DSLExpression x,DSLExpression min,DSLExpression max,PositionInfo pos)523 DSLExpression Clamp(DSLExpression x, DSLExpression min, DSLExpression max, PositionInfo pos) {
524     return DSLExpression(DSLCore::Call("clamp", std::move(x), std::move(min), std::move(max)), pos);
525 }
526 
Cos(DSLExpression x,PositionInfo pos)527 DSLExpression Cos(DSLExpression x, PositionInfo pos) {
528     return DSLExpression(DSLCore::Call("cos", std::move(x)), pos);
529 }
530 
Cross(DSLExpression x,DSLExpression y,PositionInfo pos)531 DSLExpression Cross(DSLExpression x, DSLExpression y, PositionInfo pos) {
532     return DSLExpression(DSLCore::Call("cross", std::move(x), std::move(y)), pos);
533 }
534 
Degrees(DSLExpression x,PositionInfo pos)535 DSLExpression Degrees(DSLExpression x, PositionInfo pos) {
536     return DSLExpression(DSLCore::Call("degrees", std::move(x)), pos);
537 }
538 
Distance(DSLExpression x,DSLExpression y,PositionInfo pos)539 DSLExpression Distance(DSLExpression x, DSLExpression y, PositionInfo pos) {
540     return DSLExpression(DSLCore::Call("distance", std::move(x), std::move(y)), pos);
541 }
542 
Dot(DSLExpression x,DSLExpression y,PositionInfo pos)543 DSLExpression Dot(DSLExpression x, DSLExpression y, PositionInfo pos) {
544     return DSLExpression(DSLCore::Call("dot", std::move(x), std::move(y)), pos);
545 }
546 
Equal(DSLExpression x,DSLExpression y,PositionInfo pos)547 DSLExpression Equal(DSLExpression x, DSLExpression y, PositionInfo pos) {
548     return DSLExpression(DSLCore::Call("equal", std::move(x), std::move(y)), pos);
549 }
550 
Exp(DSLExpression x,PositionInfo pos)551 DSLExpression Exp(DSLExpression x, PositionInfo pos) {
552     return DSLExpression(DSLCore::Call("exp", std::move(x)), pos);
553 }
554 
Exp2(DSLExpression x,PositionInfo pos)555 DSLExpression Exp2(DSLExpression x, PositionInfo pos) {
556     return DSLExpression(DSLCore::Call("exp2", std::move(x)), pos);
557 }
558 
Faceforward(DSLExpression n,DSLExpression i,DSLExpression nref,PositionInfo pos)559 DSLExpression Faceforward(DSLExpression n, DSLExpression i, DSLExpression nref, PositionInfo pos) {
560     return DSLExpression(DSLCore::Call("faceforward", std::move(n), std::move(i), std::move(nref)),
561                          pos);
562 }
563 
Fract(DSLExpression x,PositionInfo pos)564 DSLExpression Fract(DSLExpression x, PositionInfo pos) {
565     return DSLExpression(DSLCore::Call("fract", std::move(x)), pos);
566 }
567 
Floor(DSLExpression x,PositionInfo pos)568 DSLExpression Floor(DSLExpression x, PositionInfo pos) {
569     return DSLExpression(DSLCore::Call("floor", std::move(x)), pos);
570 }
571 
GreaterThan(DSLExpression x,DSLExpression y,PositionInfo pos)572 DSLExpression GreaterThan(DSLExpression x, DSLExpression y, PositionInfo pos) {
573     return DSLExpression(DSLCore::Call("greaterThan", std::move(x), std::move(y)), pos);
574 }
575 
GreaterThanEqual(DSLExpression x,DSLExpression y,PositionInfo pos)576 DSLExpression GreaterThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos) {
577     return DSLExpression(DSLCore::Call("greaterThanEqual", std::move(x), std::move(y)), pos);
578 }
579 
Inverse(DSLExpression x,PositionInfo pos)580 DSLExpression Inverse(DSLExpression x, PositionInfo pos) {
581     return DSLExpression(DSLCore::Call("inverse", std::move(x)), pos);
582 }
583 
Inversesqrt(DSLExpression x,PositionInfo pos)584 DSLExpression Inversesqrt(DSLExpression x, PositionInfo pos) {
585     return DSLExpression(DSLCore::Call("inversesqrt", std::move(x)), pos);
586 }
587 
Length(DSLExpression x,PositionInfo pos)588 DSLExpression Length(DSLExpression x, PositionInfo pos) {
589     return DSLExpression(DSLCore::Call("length", std::move(x)), pos);
590 }
591 
LessThan(DSLExpression x,DSLExpression y,PositionInfo pos)592 DSLExpression LessThan(DSLExpression x, DSLExpression y, PositionInfo pos) {
593     return DSLExpression(DSLCore::Call("lessThan", std::move(x), std::move(y)), pos);
594 }
595 
LessThanEqual(DSLExpression x,DSLExpression y,PositionInfo pos)596 DSLExpression LessThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos) {
597     return DSLExpression(DSLCore::Call("lessThanEqual", std::move(x), std::move(y)), pos);
598 }
599 
Log(DSLExpression x,PositionInfo pos)600 DSLExpression Log(DSLExpression x, PositionInfo pos) {
601     return DSLExpression(DSLCore::Call("log", std::move(x)), pos);
602 }
603 
Log2(DSLExpression x,PositionInfo pos)604 DSLExpression Log2(DSLExpression x, PositionInfo pos) {
605     return DSLExpression(DSLCore::Call("log2", std::move(x)), pos);
606 }
607 
Max(DSLExpression x,DSLExpression y,PositionInfo pos)608 DSLExpression Max(DSLExpression x, DSLExpression y, PositionInfo pos) {
609     return DSLExpression(DSLCore::Call("max", std::move(x), std::move(y)), pos);
610 }
611 
Min(DSLExpression x,DSLExpression y,PositionInfo pos)612 DSLExpression Min(DSLExpression x, DSLExpression y, PositionInfo pos) {
613     return DSLExpression(DSLCore::Call("min", std::move(x), std::move(y)), pos);
614 }
615 
Mix(DSLExpression x,DSLExpression y,DSLExpression a,PositionInfo pos)616 DSLExpression Mix(DSLExpression x, DSLExpression y, DSLExpression a, PositionInfo pos) {
617     return DSLExpression(DSLCore::Call("mix", std::move(x), std::move(y), std::move(a)), pos);
618 }
619 
Mod(DSLExpression x,DSLExpression y,PositionInfo pos)620 DSLExpression Mod(DSLExpression x, DSLExpression y, PositionInfo pos) {
621     return DSLExpression(DSLCore::Call("mod", std::move(x), std::move(y)), pos);
622 }
623 
Normalize(DSLExpression x,PositionInfo pos)624 DSLExpression Normalize(DSLExpression x, PositionInfo pos) {
625     return DSLExpression(DSLCore::Call("normalize", std::move(x)), pos);
626 }
627 
NotEqual(DSLExpression x,DSLExpression y,PositionInfo pos)628 DSLExpression NotEqual(DSLExpression x, DSLExpression y, PositionInfo pos) {
629     return DSLExpression(DSLCore::Call("notEqual", std::move(x), std::move(y)), pos);
630 }
631 
Pow(DSLExpression x,DSLExpression y,PositionInfo pos)632 DSLExpression Pow(DSLExpression x, DSLExpression y, PositionInfo pos) {
633     return DSLExpression(DSLCore::Call("pow", std::move(x), std::move(y)), pos);
634 }
635 
Radians(DSLExpression x,PositionInfo pos)636 DSLExpression Radians(DSLExpression x, PositionInfo pos) {
637     return DSLExpression(DSLCore::Call("radians", std::move(x)), pos);
638 }
639 
Reflect(DSLExpression i,DSLExpression n,PositionInfo pos)640 DSLExpression Reflect(DSLExpression i, DSLExpression n, PositionInfo pos) {
641     return DSLExpression(DSLCore::Call("reflect", std::move(i), std::move(n)), pos);
642 }
643 
Refract(DSLExpression i,DSLExpression n,DSLExpression eta,PositionInfo pos)644 DSLExpression Refract(DSLExpression i, DSLExpression n, DSLExpression eta, PositionInfo pos) {
645     return DSLExpression(DSLCore::Call("refract", std::move(i), std::move(n), std::move(eta)), pos);
646 }
647 
Round(DSLExpression x,PositionInfo pos)648 DSLExpression Round(DSLExpression x, PositionInfo pos) {
649     return DSLExpression(DSLCore::Call("round", std::move(x)), pos);
650 }
651 
Saturate(DSLExpression x,PositionInfo pos)652 DSLExpression Saturate(DSLExpression x, PositionInfo pos) {
653     return DSLExpression(DSLCore::Call("saturate", std::move(x)), pos);
654 }
655 
Sign(DSLExpression x,PositionInfo pos)656 DSLExpression Sign(DSLExpression x, PositionInfo pos) {
657     return DSLExpression(DSLCore::Call("sign", std::move(x)), pos);
658 }
659 
Sin(DSLExpression x,PositionInfo pos)660 DSLExpression Sin(DSLExpression x, PositionInfo pos) {
661     return DSLExpression(DSLCore::Call("sin", std::move(x)), pos);
662 }
663 
Smoothstep(DSLExpression edge1,DSLExpression edge2,DSLExpression x,PositionInfo pos)664 DSLExpression Smoothstep(DSLExpression edge1, DSLExpression edge2, DSLExpression x,
665                          PositionInfo pos) {
666     return DSLExpression(DSLCore::Call("smoothstep", std::move(edge1), std::move(edge2),
667                                        std::move(x)),
668                          pos);
669 }
670 
Sqrt(DSLExpression x,PositionInfo pos)671 DSLExpression Sqrt(DSLExpression x, PositionInfo pos) {
672     return DSLExpression(DSLCore::Call("sqrt", std::move(x)), pos);
673 }
674 
Step(DSLExpression edge,DSLExpression x,PositionInfo pos)675 DSLExpression Step(DSLExpression edge, DSLExpression x, PositionInfo pos) {
676     return DSLExpression(DSLCore::Call("step", std::move(edge), std::move(x)), pos);
677 }
678 
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,PositionInfo pos)679 DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a,
680                       PositionInfo pos) {
681     return DSLCore::Swizzle(std::move(base), a, pos);
682 }
683 
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,PositionInfo pos)684 DSLExpression Swizzle(DSLExpression base,
685                       SkSL::SwizzleComponent::Type a,
686                       SkSL::SwizzleComponent::Type b,
687                       PositionInfo pos) {
688     return DSLCore::Swizzle(std::move(base), a, b, pos);
689 }
690 
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,SkSL::SwizzleComponent::Type c,PositionInfo pos)691 DSLExpression Swizzle(DSLExpression base,
692                       SkSL::SwizzleComponent::Type a,
693                       SkSL::SwizzleComponent::Type b,
694                       SkSL::SwizzleComponent::Type c,
695                       PositionInfo pos) {
696     return DSLCore::Swizzle(std::move(base), a, b, c, pos);
697 }
698 
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,SkSL::SwizzleComponent::Type c,SkSL::SwizzleComponent::Type d,PositionInfo pos)699 DSLExpression Swizzle(DSLExpression base,
700                       SkSL::SwizzleComponent::Type a,
701                       SkSL::SwizzleComponent::Type b,
702                       SkSL::SwizzleComponent::Type c,
703                       SkSL::SwizzleComponent::Type d,
704                       PositionInfo pos) {
705     return DSLCore::Swizzle(std::move(base), a, b, c, d, pos);
706 }
707 
Tan(DSLExpression x,PositionInfo pos)708 DSLExpression Tan(DSLExpression x, PositionInfo pos) {
709     return DSLExpression(DSLCore::Call("tan", std::move(x)), pos);
710 }
711 
Unpremul(DSLExpression x,PositionInfo pos)712 DSLExpression Unpremul(DSLExpression x, PositionInfo pos) {
713     return DSLExpression(DSLCore::Call("unpremul", std::move(x)), pos);
714 }
715 
716 } // namespace dsl
717 
718 } // namespace SkSL
719