| /* |
| * Copyright 2020 Google LLC |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "include/sksl/DSLCore.h" |
| |
| #include "include/core/SkTypes.h" |
| #include "include/private/SkSLDefines.h" |
| #include "include/private/SkSLProgramElement.h" |
| #include "include/private/SkSLStatement.h" |
| #include "include/private/SkSLSymbol.h" |
| #include "include/sksl/DSLModifiers.h" |
| #include "include/sksl/DSLSymbols.h" |
| #include "include/sksl/DSLType.h" |
| #include "include/sksl/DSLVar.h" |
| #include "include/sksl/SkSLPosition.h" |
| #include "src/sksl/SkSLBuiltinTypes.h" |
| #include "src/sksl/SkSLCompiler.h" |
| #include "src/sksl/SkSLContext.h" |
| #include "src/sksl/SkSLParsedModule.h" |
| #include "src/sksl/SkSLPool.h" |
| #include "src/sksl/SkSLProgramSettings.h" |
| #include "src/sksl/SkSLThreadContext.h" |
| #include "src/sksl/dsl/priv/DSLWriter.h" |
| #include "src/sksl/ir/SkSLBlock.h" |
| #include "src/sksl/ir/SkSLBreakStatement.h" |
| #include "src/sksl/ir/SkSLContinueStatement.h" |
| #include "src/sksl/ir/SkSLDiscardStatement.h" |
| #include "src/sksl/ir/SkSLDoStatement.h" |
| #include "src/sksl/ir/SkSLExpression.h" |
| #include "src/sksl/ir/SkSLExtension.h" |
| #include "src/sksl/ir/SkSLField.h" |
| #include "src/sksl/ir/SkSLForStatement.h" |
| #include "src/sksl/ir/SkSLFunctionCall.h" |
| #include "src/sksl/ir/SkSLIfStatement.h" |
| #include "src/sksl/ir/SkSLInterfaceBlock.h" |
| #include "src/sksl/ir/SkSLModifiersDeclaration.h" |
| #include "src/sksl/ir/SkSLProgram.h" |
| #include "src/sksl/ir/SkSLReturnStatement.h" |
| #include "src/sksl/ir/SkSLSwitchStatement.h" |
| #include "src/sksl/ir/SkSLSwizzle.h" |
| #include "src/sksl/ir/SkSLSymbolTable.h" |
| #include "src/sksl/ir/SkSLTernaryExpression.h" |
| #include "src/sksl/ir/SkSLType.h" |
| #include "src/sksl/ir/SkSLVarDeclarations.h" |
| #include "src/sksl/ir/SkSLVariable.h" |
| #include "src/sksl/transform/SkSLTransform.h" |
| |
| #include <type_traits> |
| #include <vector> |
| |
| namespace SkSL { |
| |
| namespace dsl { |
| |
| void Start(SkSL::Compiler* compiler, ProgramKind kind) { |
| Start(compiler, kind, ProgramSettings()); |
| } |
| |
| void Start(SkSL::Compiler* compiler, ProgramKind kind, const ProgramSettings& settings) { |
| ThreadContext::SetInstance(std::make_unique<ThreadContext>(compiler, kind, settings, |
| compiler->moduleForProgramKind(kind), /*isModule=*/false)); |
| } |
| |
| void StartModule(SkSL::Compiler* compiler, ProgramKind kind, const ProgramSettings& settings, |
| SkSL::ParsedModule baseModule) { |
| ThreadContext::SetInstance(std::make_unique<ThreadContext>(compiler, kind, settings, |
| baseModule, /*isModule=*/true)); |
| } |
| |
| void End() { |
| ThreadContext::SetInstance(nullptr); |
| } |
| |
| ErrorReporter& GetErrorReporter() { |
| return ThreadContext::GetErrorReporter(); |
| } |
| |
| void SetErrorReporter(ErrorReporter* errorReporter) { |
| SkASSERT(errorReporter); |
| ThreadContext::SetErrorReporter(errorReporter); |
| } |
| |
| class DSLCore { |
| public: |
| static std::unique_ptr<SkSL::Program> ReleaseProgram(std::unique_ptr<std::string> source) { |
| ThreadContext& instance = ThreadContext::Instance(); |
| SkSL::Compiler& compiler = *instance.fCompiler; |
| const SkSL::Context& context = *compiler.fContext; |
| // Variables defined in the pre-includes need their declaring elements added to the program |
| if (!instance.fConfig->fIsBuiltinCode && context.fBuiltins) { |
| Transform::FindAndDeclareBuiltinVariables(context, instance.fConfig->fKind, |
| instance.fSharedElements); |
| } |
| Pool* pool = instance.fPool.get(); |
| auto result = std::make_unique<SkSL::Program>(std::move(source), |
| std::move(instance.fConfig), |
| compiler.fContext, |
| std::move(instance.fProgramElements), |
| std::move(instance.fSharedElements), |
| std::move(instance.fModifiersPool), |
| std::move(compiler.fSymbolTable), |
| std::move(instance.fPool), |
| instance.fInputs); |
| bool success = false; |
| if (!compiler.finalize(*result)) { |
| // Do not return programs that failed to compile. |
| } else if (!compiler.optimize(*result)) { |
| // Do not return programs that failed to optimize. |
| } else { |
| // We have a successful program! |
| success = true; |
| } |
| if (pool) { |
| pool->detachFromThread(); |
| } |
| SkASSERT(instance.fProgramElements.empty()); |
| SkASSERT(!ThreadContext::SymbolTable()); |
| return success ? std::move(result) : nullptr; |
| } |
| |
| static DSLGlobalVar sk_FragColor() { |
| return DSLGlobalVar("sk_FragColor"); |
| } |
| |
| static DSLGlobalVar sk_FragCoord() { |
| return DSLGlobalVar("sk_FragCoord"); |
| } |
| |
| static DSLExpression sk_Position() { |
| return DSLExpression(Symbol("sk_Position")); |
| } |
| |
| template <typename... Args> |
| static DSLExpression Call(const char* name, Position pos, Args... args) { |
| SkSL::ExpressionArray argArray; |
| argArray.reserve_back(sizeof...(args)); |
| ((void)argArray.push_back(args.release()), ...); |
| |
| return DSLExpression(SkSL::FunctionCall::Convert(ThreadContext::Context(), pos, |
| ThreadContext::Compiler().convertIdentifier(Position(), name), |
| std::move(argArray))); |
| } |
| |
| static DSLStatement Break(Position pos) { |
| return SkSL::BreakStatement::Make(pos); |
| } |
| |
| static DSLStatement Continue(Position pos) { |
| return SkSL::ContinueStatement::Make(pos); |
| } |
| |
| static void Declare(const DSLModifiers& modifiers) { |
| ThreadContext::ProgramElements().push_back(std::make_unique<SkSL::ModifiersDeclaration>( |
| ThreadContext::Modifiers(modifiers.fModifiers))); |
| } |
| |
| static DSLStatement Declare(DSLVar& var, Position pos) { |
| return DSLWriter::Declaration(var); |
| } |
| |
| static DSLStatement Declare(SkTArray<DSLVar>& vars, Position pos) { |
| StatementArray statements; |
| for (DSLVar& v : vars) { |
| statements.push_back(Declare(v, pos).release()); |
| } |
| return SkSL::Block::Make(pos, std::move(statements), Block::Kind::kCompoundStatement); |
| } |
| |
| static void Declare(DSLGlobalVar& var, Position pos) { |
| std::unique_ptr<SkSL::Statement> stmt = DSLWriter::Declaration(var); |
| if (stmt) { |
| if (!stmt->isEmpty()) { |
| ThreadContext::ProgramElements().push_back( |
| std::make_unique<SkSL::GlobalVarDeclaration>(std::move(stmt))); |
| } |
| } else if (var.fName == SkSL::Compiler::FRAGCOLOR_NAME) { |
| // sk_FragColor can end up with a null declaration despite no error occurring due to |
| // specific treatment in the compiler. Ignore the null and just grab the existing |
| // variable from the symbol table. |
| const SkSL::Symbol* alreadyDeclared = (*ThreadContext::SymbolTable())[var.fName]; |
| if (alreadyDeclared && alreadyDeclared->is<Variable>()) { |
| var.fVar = &alreadyDeclared->as<Variable>(); |
| var.fInitialized = true; |
| } |
| } |
| } |
| |
| static void Declare(SkTArray<DSLGlobalVar>& vars, Position pos) { |
| for (DSLGlobalVar& v : vars) { |
| Declare(v, pos); |
| } |
| } |
| |
| static DSLStatement Discard(Position pos) { |
| return SkSL::DiscardStatement::Make(pos); |
| } |
| |
| static DSLStatement Do(DSLStatement stmt, DSLExpression test, Position pos) { |
| return DSLStatement(DoStatement::Convert(ThreadContext::Context(), pos, stmt.release(), |
| test.release()), pos); |
| } |
| |
| static DSLStatement For(DSLStatement initializer, DSLExpression test, |
| DSLExpression next, DSLStatement stmt, Position pos, |
| const ForLoopPositions& forLoopPositions) { |
| return DSLStatement(ForStatement::Convert(ThreadContext::Context(), pos, forLoopPositions, |
| initializer.releaseIfPossible(), |
| test.releaseIfPossible(), |
| next.releaseIfPossible(), |
| stmt.release(), |
| ThreadContext::SymbolTable()), pos); |
| } |
| |
| static DSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse, |
| bool isStatic, Position pos) { |
| return DSLStatement(IfStatement::Convert(ThreadContext::Context(), pos, isStatic, |
| test.release(), ifTrue.release(), ifFalse.releaseIfPossible()), pos); |
| } |
| |
| static void FindRTAdjust(SkSL::InterfaceBlock& intf, Position pos) { |
| const std::vector<SkSL::Type::Field>& fields = |
| intf.variable().type().componentType().fields(); |
| const Context& context = ThreadContext::Context(); |
| for (size_t i = 0; i < fields.size(); ++i) { |
| const SkSL::Type::Field& f = fields[i]; |
| if (f.fName == SkSL::Compiler::RTADJUST_NAME) { |
| if (f.fType->matches(*context.fTypes.fFloat4)) { |
| ThreadContext::RTAdjustData& rtAdjust = ThreadContext::RTAdjustState(); |
| rtAdjust.fInterfaceBlock = &intf.variable(); |
| rtAdjust.fFieldIndex = i; |
| } else { |
| ThreadContext::ReportError("sk_RTAdjust must have type 'float4'", pos); |
| } |
| break; |
| } |
| } |
| } |
| |
| static DSLGlobalVar InterfaceBlock(const DSLModifiers& modifiers, std::string_view typeName, |
| SkTArray<DSLField> fields, std::string_view varName, |
| int arraySize, Position pos) { |
| // We need to create a new struct type for the interface block, but we don't want it in the |
| // symbol table. Since dsl::Struct automatically sticks it in the symbol table, we create it |
| // the old fashioned way with MakeStructType. |
| std::vector<SkSL::Type::Field> skslFields; |
| skslFields.reserve(fields.count()); |
| for (const DSLField& field : fields) { |
| const SkSL::Type* baseType = &field.fType.skslType(); |
| if (baseType->isArray()) { |
| baseType = &baseType->componentType(); |
| } |
| SkSL::VarDeclaration::ErrorCheck(ThreadContext::Context(), field.fPosition, |
| field.fModifiers.fPosition, field.fModifiers.fModifiers, baseType, |
| Variable::Storage::kInterfaceBlock); |
| skslFields.push_back(SkSL::Type::Field(field.fPosition, field.fModifiers.fModifiers, |
| field.fName, &field.fType.skslType())); |
| } |
| const SkSL::Type* structType = |
| ThreadContext::SymbolTable()->takeOwnershipOfSymbol(SkSL::Type::MakeStructType( |
| pos, typeName, std::move(skslFields), /*interfaceBlock=*/true)); |
| DSLType varType = arraySize > 0 ? Array(structType, arraySize) : DSLType(structType); |
| DSLGlobalVar var(modifiers, varType, !varName.empty() ? varName : typeName, DSLExpression(), |
| pos); |
| const SkSL::Variable* skslVar = DSLWriter::Var(var); |
| if (skslVar) { |
| auto intf = std::make_unique<SkSL::InterfaceBlock>(pos, *skslVar, typeName, varName, |
| arraySize, ThreadContext::SymbolTable()); |
| FindRTAdjust(*intf, pos); |
| ThreadContext::ProgramElements().push_back(std::move(intf)); |
| if (varName.empty()) { |
| const std::vector<SkSL::Type::Field>& structFields = structType->fields(); |
| for (size_t i = 0; i < structFields.size(); ++i) { |
| ThreadContext::SymbolTable()->add(std::make_unique<SkSL::Field>( |
| structFields[i].fPosition, skslVar, i)); |
| } |
| } else { |
| AddToSymbolTable(var); |
| } |
| } |
| return var; |
| } |
| |
| static DSLStatement Return(DSLExpression value, Position pos) { |
| // Note that because Return is called before the function in which it resides exists, at |
| // this point we do not know the function's return type. We therefore do not check for |
| // errors, or coerce the value to the correct type, until the return statement is actually |
| // added to a function. (This is done in FunctionDefinition::Convert.) |
| return SkSL::ReturnStatement::Make(pos, value.releaseIfPossible()); |
| } |
| |
| static DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a, |
| Position pos, Position maskPos) { |
| return DSLExpression(Swizzle::Convert(ThreadContext::Context(), pos, maskPos, |
| base.release(), ComponentArray{a}), |
| pos); |
| } |
| |
| static DSLExpression Swizzle(DSLExpression base, |
| SkSL::SwizzleComponent::Type a, |
| SkSL::SwizzleComponent::Type b, |
| Position pos, |
| Position maskPos) { |
| return DSLExpression(Swizzle::Convert(ThreadContext::Context(), pos, maskPos, |
| base.release(), ComponentArray{a, b}), |
| pos); |
| } |
| |
| static DSLExpression Swizzle(DSLExpression base, |
| SkSL::SwizzleComponent::Type a, |
| SkSL::SwizzleComponent::Type b, |
| SkSL::SwizzleComponent::Type c, |
| Position pos, |
| Position maskPos) { |
| return DSLExpression(Swizzle::Convert(ThreadContext::Context(), pos, maskPos, base.release(), |
| ComponentArray{a, b, c}), |
| pos); |
| } |
| |
| static DSLExpression Swizzle(DSLExpression base, |
| SkSL::SwizzleComponent::Type a, |
| SkSL::SwizzleComponent::Type b, |
| SkSL::SwizzleComponent::Type c, |
| SkSL::SwizzleComponent::Type d, |
| Position pos, |
| Position maskPos) { |
| return DSLExpression(Swizzle::Convert(ThreadContext::Context(), pos, maskPos, base.release(), |
| ComponentArray{a,b,c,d}), |
| pos); |
| } |
| |
| static DSLExpression Select(DSLExpression test, DSLExpression ifTrue, DSLExpression ifFalse, |
| Position pos) { |
| auto result = TernaryExpression::Convert(ThreadContext::Context(), pos, test.release(), |
| ifTrue.release(), ifFalse.release()); |
| SkASSERT(!result || result->fPosition == pos); |
| return DSLExpression(std::move(result), pos); |
| } |
| |
| static DSLStatement Switch(DSLExpression value, SkTArray<DSLCase> cases, bool isStatic, |
| Position pos) { |
| ExpressionArray values; |
| values.reserve_back(cases.count()); |
| StatementArray caseBlocks; |
| caseBlocks.reserve_back(cases.count()); |
| for (DSLCase& c : cases) { |
| values.push_back(c.fValue.releaseIfPossible()); |
| caseBlocks.push_back(SkSL::Block::Make(Position(), std::move(c.fStatements), |
| Block::Kind::kUnbracedBlock)); |
| } |
| return DSLStatement(SwitchStatement::Convert(ThreadContext::Context(), pos, isStatic, |
| value.release(), |
| std::move(values), |
| std::move(caseBlocks), |
| ThreadContext::SymbolTable()), pos); |
| } |
| |
| static DSLStatement While(DSLExpression test, DSLStatement stmt, Position pos) { |
| return DSLStatement(ForStatement::ConvertWhile(ThreadContext::Context(), pos, |
| test.release(), |
| stmt.release(), |
| ThreadContext::SymbolTable()), pos); |
| } |
| }; |
| |
| std::unique_ptr<SkSL::Program> ReleaseProgram(std::unique_ptr<std::string> source) { |
| return DSLCore::ReleaseProgram(std::move(source)); |
| } |
| |
| DSLGlobalVar sk_FragColor() { |
| return DSLCore::sk_FragColor(); |
| } |
| |
| DSLGlobalVar sk_FragCoord() { |
| return DSLCore::sk_FragCoord(); |
| } |
| |
| DSLExpression sk_Position() { |
| return DSLCore::sk_Position(); |
| } |
| |
| void AddExtension(std::string_view name, Position pos) { |
| ThreadContext::ProgramElements().push_back(std::make_unique<SkSL::Extension>(pos, name)); |
| } |
| |
| DSLStatement Break(Position pos) { |
| return DSLCore::Break(pos); |
| } |
| |
| DSLStatement Continue(Position pos) { |
| return DSLCore::Continue(pos); |
| } |
| |
| void Declare(const DSLModifiers& modifiers, Position pos) { |
| SkSL::ProgramKind kind = ThreadContext::GetProgramConfig()->fKind; |
| if (!ProgramConfig::IsFragment(kind) && |
| !ProgramConfig::IsVertex(kind)) { |
| ThreadContext::ReportError("layout qualifiers are not allowed in this kind of program", |
| pos); |
| return; |
| } |
| DSLCore::Declare(modifiers); |
| } |
| |
| // Logically, we'd want the variable's initial value to appear on here in Declare, since that |
| // matches how we actually write code (and in fact that was what our first attempt looked like). |
| // Unfortunately, C++ doesn't guarantee execution order between arguments, and Declare() can appear |
| // as a function argument in constructs like Block(Declare(x, 0), foo(x)). If these are executed out |
| // of order, we will evaluate the reference to x before we evaluate Declare(x, 0), and thus the |
| // variable's initial value is unknown at the point of reference. There are probably some other |
| // issues with this as well, but it is particularly dangerous when x is const, since SkSL will |
| // expect its value to be known when it is referenced and will end up asserting, dereferencing a |
| // null pointer, or possibly doing something else awful. |
| // |
| // So, we put the initial value onto the Var itself instead of the Declare to guarantee that it is |
| // always executed in the correct order. |
| DSLStatement Declare(DSLVar& var, Position pos) { |
| return DSLCore::Declare(var, pos); |
| } |
| |
| DSLStatement Declare(SkTArray<DSLVar>& vars, Position pos) { |
| return DSLCore::Declare(vars, pos); |
| } |
| |
| void Declare(DSLGlobalVar& var, Position pos) { |
| DSLCore::Declare(var, pos); |
| } |
| |
| void Declare(SkTArray<DSLGlobalVar>& vars, Position pos) { |
| DSLCore::Declare(vars, pos); |
| } |
| |
| DSLStatement Discard(Position pos) { |
| if (!ProgramConfig::IsFragment(ThreadContext::GetProgramConfig()->fKind)) { |
| ThreadContext::ReportError("discard statement is only permitted in fragment shaders", pos); |
| } |
| return DSLCore::Discard(pos); |
| } |
| |
| DSLStatement Do(DSLStatement stmt, DSLExpression test, Position pos) { |
| return DSLCore::Do(std::move(stmt), std::move(test), pos); |
| } |
| |
| DSLStatement For(DSLStatement initializer, DSLExpression test, DSLExpression next, |
| DSLStatement stmt, Position pos, ForLoopPositions forLoopPositions) { |
| return DSLCore::For(std::move(initializer), std::move(test), std::move(next), |
| std::move(stmt), pos, forLoopPositions); |
| } |
| |
| DSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse, Position pos) { |
| return DSLCore::If(std::move(test), std::move(ifTrue), std::move(ifFalse), /*isStatic=*/false, |
| pos); |
| } |
| |
| DSLGlobalVar InterfaceBlock(const DSLModifiers& modifiers, std::string_view typeName, |
| SkTArray<DSLField> fields, std::string_view varName, int arraySize, |
| Position pos) { |
| SkSL::ProgramKind kind = ThreadContext::GetProgramConfig()->fKind; |
| if (!ProgramConfig::IsFragment(kind) && |
| !ProgramConfig::IsVertex(kind)) { |
| ThreadContext::ReportError("interface blocks are not allowed in this kind of program", pos); |
| return DSLGlobalVar(); |
| } |
| return DSLCore::InterfaceBlock(modifiers, typeName, std::move(fields), varName, arraySize, pos); |
| } |
| |
| DSLStatement Return(DSLExpression expr, Position pos) { |
| return DSLCore::Return(std::move(expr), pos); |
| } |
| |
| DSLExpression Select(DSLExpression test, DSLExpression ifTrue, DSLExpression ifFalse, |
| Position pos) { |
| return DSLCore::Select(std::move(test), std::move(ifTrue), std::move(ifFalse), pos); |
| } |
| |
| DSLStatement StaticIf(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse, |
| Position pos) { |
| return DSLCore::If(std::move(test), std::move(ifTrue), std::move(ifFalse), /*isStatic=*/true, |
| pos); |
| } |
| |
| DSLStatement StaticSwitch(DSLExpression value, SkTArray<DSLCase> cases, Position pos) { |
| return DSLCore::Switch(std::move(value), std::move(cases), /*isStatic=*/true, pos); |
| } |
| |
| DSLStatement Switch(DSLExpression value, SkTArray<DSLCase> cases, Position pos) { |
| return DSLCore::Switch(std::move(value), std::move(cases), /*isStatic=*/false, pos); |
| } |
| |
| DSLStatement While(DSLExpression test, DSLStatement stmt, Position pos) { |
| return DSLCore::While(std::move(test), std::move(stmt), pos); |
| } |
| |
| DSLExpression Abs(DSLExpression x, Position pos) { |
| return DSLCore::Call("abs", pos, std::move(x)); |
| } |
| |
| DSLExpression All(DSLExpression x, Position pos) { |
| return DSLCore::Call("all", pos, std::move(x)); |
| } |
| |
| DSLExpression Any(DSLExpression x, Position pos) { |
| return DSLCore::Call("any", pos, std::move(x)); |
| } |
| |
| DSLExpression Atan(DSLExpression y_over_x, Position pos) { |
| return DSLCore::Call("atan", pos, std::move(y_over_x)); |
| } |
| |
| DSLExpression Atan(DSLExpression y, DSLExpression x, Position pos) { |
| return DSLCore::Call("atan", pos, std::move(y), std::move(x)); |
| } |
| |
| DSLExpression Ceil(DSLExpression x, Position pos) { |
| return DSLCore::Call("ceil", pos, std::move(x)); |
| } |
| |
| DSLExpression Clamp(DSLExpression x, DSLExpression min, DSLExpression max, Position pos) { |
| return DSLCore::Call("clamp", pos, std::move(x), std::move(min), std::move(max)); |
| } |
| |
| DSLExpression Cos(DSLExpression x, Position pos) { |
| return DSLCore::Call("cos", pos, std::move(x)); |
| } |
| |
| DSLExpression Cross(DSLExpression x, DSLExpression y, Position pos) { |
| return DSLCore::Call("cross", pos, std::move(x), std::move(y)); |
| } |
| |
| DSLExpression Degrees(DSLExpression x, Position pos) { |
| return DSLCore::Call("degrees", pos, std::move(x)); |
| } |
| |
| DSLExpression Distance(DSLExpression x, DSLExpression y, Position pos) { |
| return DSLCore::Call("distance", pos, std::move(x), std::move(y)); |
| } |
| |
| DSLExpression Dot(DSLExpression x, DSLExpression y, Position pos) { |
| return DSLCore::Call("dot", pos, std::move(x), std::move(y)); |
| } |
| |
| DSLExpression Equal(DSLExpression x, DSLExpression y, Position pos) { |
| return DSLCore::Call("equal", pos, std::move(x), std::move(y)); |
| } |
| |
| DSLExpression Exp(DSLExpression x, Position pos) { |
| return DSLCore::Call("exp", pos, std::move(x)); |
| } |
| |
| DSLExpression Exp2(DSLExpression x, Position pos) { |
| return DSLCore::Call("exp2", pos, std::move(x)); |
| } |
| |
| DSLExpression Faceforward(DSLExpression n, DSLExpression i, DSLExpression nref, Position pos) { |
| return DSLCore::Call("faceforward", pos, std::move(n), std::move(i), std::move(nref)); |
| } |
| |
| DSLExpression Fract(DSLExpression x, Position pos) { |
| return DSLCore::Call("fract", pos, std::move(x)); |
| } |
| |
| DSLExpression Floor(DSLExpression x, Position pos) { |
| return DSLCore::Call("floor", pos, std::move(x)); |
| } |
| |
| DSLExpression GreaterThan(DSLExpression x, DSLExpression y, Position pos) { |
| return DSLCore::Call("greaterThan", pos, std::move(x), std::move(y)); |
| } |
| |
| DSLExpression GreaterThanEqual(DSLExpression x, DSLExpression y, Position pos) { |
| return DSLCore::Call("greaterThanEqual", pos, std::move(x), std::move(y)); |
| } |
| |
| DSLExpression Inverse(DSLExpression x, Position pos) { |
| return DSLCore::Call("inverse", pos, std::move(x)); |
| } |
| |
| DSLExpression Inversesqrt(DSLExpression x, Position pos) { |
| return DSLCore::Call("inversesqrt", pos, std::move(x)); |
| } |
| |
| DSLExpression Length(DSLExpression x, Position pos) { |
| return DSLCore::Call("length", pos, std::move(x)); |
| } |
| |
| DSLExpression LessThan(DSLExpression x, DSLExpression y, Position pos) { |
| return DSLCore::Call("lessThan", pos, std::move(x), std::move(y)); |
| } |
| |
| DSLExpression LessThanEqual(DSLExpression x, DSLExpression y, Position pos) { |
| return DSLCore::Call("lessThanEqual", pos, std::move(x), std::move(y)); |
| } |
| |
| DSLExpression Log(DSLExpression x, Position pos) { |
| return DSLCore::Call("log", pos, std::move(x)); |
| } |
| |
| DSLExpression Log2(DSLExpression x, Position pos) { |
| return DSLCore::Call("log2", pos, std::move(x)); |
| } |
| |
| DSLExpression Max(DSLExpression x, DSLExpression y, Position pos) { |
| return DSLCore::Call("max", pos, std::move(x), std::move(y)); |
| } |
| |
| DSLExpression Min(DSLExpression x, DSLExpression y, Position pos) { |
| return DSLCore::Call("min", pos, std::move(x), std::move(y)); |
| } |
| |
| DSLExpression Mix(DSLExpression x, DSLExpression y, DSLExpression a, Position pos) { |
| return DSLCore::Call("mix", pos, std::move(x), std::move(y), std::move(a)); |
| } |
| |
| DSLExpression Mod(DSLExpression x, DSLExpression y, Position pos) { |
| return DSLCore::Call("mod", pos, std::move(x), std::move(y)); |
| } |
| |
| DSLExpression Normalize(DSLExpression x, Position pos) { |
| return DSLCore::Call("normalize", pos, std::move(x)); |
| } |
| |
| DSLExpression NotEqual(DSLExpression x, DSLExpression y, Position pos) { |
| return DSLCore::Call("notEqual", pos, std::move(x), std::move(y)); |
| } |
| |
| DSLExpression Pow(DSLExpression x, DSLExpression y, Position pos) { |
| return DSLCore::Call("pow", pos, std::move(x), std::move(y)); |
| } |
| |
| DSLExpression Radians(DSLExpression x, Position pos) { |
| return DSLCore::Call("radians", pos, std::move(x)); |
| } |
| |
| DSLExpression Reflect(DSLExpression i, DSLExpression n, Position pos) { |
| return DSLCore::Call("reflect", pos, std::move(i), std::move(n)); |
| } |
| |
| DSLExpression Refract(DSLExpression i, DSLExpression n, DSLExpression eta, Position pos) { |
| return DSLCore::Call("refract", pos, std::move(i), std::move(n), std::move(eta)); |
| } |
| |
| DSLExpression Round(DSLExpression x, Position pos) { |
| return DSLCore::Call("round", pos, std::move(x)); |
| } |
| |
| DSLExpression Saturate(DSLExpression x, Position pos) { |
| return DSLCore::Call("saturate", pos, std::move(x)); |
| } |
| |
| DSLExpression Sign(DSLExpression x, Position pos) { |
| return DSLCore::Call("sign", pos, std::move(x)); |
| } |
| |
| DSLExpression Sin(DSLExpression x, Position pos) { |
| return DSLCore::Call("sin", pos, std::move(x)); |
| } |
| |
| DSLExpression Smoothstep(DSLExpression edge1, DSLExpression edge2, DSLExpression x, |
| Position pos) { |
| return DSLCore::Call("smoothstep", pos, std::move(edge1), std::move(edge2), std::move(x)); |
| } |
| |
| DSLExpression Sqrt(DSLExpression x, Position pos) { |
| return DSLCore::Call("sqrt", pos, std::move(x)); |
| } |
| |
| DSLExpression Step(DSLExpression edge, DSLExpression x, Position pos) { |
| return DSLCore::Call("step", pos, std::move(edge), std::move(x)); |
| } |
| |
| DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a, |
| Position pos, Position maskPos) { |
| return DSLCore::Swizzle(std::move(base), a, pos, maskPos); |
| } |
| |
| DSLExpression Swizzle(DSLExpression base, |
| SkSL::SwizzleComponent::Type a, |
| SkSL::SwizzleComponent::Type b, |
| Position pos, |
| Position maskPos) { |
| return DSLCore::Swizzle(std::move(base), a, b, pos, maskPos); |
| } |
| |
| DSLExpression Swizzle(DSLExpression base, |
| SkSL::SwizzleComponent::Type a, |
| SkSL::SwizzleComponent::Type b, |
| SkSL::SwizzleComponent::Type c, |
| Position pos, |
| Position maskPos) { |
| return DSLCore::Swizzle(std::move(base), a, b, c, pos, maskPos); |
| } |
| |
| DSLExpression Swizzle(DSLExpression base, |
| SkSL::SwizzleComponent::Type a, |
| SkSL::SwizzleComponent::Type b, |
| SkSL::SwizzleComponent::Type c, |
| SkSL::SwizzleComponent::Type d, |
| Position pos, |
| Position maskPos) { |
| return DSLCore::Swizzle(std::move(base), a, b, c, d, pos, maskPos); |
| } |
| |
| DSLExpression Tan(DSLExpression x, Position pos) { |
| return DSLCore::Call("tan", pos, std::move(x)); |
| } |
| |
| DSLExpression Unpremul(DSLExpression x, Position pos) { |
| return DSLCore::Call("unpremul", pos, std::move(x)); |
| } |
| |
| } // namespace dsl |
| |
| } // namespace SkSL |