/* * Copyright 2020 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SKSL_DSL_CORE #define SKSL_DSL_CORE #include "include/private/SkSLProgramKind.h" #include "include/private/SkTArray.h" #include "include/sksl/DSLBlock.h" #include "include/sksl/DSLCase.h" #include "include/sksl/DSLExpression.h" #include "include/sksl/DSLFunction.h" #include "include/sksl/DSLStatement.h" #include "include/sksl/DSLType.h" #include "include/sksl/DSLVar.h" #include "include/sksl/DSLWrapper.h" #include "include/sksl/SkSLErrorReporter.h" #define SKSL_DSL_PARSER 0 namespace SkSL { class Compiler; struct Program; struct ProgramSettings; namespace dsl { // When users import the DSL namespace via `using namespace SkSL::dsl`, we want the SwizzleComponent // Type enum to come into scope as well, so `Swizzle(var, X, Y, ONE)` can work as expected. // `namespace SkSL::SwizzleComponent` contains only an `enum Type`; this `using namespace` directive // shouldn't pollute the SkSL::dsl namespace with anything else. using namespace SkSL::SwizzleComponent; /** * Starts DSL output on the current thread using the specified compiler. This must be called * prior to any other DSL functions. */ void Start(SkSL::Compiler* compiler, SkSL::ProgramKind kind = SkSL::ProgramKind::kFragment); void Start(SkSL::Compiler* compiler, SkSL::ProgramKind kind, const SkSL::ProgramSettings& settings); /** * Signals the end of DSL output. This must be called sometime between a call to Start() and the * termination of the thread. */ void End(); /** * Returns all global elements (functions and global variables) as a self-contained Program. The * optional source string is retained as the program's source. DSL programs do not normally have * sources, but when a DSL program is produced from parsed program text (as in DSLParser), it may be * important to retain it so that any skstd::string_views derived from it remain valid. */ std::unique_ptr ReleaseProgram(std::unique_ptr source = nullptr); /** * Returns the ErrorReporter which will be notified of any errors that occur during DSL calls. The * default error reporter aborts on any error. */ ErrorReporter& GetErrorReporter(); /** * Installs an ErrorReporter which will be notified of any errors that occur during DSL calls. */ void SetErrorReporter(ErrorReporter* errorReporter); DSLGlobalVar sk_FragColor(); DSLGlobalVar sk_FragCoord(); DSLExpression sk_Position(); /** * #extension : enable */ void AddExtension(skstd::string_view name, PositionInfo pos = PositionInfo::Capture()); /** * break; */ DSLStatement Break(PositionInfo pos = PositionInfo::Capture()); /** * continue; */ DSLStatement Continue(PositionInfo pos = PositionInfo::Capture()); /** * Adds a modifiers declaration to the current program. */ void Declare(const DSLModifiers& modifiers, PositionInfo pos = PositionInfo::Capture()); /** * Creates a local variable declaration statement. */ DSLStatement Declare(DSLVar& var, PositionInfo pos = PositionInfo::Capture()); /** * Creates a local variable declaration statement containing multiple variables. */ DSLStatement Declare(SkTArray& vars, PositionInfo pos = PositionInfo::Capture()); /** * Declares a global variable. */ void Declare(DSLGlobalVar& var, PositionInfo pos = PositionInfo::Capture()); /** * Declares a set of global variables. */ void Declare(SkTArray& vars, PositionInfo pos = PositionInfo::Capture()); /** * default: statements */ template DSLCase Default(Statements... statements) { return DSLCase(DSLExpression(), std::move(statements)...); } /** * discard; */ DSLStatement Discard(PositionInfo pos = PositionInfo::Capture()); /** * do stmt; while (test); */ DSLStatement Do(DSLStatement stmt, DSLExpression test, PositionInfo pos = PositionInfo::Capture()); /** * for (initializer; test; next) stmt; */ DSLStatement For(DSLStatement initializer, DSLExpression test, DSLExpression next, DSLStatement stmt, PositionInfo pos = PositionInfo::Capture()); /** * if (test) ifTrue; [else ifFalse;] */ DSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse = DSLStatement(), PositionInfo pos = PositionInfo::Capture()); DSLGlobalVar InterfaceBlock(const DSLModifiers& modifiers, skstd::string_view typeName, SkTArray fields, skstd::string_view varName = "", int arraySize = 0, PositionInfo pos = PositionInfo::Capture()); /** * return [value]; */ DSLStatement Return(DSLExpression value = DSLExpression(), PositionInfo pos = PositionInfo::Capture()); /** * test ? ifTrue : ifFalse */ DSLExpression Select(DSLExpression test, DSLExpression ifTrue, DSLExpression ifFalse, PositionInfo info = PositionInfo::Capture()); DSLStatement StaticIf(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse = DSLStatement(), PositionInfo pos = PositionInfo::Capture()); DSLPossibleStatement StaticSwitch(DSLExpression value, SkTArray cases, PositionInfo info = PositionInfo::Capture()); /** * @switch (value) { cases } */ template DSLPossibleStatement StaticSwitch(DSLExpression value, Cases... cases) { SkTArray caseArray; caseArray.reserve_back(sizeof...(cases)); (caseArray.push_back(std::move(cases)), ...); return StaticSwitch(std::move(value), std::move(caseArray)); } DSLPossibleStatement Switch(DSLExpression value, SkTArray cases, PositionInfo info = PositionInfo::Capture()); /** * switch (value) { cases } */ template DSLPossibleStatement Switch(DSLExpression value, Cases... cases) { SkTArray caseArray; caseArray.reserve_back(sizeof...(cases)); (caseArray.push_back(std::move(cases)), ...); return Switch(std::move(value), std::move(caseArray)); } /** * while (test) stmt; */ DSLStatement While(DSLExpression test, DSLStatement stmt, PositionInfo info = PositionInfo::Capture()); /** * expression.xyz1 */ DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a, PositionInfo pos = PositionInfo::Capture()); DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a, SkSL::SwizzleComponent::Type b, PositionInfo pos = PositionInfo::Capture()); DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a, SkSL::SwizzleComponent::Type b, SkSL::SwizzleComponent::Type c, PositionInfo pos = PositionInfo::Capture()); DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a, SkSL::SwizzleComponent::Type b, SkSL::SwizzleComponent::Type c, SkSL::SwizzleComponent::Type d, PositionInfo pos = PositionInfo::Capture()); /** * Returns the absolute value of x. If x is a vector, operates componentwise. */ DSLExpression Abs(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns true if all of the components of boolean vector x are true. */ DSLExpression All(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns true if any of the components of boolean vector x are true. */ DSLExpression Any(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns the arctangent of y over x. Operates componentwise on vectors. */ DSLExpression Atan(DSLExpression y_over_x, PositionInfo pos = PositionInfo::Capture()); DSLExpression Atan(DSLExpression y, DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns x rounded towards positive infinity. If x is a vector, operates componentwise. */ DSLExpression Ceil(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns x clamped to between min and max. If x is a vector, operates componentwise. */ DSLExpression Clamp(DSLExpression x, DSLExpression min, DSLExpression max, PositionInfo pos = PositionInfo::Capture()); /** * Returns the cosine of x. If x is a vector, operates componentwise. */ DSLExpression Cos(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns the cross product of x and y. */ DSLExpression Cross(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture()); /** * Returns x converted from radians to degrees. If x is a vector, operates componentwise. */ DSLExpression Degrees(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns the distance between x and y. */ DSLExpression Distance(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture()); /** * Returns the dot product of x and y. */ DSLExpression Dot(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture()); /** * Returns a boolean vector indicating whether components of x are equal to the corresponding * components of y. */ DSLExpression Equal(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture()); /** * Returns e^x. If x is a vector, operates componentwise. */ DSLExpression Exp(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns 2^x. If x is a vector, operates componentwise. */ DSLExpression Exp2(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * If dot(i, nref) >= 0, returns n, otherwise returns -n. */ DSLExpression Faceforward(DSLExpression n, DSLExpression i, DSLExpression nref, PositionInfo pos = PositionInfo::Capture()); /** * Returns x rounded towards negative infinity. If x is a vector, operates componentwise. */ DSLExpression Floor(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns the fractional part of x. If x is a vector, operates componentwise. */ DSLExpression Fract(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns a boolean vector indicating whether components of x are greater than the corresponding * components of y. */ DSLExpression GreaterThan(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture()); /** * Returns a boolean vector indicating whether components of x are greater than or equal to the * corresponding components of y. */ DSLExpression GreaterThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture()); /** * Returns the 1/sqrt(x). If x is a vector, operates componentwise. */ DSLExpression Inversesqrt(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns the inverse of the matrix x. */ DSLExpression Inverse(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns the length of the vector x. */ DSLExpression Length(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns a boolean vector indicating whether components of x are less than the corresponding * components of y. */ DSLExpression LessThan(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture()); /** * Returns a boolean vector indicating whether components of x are less than or equal to the * corresponding components of y. */ DSLExpression LessThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture()); /** * Returns the log base e of x. If x is a vector, operates componentwise. */ DSLExpression Log(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns the log base 2 of x. If x is a vector, operates componentwise. */ DSLExpression Log2(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns the larger (closer to positive infinity) of x and y. If x is a vector, operates * componentwise. y may be either a vector of the same dimensions as x, or a scalar. */ DSLExpression Max(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture()); /** * Returns the smaller (closer to negative infinity) of x and y. If x is a vector, operates * componentwise. y may be either a vector of the same dimensions as x, or a scalar. */ DSLExpression Min(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture()); /** * Returns a linear intepolation between x and y at position a, where a=0 results in x and a=1 * results in y. If x and y are vectors, operates componentwise. a may be either a vector of the * same dimensions as x and y, or a scalar. */ DSLExpression Mix(DSLExpression x, DSLExpression y, DSLExpression a, PositionInfo pos = PositionInfo::Capture()); /** * Returns x modulo y. If x is a vector, operates componentwise. y may be either a vector of the * same dimensions as x, or a scalar. */ DSLExpression Mod(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture()); /** * Returns the vector x normalized to a length of 1. */ DSLExpression Normalize(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns a boolean vector indicating whether components of x are not equal to the corresponding * components of y. */ DSLExpression NotEqual(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture()); /** * Returns x raised to the power y. If x is a vector, operates componentwise. y may be either a * vector of the same dimensions as x, or a scalar. */ DSLExpression Pow(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture()); /** * Returns x converted from degrees to radians. If x is a vector, operates componentwise. */ DSLExpression Radians(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns i reflected from a surface with normal n. */ DSLExpression Reflect(DSLExpression i, DSLExpression n, PositionInfo pos = PositionInfo::Capture()); /** * Returns i refracted across a surface with normal n and ratio of indices of refraction eta. */ DSLExpression Refract(DSLExpression i, DSLExpression n, DSLExpression eta, PositionInfo pos = PositionInfo::Capture()); /** * Samples the child processor at the current coordinates. */ DSLExpression Sample(DSLExpression fp, PositionInfo pos = PositionInfo::Capture()); /** * Implements the following functions: * half4 sample(fragmentProcessor fp, float2 coords); * half4 sample(fragmentProcessor fp, half4 input); */ DSLExpression Sample(DSLExpression target, DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Implements the following functions: * half4 sample(fragmentProcessor fp, float2 coords, half4 input); */ DSLExpression Sample(DSLExpression childProcessor, DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture()); /** * Returns x clamped to the range [0, 1]. If x is a vector, operates componentwise. */ DSLExpression Saturate(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns -1, 0, or 1 depending on whether x is negative, zero, or positive, respectively. If x is * a vector, operates componentwise. */ DSLExpression Sign(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns the sine of x. If x is a vector, operates componentwise. */ DSLExpression Sin(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns a smooth interpolation between 0 (at x=edge1) and 1 (at x=edge2). If x is a vector, * operates componentwise. edge1 and edge2 may either be both vectors of the same dimensions as x or * scalars. */ DSLExpression Smoothstep(DSLExpression edge1, DSLExpression edge2, DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns the square root of x. If x is a vector, operates componentwise. */ DSLExpression Sqrt(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns 0 if x < edge or 1 if x >= edge. If x is a vector, operates componentwise. edge may be * either a vector of the same dimensions as x, or a scalar. */ DSLExpression Step(DSLExpression edge, DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns the tangent of x. If x is a vector, operates componentwise. */ DSLExpression Tan(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); /** * Returns x converted from premultipled to unpremultiplied alpha. */ DSLExpression Unpremul(DSLExpression x, PositionInfo pos = PositionInfo::Capture()); } // namespace dsl } // namespace SkSL #endif