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<String> source)71 static std::unique_ptr<SkSL::Program> ReleaseProgram(std::unique_ptr<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.fIntrinsics) {
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 == *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,skstd::string_view typeName,SkTArray<DSLField> fields,skstd::string_view varName,int arraySize,PositionInfo pos)235 static DSLGlobalVar InterfaceBlock(const DSLModifiers& modifiers, skstd::string_view typeName,
236 SkTArray<DSLField> fields, skstd::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(), pos.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 = ThreadContext::SymbolTable()->takeOwnershipOfSymbol(
255 SkSL::Type::MakeStructType(pos.line(), typeName, std::move(skslFields)));
256 DSLType varType = arraySize > 0 ? Array(structType, arraySize) : DSLType(structType);
257 DSLGlobalVar var(modifiers, varType, !varName.empty() ? varName : typeName, DSLExpression(),
258 pos);
259 // Interface blocks can't be declared, so we always need to mark the var declared ourselves.
260 // We do this only when fDSLMarkVarDeclared is false, so we don't double-declare it.
261 if (!ThreadContext::Settings().fDSLMarkVarsDeclared) {
262 DSLWriter::MarkDeclared(var);
263 }
264 const SkSL::Variable* skslVar = DSLWriter::Var(var);
265 if (skslVar) {
266 auto intf = std::make_unique<SkSL::InterfaceBlock>(pos.line(),
267 *skslVar, typeName, varName, arraySize, ThreadContext::SymbolTable());
268 FindRTAdjust(*intf, pos);
269 ThreadContext::ProgramElements().push_back(std::move(intf));
270 if (varName.empty()) {
271 const std::vector<SkSL::Type::Field>& structFields = structType->fields();
272 for (size_t i = 0; i < structFields.size(); ++i) {
273 ThreadContext::SymbolTable()->add(std::make_unique<SkSL::Field>(pos.line(),
274 skslVar,
275 i));
276 }
277 } else {
278 AddToSymbolTable(var);
279 }
280 }
281 GetErrorReporter().reportPendingErrors(pos);
282 return var;
283 }
284
Return(DSLExpression value,PositionInfo pos)285 static DSLStatement Return(DSLExpression value, PositionInfo pos) {
286 // Note that because Return is called before the function in which it resides exists, at
287 // this point we do not know the function's return type. We therefore do not check for
288 // errors, or coerce the value to the correct type, until the return statement is actually
289 // added to a function. (This is done in FunctionDefinition::Convert.)
290 return SkSL::ReturnStatement::Make(pos.line(), value.releaseIfPossible());
291 }
292
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,PositionInfo pos)293 static DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a,
294 PositionInfo pos) {
295 return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(),
296 ComponentArray{a}),
297 pos);
298 }
299
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,PositionInfo pos)300 static DSLExpression Swizzle(DSLExpression base,
301 SkSL::SwizzleComponent::Type a,
302 SkSL::SwizzleComponent::Type b,
303 PositionInfo pos) {
304 return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(),
305 ComponentArray{a, b}),
306 pos);
307 }
308
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,SkSL::SwizzleComponent::Type c,PositionInfo pos)309 static DSLExpression Swizzle(DSLExpression base,
310 SkSL::SwizzleComponent::Type a,
311 SkSL::SwizzleComponent::Type b,
312 SkSL::SwizzleComponent::Type c,
313 PositionInfo pos) {
314 return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(),
315 ComponentArray{a, b, c}),
316 pos);
317 }
318
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,SkSL::SwizzleComponent::Type c,SkSL::SwizzleComponent::Type d,PositionInfo pos)319 static DSLExpression Swizzle(DSLExpression base,
320 SkSL::SwizzleComponent::Type a,
321 SkSL::SwizzleComponent::Type b,
322 SkSL::SwizzleComponent::Type c,
323 SkSL::SwizzleComponent::Type d,
324 PositionInfo pos) {
325 return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(),
326 ComponentArray{a,b,c,d}),
327 pos);
328 }
329
Select(DSLExpression test,DSLExpression ifTrue,DSLExpression ifFalse)330 static DSLPossibleExpression Select(DSLExpression test, DSLExpression ifTrue,
331 DSLExpression ifFalse) {
332 return TernaryExpression::Convert(ThreadContext::Context(), test.release(),
333 ifTrue.release(), ifFalse.release());
334 }
335
Switch(DSLExpression value,SkTArray<DSLCase> cases,bool isStatic)336 static DSLPossibleStatement Switch(DSLExpression value, SkTArray<DSLCase> cases,
337 bool isStatic) {
338 ExpressionArray values;
339 values.reserve_back(cases.count());
340 StatementArray caseBlocks;
341 caseBlocks.reserve_back(cases.count());
342 for (DSLCase& c : cases) {
343 values.push_back(c.fValue.releaseIfPossible());
344 caseBlocks.push_back(SkSL::Block::Make(/*line=*/-1,
345 std::move(c.fStatements), /*symbols=*/nullptr, /*isScope=*/false));
346 }
347 return SwitchStatement::Convert(ThreadContext::Context(), /*line=*/-1, isStatic,
348 value.release(), std::move(values), std::move(caseBlocks),
349 ThreadContext::SymbolTable());
350 }
351
While(DSLExpression test,DSLStatement stmt)352 static DSLPossibleStatement While(DSLExpression test, DSLStatement stmt) {
353 return ForStatement::ConvertWhile(ThreadContext::Context(), /*line=*/-1, test.release(),
354 stmt.release(), ThreadContext::SymbolTable());
355 }
356 };
357
ReleaseProgram(std::unique_ptr<String> source)358 std::unique_ptr<SkSL::Program> ReleaseProgram(std::unique_ptr<String> source) {
359 return DSLCore::ReleaseProgram(std::move(source));
360 }
361
sk_FragColor()362 DSLGlobalVar sk_FragColor() {
363 return DSLCore::sk_FragColor();
364 }
365
sk_FragCoord()366 DSLGlobalVar sk_FragCoord() {
367 return DSLCore::sk_FragCoord();
368 }
369
sk_Position()370 DSLExpression sk_Position() {
371 return DSLCore::sk_Position();
372 }
373
AddExtension(skstd::string_view name,PositionInfo pos)374 void AddExtension(skstd::string_view name, PositionInfo pos) {
375 ThreadContext::ProgramElements().push_back(std::make_unique<SkSL::Extension>(pos.line(), name));
376 ThreadContext::ReportErrors(pos);
377 }
378
Break(PositionInfo pos)379 DSLStatement Break(PositionInfo pos) {
380 return DSLCore::Break(pos);
381 }
382
Continue(PositionInfo pos)383 DSLStatement Continue(PositionInfo pos) {
384 return DSLCore::Continue(pos);
385 }
386
Declare(const DSLModifiers & modifiers,PositionInfo pos)387 void Declare(const DSLModifiers& modifiers, PositionInfo pos) {
388 SkSL::ProgramKind kind = ThreadContext::GetProgramConfig()->fKind;
389 if (kind != ProgramKind::kFragment &&
390 kind != ProgramKind::kVertex) {
391 ThreadContext::ReportError("layout qualifiers are not allowed in this kind of program",
392 pos);
393 return;
394 }
395 DSLCore::Declare(modifiers);
396 }
397
398 // Logically, we'd want the variable's initial value to appear on here in Declare, since that
399 // matches how we actually write code (and in fact that was what our first attempt looked like).
400 // Unfortunately, C++ doesn't guarantee execution order between arguments, and Declare() can appear
401 // as a function argument in constructs like Block(Declare(x, 0), foo(x)). If these are executed out
402 // of order, we will evaluate the reference to x before we evaluate Declare(x, 0), and thus the
403 // variable's initial value is unknown at the point of reference. There are probably some other
404 // issues with this as well, but it is particularly dangerous when x is const, since SkSL will
405 // expect its value to be known when it is referenced and will end up asserting, dereferencing a
406 // null pointer, or possibly doing something else awful.
407 //
408 // So, we put the initial value onto the Var itself instead of the Declare to guarantee that it is
409 // always executed in the correct order.
Declare(DSLVar & var,PositionInfo pos)410 DSLStatement Declare(DSLVar& var, PositionInfo pos) {
411 return DSLCore::Declare(var, pos);
412 }
413
Declare(SkTArray<DSLVar> & vars,PositionInfo pos)414 DSLStatement Declare(SkTArray<DSLVar>& vars, PositionInfo pos) {
415 return DSLCore::Declare(vars, pos);
416 }
417
Declare(DSLGlobalVar & var,PositionInfo pos)418 void Declare(DSLGlobalVar& var, PositionInfo pos) {
419 DSLCore::Declare(var, pos);
420 }
421
Declare(SkTArray<DSLGlobalVar> & vars,PositionInfo pos)422 void Declare(SkTArray<DSLGlobalVar>& vars, PositionInfo pos) {
423 DSLCore::Declare(vars, pos);
424 }
425
Discard(PositionInfo pos)426 DSLStatement Discard(PositionInfo pos) {
427 if (ThreadContext::GetProgramConfig()->fKind != ProgramKind::kFragment) {
428 ThreadContext::ReportError("discard statement is only permitted in fragment shaders", pos);
429 }
430 return DSLCore::Discard(pos);
431 }
432
Do(DSLStatement stmt,DSLExpression test,PositionInfo pos)433 DSLStatement Do(DSLStatement stmt, DSLExpression test, PositionInfo pos) {
434 return DSLStatement(DSLCore::Do(std::move(stmt), std::move(test)), pos);
435 }
436
For(DSLStatement initializer,DSLExpression test,DSLExpression next,DSLStatement stmt,PositionInfo pos)437 DSLStatement For(DSLStatement initializer, DSLExpression test, DSLExpression next,
438 DSLStatement stmt, PositionInfo pos) {
439 return DSLStatement(DSLCore::For(std::move(initializer), std::move(test), std::move(next),
440 std::move(stmt), pos), pos);
441 }
442
If(DSLExpression test,DSLStatement ifTrue,DSLStatement ifFalse,PositionInfo pos)443 DSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse, PositionInfo pos) {
444 return DSLStatement(DSLCore::If(std::move(test), std::move(ifTrue), std::move(ifFalse),
445 /*isStatic=*/false),
446 pos);
447 }
448
InterfaceBlock(const DSLModifiers & modifiers,skstd::string_view typeName,SkTArray<DSLField> fields,skstd::string_view varName,int arraySize,PositionInfo pos)449 DSLGlobalVar InterfaceBlock(const DSLModifiers& modifiers, skstd::string_view typeName,
450 SkTArray<DSLField> fields, skstd::string_view varName, int arraySize,
451 PositionInfo pos) {
452 SkSL::ProgramKind kind = ThreadContext::GetProgramConfig()->fKind;
453 if (kind != ProgramKind::kFragment &&
454 kind != ProgramKind::kVertex) {
455 ThreadContext::ReportError("interface blocks are not allowed in this kind of program", pos);
456 return DSLGlobalVar();
457 }
458 return DSLCore::InterfaceBlock(modifiers, typeName, std::move(fields), varName, arraySize, pos);
459 }
460
Return(DSLExpression expr,PositionInfo pos)461 DSLStatement Return(DSLExpression expr, PositionInfo pos) {
462 return DSLCore::Return(std::move(expr), pos);
463 }
464
Select(DSLExpression test,DSLExpression ifTrue,DSLExpression ifFalse,PositionInfo pos)465 DSLExpression Select(DSLExpression test, DSLExpression ifTrue, DSLExpression ifFalse,
466 PositionInfo pos) {
467 return DSLExpression(DSLCore::Select(std::move(test), std::move(ifTrue), std::move(ifFalse)),
468 pos);
469 }
470
StaticIf(DSLExpression test,DSLStatement ifTrue,DSLStatement ifFalse,PositionInfo pos)471 DSLStatement StaticIf(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse,
472 PositionInfo pos) {
473 return DSLStatement(DSLCore::If(std::move(test), std::move(ifTrue), std::move(ifFalse),
474 /*isStatic=*/true),
475 pos);
476 }
477
PossibleStaticSwitch(DSLExpression value,SkTArray<DSLCase> cases)478 DSLPossibleStatement PossibleStaticSwitch(DSLExpression value, SkTArray<DSLCase> cases) {
479 return DSLCore::Switch(std::move(value), std::move(cases), /*isStatic=*/true);
480 }
481
StaticSwitch(DSLExpression value,SkTArray<DSLCase> cases,PositionInfo pos)482 DSLStatement StaticSwitch(DSLExpression value, SkTArray<DSLCase> cases, PositionInfo pos) {
483 return DSLStatement(PossibleStaticSwitch(std::move(value), std::move(cases)), pos);
484 }
485
PossibleSwitch(DSLExpression value,SkTArray<DSLCase> cases)486 DSLPossibleStatement PossibleSwitch(DSLExpression value, SkTArray<DSLCase> cases) {
487 return DSLCore::Switch(std::move(value), std::move(cases), /*isStatic=*/false);
488 }
489
Switch(DSLExpression value,SkTArray<DSLCase> cases,PositionInfo pos)490 DSLStatement Switch(DSLExpression value, SkTArray<DSLCase> cases, PositionInfo pos) {
491 return DSLStatement(PossibleSwitch(std::move(value), std::move(cases)), pos);
492 }
493
While(DSLExpression test,DSLStatement stmt,PositionInfo pos)494 DSLStatement While(DSLExpression test, DSLStatement stmt, PositionInfo pos) {
495 return DSLStatement(DSLCore::While(std::move(test), std::move(stmt)), pos);
496 }
497
Abs(DSLExpression x,PositionInfo pos)498 DSLExpression Abs(DSLExpression x, PositionInfo pos) {
499 return DSLExpression(DSLCore::Call("abs", std::move(x)), pos);
500 }
501
All(DSLExpression x,PositionInfo pos)502 DSLExpression All(DSLExpression x, PositionInfo pos) {
503 return DSLExpression(DSLCore::Call("all", std::move(x)), pos);
504 }
505
Any(DSLExpression x,PositionInfo pos)506 DSLExpression Any(DSLExpression x, PositionInfo pos) {
507 return DSLExpression(DSLCore::Call("any", std::move(x)), pos);
508 }
509
Atan(DSLExpression y_over_x,PositionInfo pos)510 DSLExpression Atan(DSLExpression y_over_x, PositionInfo pos) {
511 return DSLExpression(DSLCore::Call("atan", std::move(y_over_x)), pos);
512 }
513
Atan(DSLExpression y,DSLExpression x,PositionInfo pos)514 DSLExpression Atan(DSLExpression y, DSLExpression x, PositionInfo pos) {
515 return DSLExpression(DSLCore::Call("atan", std::move(y), std::move(x)), pos);
516 }
517
Ceil(DSLExpression x,PositionInfo pos)518 DSLExpression Ceil(DSLExpression x, PositionInfo pos) {
519 return DSLExpression(DSLCore::Call("ceil", std::move(x)), pos);
520 }
521
Clamp(DSLExpression x,DSLExpression min,DSLExpression max,PositionInfo pos)522 DSLExpression Clamp(DSLExpression x, DSLExpression min, DSLExpression max, PositionInfo pos) {
523 return DSLExpression(DSLCore::Call("clamp", std::move(x), std::move(min), std::move(max)), pos);
524 }
525
Cos(DSLExpression x,PositionInfo pos)526 DSLExpression Cos(DSLExpression x, PositionInfo pos) {
527 return DSLExpression(DSLCore::Call("cos", std::move(x)), pos);
528 }
529
Cross(DSLExpression x,DSLExpression y,PositionInfo pos)530 DSLExpression Cross(DSLExpression x, DSLExpression y, PositionInfo pos) {
531 return DSLExpression(DSLCore::Call("cross", std::move(x), std::move(y)), pos);
532 }
533
Degrees(DSLExpression x,PositionInfo pos)534 DSLExpression Degrees(DSLExpression x, PositionInfo pos) {
535 return DSLExpression(DSLCore::Call("degrees", std::move(x)), pos);
536 }
537
Distance(DSLExpression x,DSLExpression y,PositionInfo pos)538 DSLExpression Distance(DSLExpression x, DSLExpression y, PositionInfo pos) {
539 return DSLExpression(DSLCore::Call("distance", std::move(x), std::move(y)), pos);
540 }
541
Dot(DSLExpression x,DSLExpression y,PositionInfo pos)542 DSLExpression Dot(DSLExpression x, DSLExpression y, PositionInfo pos) {
543 return DSLExpression(DSLCore::Call("dot", std::move(x), std::move(y)), pos);
544 }
545
Equal(DSLExpression x,DSLExpression y,PositionInfo pos)546 DSLExpression Equal(DSLExpression x, DSLExpression y, PositionInfo pos) {
547 return DSLExpression(DSLCore::Call("equal", std::move(x), std::move(y)), pos);
548 }
549
Exp(DSLExpression x,PositionInfo pos)550 DSLExpression Exp(DSLExpression x, PositionInfo pos) {
551 return DSLExpression(DSLCore::Call("exp", std::move(x)), pos);
552 }
553
Exp2(DSLExpression x,PositionInfo pos)554 DSLExpression Exp2(DSLExpression x, PositionInfo pos) {
555 return DSLExpression(DSLCore::Call("exp2", std::move(x)), pos);
556 }
557
Faceforward(DSLExpression n,DSLExpression i,DSLExpression nref,PositionInfo pos)558 DSLExpression Faceforward(DSLExpression n, DSLExpression i, DSLExpression nref, PositionInfo pos) {
559 return DSLExpression(DSLCore::Call("faceforward", std::move(n), std::move(i), std::move(nref)),
560 pos);
561 }
562
Fract(DSLExpression x,PositionInfo pos)563 DSLExpression Fract(DSLExpression x, PositionInfo pos) {
564 return DSLExpression(DSLCore::Call("fract", std::move(x)), pos);
565 }
566
Floor(DSLExpression x,PositionInfo pos)567 DSLExpression Floor(DSLExpression x, PositionInfo pos) {
568 return DSLExpression(DSLCore::Call("floor", std::move(x)), pos);
569 }
570
GreaterThan(DSLExpression x,DSLExpression y,PositionInfo pos)571 DSLExpression GreaterThan(DSLExpression x, DSLExpression y, PositionInfo pos) {
572 return DSLExpression(DSLCore::Call("greaterThan", std::move(x), std::move(y)), pos);
573 }
574
GreaterThanEqual(DSLExpression x,DSLExpression y,PositionInfo pos)575 DSLExpression GreaterThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos) {
576 return DSLExpression(DSLCore::Call("greaterThanEqual", std::move(x), std::move(y)), pos);
577 }
578
Inverse(DSLExpression x,PositionInfo pos)579 DSLExpression Inverse(DSLExpression x, PositionInfo pos) {
580 return DSLExpression(DSLCore::Call("inverse", std::move(x)), pos);
581 }
582
Inversesqrt(DSLExpression x,PositionInfo pos)583 DSLExpression Inversesqrt(DSLExpression x, PositionInfo pos) {
584 return DSLExpression(DSLCore::Call("inversesqrt", std::move(x)), pos);
585 }
586
Length(DSLExpression x,PositionInfo pos)587 DSLExpression Length(DSLExpression x, PositionInfo pos) {
588 return DSLExpression(DSLCore::Call("length", std::move(x)), pos);
589 }
590
LessThan(DSLExpression x,DSLExpression y,PositionInfo pos)591 DSLExpression LessThan(DSLExpression x, DSLExpression y, PositionInfo pos) {
592 return DSLExpression(DSLCore::Call("lessThan", std::move(x), std::move(y)), pos);
593 }
594
LessThanEqual(DSLExpression x,DSLExpression y,PositionInfo pos)595 DSLExpression LessThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos) {
596 return DSLExpression(DSLCore::Call("lessThanEqual", std::move(x), std::move(y)), pos);
597 }
598
Log(DSLExpression x,PositionInfo pos)599 DSLExpression Log(DSLExpression x, PositionInfo pos) {
600 return DSLExpression(DSLCore::Call("log", std::move(x)), pos);
601 }
602
Log2(DSLExpression x,PositionInfo pos)603 DSLExpression Log2(DSLExpression x, PositionInfo pos) {
604 return DSLExpression(DSLCore::Call("log2", std::move(x)), pos);
605 }
606
Max(DSLExpression x,DSLExpression y,PositionInfo pos)607 DSLExpression Max(DSLExpression x, DSLExpression y, PositionInfo pos) {
608 return DSLExpression(DSLCore::Call("max", std::move(x), std::move(y)), pos);
609 }
610
Min(DSLExpression x,DSLExpression y,PositionInfo pos)611 DSLExpression Min(DSLExpression x, DSLExpression y, PositionInfo pos) {
612 return DSLExpression(DSLCore::Call("min", std::move(x), std::move(y)), pos);
613 }
614
Mix(DSLExpression x,DSLExpression y,DSLExpression a,PositionInfo pos)615 DSLExpression Mix(DSLExpression x, DSLExpression y, DSLExpression a, PositionInfo pos) {
616 return DSLExpression(DSLCore::Call("mix", std::move(x), std::move(y), std::move(a)), pos);
617 }
618
Mod(DSLExpression x,DSLExpression y,PositionInfo pos)619 DSLExpression Mod(DSLExpression x, DSLExpression y, PositionInfo pos) {
620 return DSLExpression(DSLCore::Call("mod", std::move(x), std::move(y)), pos);
621 }
622
Normalize(DSLExpression x,PositionInfo pos)623 DSLExpression Normalize(DSLExpression x, PositionInfo pos) {
624 return DSLExpression(DSLCore::Call("normalize", std::move(x)), pos);
625 }
626
NotEqual(DSLExpression x,DSLExpression y,PositionInfo pos)627 DSLExpression NotEqual(DSLExpression x, DSLExpression y, PositionInfo pos) {
628 return DSLExpression(DSLCore::Call("notEqual", std::move(x), std::move(y)), pos);
629 }
630
Pow(DSLExpression x,DSLExpression y,PositionInfo pos)631 DSLExpression Pow(DSLExpression x, DSLExpression y, PositionInfo pos) {
632 return DSLExpression(DSLCore::Call("pow", std::move(x), std::move(y)), pos);
633 }
634
Radians(DSLExpression x,PositionInfo pos)635 DSLExpression Radians(DSLExpression x, PositionInfo pos) {
636 return DSLExpression(DSLCore::Call("radians", std::move(x)), pos);
637 }
638
Reflect(DSLExpression i,DSLExpression n,PositionInfo pos)639 DSLExpression Reflect(DSLExpression i, DSLExpression n, PositionInfo pos) {
640 return DSLExpression(DSLCore::Call("reflect", std::move(i), std::move(n)), pos);
641 }
642
Refract(DSLExpression i,DSLExpression n,DSLExpression eta,PositionInfo pos)643 DSLExpression Refract(DSLExpression i, DSLExpression n, DSLExpression eta, PositionInfo pos) {
644 return DSLExpression(DSLCore::Call("refract", std::move(i), std::move(n), std::move(eta)), pos);
645 }
646
Round(DSLExpression x,PositionInfo pos)647 DSLExpression Round(DSLExpression x, PositionInfo pos) {
648 return DSLExpression(DSLCore::Call("round", std::move(x)), pos);
649 }
650
Saturate(DSLExpression x,PositionInfo pos)651 DSLExpression Saturate(DSLExpression x, PositionInfo pos) {
652 return DSLExpression(DSLCore::Call("saturate", std::move(x)), pos);
653 }
654
Sign(DSLExpression x,PositionInfo pos)655 DSLExpression Sign(DSLExpression x, PositionInfo pos) {
656 return DSLExpression(DSLCore::Call("sign", std::move(x)), pos);
657 }
658
Sin(DSLExpression x,PositionInfo pos)659 DSLExpression Sin(DSLExpression x, PositionInfo pos) {
660 return DSLExpression(DSLCore::Call("sin", std::move(x)), pos);
661 }
662
Smoothstep(DSLExpression edge1,DSLExpression edge2,DSLExpression x,PositionInfo pos)663 DSLExpression Smoothstep(DSLExpression edge1, DSLExpression edge2, DSLExpression x,
664 PositionInfo pos) {
665 return DSLExpression(DSLCore::Call("smoothstep", std::move(edge1), std::move(edge2),
666 std::move(x)),
667 pos);
668 }
669
Sqrt(DSLExpression x,PositionInfo pos)670 DSLExpression Sqrt(DSLExpression x, PositionInfo pos) {
671 return DSLExpression(DSLCore::Call("sqrt", std::move(x)), pos);
672 }
673
Step(DSLExpression edge,DSLExpression x,PositionInfo pos)674 DSLExpression Step(DSLExpression edge, DSLExpression x, PositionInfo pos) {
675 return DSLExpression(DSLCore::Call("step", std::move(edge), std::move(x)), pos);
676 }
677
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,PositionInfo pos)678 DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a,
679 PositionInfo pos) {
680 return DSLCore::Swizzle(std::move(base), a, pos);
681 }
682
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,PositionInfo pos)683 DSLExpression Swizzle(DSLExpression base,
684 SkSL::SwizzleComponent::Type a,
685 SkSL::SwizzleComponent::Type b,
686 PositionInfo pos) {
687 return DSLCore::Swizzle(std::move(base), a, b, pos);
688 }
689
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,SkSL::SwizzleComponent::Type c,PositionInfo pos)690 DSLExpression Swizzle(DSLExpression base,
691 SkSL::SwizzleComponent::Type a,
692 SkSL::SwizzleComponent::Type b,
693 SkSL::SwizzleComponent::Type c,
694 PositionInfo pos) {
695 return DSLCore::Swizzle(std::move(base), a, b, c, pos);
696 }
697
Swizzle(DSLExpression base,SkSL::SwizzleComponent::Type a,SkSL::SwizzleComponent::Type b,SkSL::SwizzleComponent::Type c,SkSL::SwizzleComponent::Type d,PositionInfo pos)698 DSLExpression Swizzle(DSLExpression base,
699 SkSL::SwizzleComponent::Type a,
700 SkSL::SwizzleComponent::Type b,
701 SkSL::SwizzleComponent::Type c,
702 SkSL::SwizzleComponent::Type d,
703 PositionInfo pos) {
704 return DSLCore::Swizzle(std::move(base), a, b, c, d, pos);
705 }
706
Tan(DSLExpression x,PositionInfo pos)707 DSLExpression Tan(DSLExpression x, PositionInfo pos) {
708 return DSLExpression(DSLCore::Call("tan", std::move(x)), pos);
709 }
710
Unpremul(DSLExpression x,PositionInfo pos)711 DSLExpression Unpremul(DSLExpression x, PositionInfo pos) {
712 return DSLExpression(DSLCore::Call("unpremul", std::move(x)), pos);
713 }
714
715 } // namespace dsl
716
717 } // namespace SkSL
718