blob: b2665ea86779005e225bc7d32afb89fc218af763 [file] [log] [blame]
Ethan Nicholas95046142021-01-07 10:57:27 -05001/*
2 * Copyright 2020 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SKSL_DSLWRITER
9#define SKSL_DSLWRITER
10
Ethan Nicholasbffe80a2021-01-11 15:42:44 -050011#include "src/sksl/SkSLMangler.h"
Ethan Nicholas95046142021-01-07 10:57:27 -050012#include "src/sksl/dsl/DSLExpression.h"
Ethan Nicholascfefec02021-02-09 15:22:57 -050013#include "src/sksl/dsl/DSLStatement.h"
Ethan Nicholas95046142021-01-07 10:57:27 -050014#include "src/sksl/ir/SkSLExpressionStatement.h"
15#include "src/sksl/ir/SkSLProgram.h"
16#include "src/sksl/ir/SkSLStatement.h"
17#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
18#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
19#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
20
21#include <stack>
22
23class AutoDSLContext;
24
25namespace SkSL {
26
27class Compiler;
28class Context;
29class IRGenerator;
30class SymbolTable;
31class Type;
32
33namespace dsl {
34
35class ErrorHandler;
36
37/**
38 * Thread-safe class that tracks per-thread state associated with DSL output. This class is for
39 * internal use only.
40 */
41class DSLWriter {
42public:
43 DSLWriter(SkSL::Compiler* compiler);
44
45 /**
46 * Returns the Compiler used by DSL operations in the current thread.
47 */
48 static SkSL::Compiler& Compiler() {
49 return *Instance().fCompiler;
50 }
51
52 /**
53 * Returns the IRGenerator used by DSL operations in the current thread.
54 */
55 static SkSL::IRGenerator& IRGenerator();
56
57 /**
58 * Returns the Context used by DSL operations in the current thread.
59 */
60 static const SkSL::Context& Context();
61
62 /**
Ethan Nicholas1ff76092021-01-28 10:02:43 -050063 * Returns the collection to which DSL program elements in this thread should be appended.
64 */
65 static std::vector<std::unique_ptr<SkSL::ProgramElement>>& ProgramElements() {
66 return Instance().fProgramElements;
67 }
68
69 /**
Ethan Nicholas95046142021-01-07 10:57:27 -050070 * Returns the SymbolTable of the current thread's IRGenerator.
71 */
72 static const std::shared_ptr<SkSL::SymbolTable>& SymbolTable();
73
74 /**
Ethan Nicholasbffe80a2021-01-11 15:42:44 -050075 * Returns the final pointer to a pooled Modifiers object that should be used to represent the
76 * given modifiers.
77 */
78 static const SkSL::Modifiers* Modifiers(SkSL::Modifiers modifiers);
79
80 /**
Ethan Nicholasd6b26e52021-01-27 07:53:46 -050081 * Returns the SkSL variable corresponding to a DSLVar.
82 */
83 static const SkSL::Variable& Var(const DSLVar& var);
84
85 /**
Ethan Nicholasbffe80a2021-01-11 15:42:44 -050086 * Returns the (possibly mangled) final name that should be used for an entity with the given
87 * raw name.
88 */
89 static const char* Name(const char* name);
90
Ethan Nicholasc3bb9e32021-02-02 11:51:03 -050091#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
92 /**
93 * Returns the fragment processor for which DSL output is being generated for the current
94 * thread.
95 */
96 static GrGLSLFragmentProcessor* CurrentProcessor() {
97 SkASSERTF(!Instance().fStack.empty(), "This feature requires a FragmentProcessor");
98 return Instance().fStack.top().fProcessor;
99 }
100
101 /**
102 * Returns the EmitArgs for fragment processor output in the current thread.
103 */
104 static GrGLSLFragmentProcessor::EmitArgs* CurrentEmitArgs() {
105 SkASSERTF(!Instance().fStack.empty(), "This feature requires a FragmentProcessor");
106 return Instance().fStack.top().fEmitArgs;
107 }
108
109 /**
110 * Pushes a new processor / emitArgs pair for the current thread.
111 */
112 static void StartFragmentProcessor(GrGLSLFragmentProcessor* processor,
113 GrGLSLFragmentProcessor::EmitArgs* emitArgs);
114
115 /**
116 * Pops the processor / emitArgs pair associated with the current thread.
117 */
118 static void EndFragmentProcessor();
119#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
120
Ethan Nicholas1ff76092021-01-28 10:02:43 -0500121 /**
Ethan Nicholas95046142021-01-07 10:57:27 -0500122 * Reports an error if the argument is null. Returns its argument unmodified.
123 */
124 static std::unique_ptr<SkSL::Expression> Check(std::unique_ptr<SkSL::Expression> expr);
125
Ethan Nicholas92969f22021-01-13 10:38:59 -0500126 static DSLExpression Coerce(std::unique_ptr<Expression> left, const SkSL::Type& type);
127
Ethan Nicholasb3d4e742021-01-08 11:42:25 -0500128 static DSLExpression Construct(const SkSL::Type& type, std::vector<DSLExpression> rawArgs);
129
Ethan Nicholas92969f22021-01-13 10:38:59 -0500130 static DSLExpression ConvertBinary(std::unique_ptr<Expression> left, Token::Kind op,
131 std::unique_ptr<Expression> right);
132
133 static DSLExpression ConvertIndex(std::unique_ptr<Expression> base,
134 std::unique_ptr<Expression> index);
135
136 static DSLExpression ConvertPostfix(std::unique_ptr<Expression> expr, Token::Kind op);
137
138 static DSLExpression ConvertPrefix(Token::Kind op, std::unique_ptr<Expression> expr);
139
Ethan Nicholascfefec02021-02-09 15:22:57 -0500140 static DSLStatement ConvertSwitch(std::unique_ptr<Expression> value,
141 ExpressionArray caseValues,
142 SkTArray<SkSL::StatementArray> caseStatements);
143
144 static void Ignore(std::unique_ptr<SkSL::Expression>&) {}
145
Ethan Nicholas95046142021-01-07 10:57:27 -0500146 /**
147 * Sets the ErrorHandler associated with the current thread. This object will be notified when
148 * any DSL errors occur. With a null ErrorHandler (the default), any errors will be dumped to
149 * stderr and a fatal exception will be generated.
150 */
151 static void SetErrorHandler(ErrorHandler* errorHandler) {
152 Instance().fErrorHandler = errorHandler;
153 }
154
155 /**
156 * Notifies the current ErrorHandler that a DSL error has occurred. With a null ErrorHandler
157 * (the default), any errors will be dumped to stderr and a fatal exception will be generated.
158 */
159 static void ReportError(const char* msg);
160
Ethan Nicholasbffe80a2021-01-11 15:42:44 -0500161 /**
162 * Returns whether name mangling is enabled. This should always be enabled outside of tests.
163 */
164 static bool ManglingEnabled() {
165 return Instance().fMangle;
166 }
167
Ethan Nicholas95046142021-01-07 10:57:27 -0500168 static DSLWriter& Instance();
169
170 static void SetInstance(std::unique_ptr<DSLWriter> instance);
171
172private:
173 SkSL::Program::Settings fSettings;
174 SkSL::Compiler* fCompiler;
Ethan Nicholas1ff76092021-01-28 10:02:43 -0500175 std::vector<std::unique_ptr<SkSL::ProgramElement>> fProgramElements;
Ethan Nicholas95046142021-01-07 10:57:27 -0500176 ErrorHandler* fErrorHandler = nullptr;
Ethan Nicholasbffe80a2021-01-11 15:42:44 -0500177 bool fMangle = true;
178 Mangler fMangler;
Ethan Nicholasc3bb9e32021-02-02 11:51:03 -0500179#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
180 struct StackFrame {
181 GrGLSLFragmentProcessor* fProcessor;
182 GrGLSLFragmentProcessor::EmitArgs* fEmitArgs;
183 };
184 std::stack<StackFrame> fStack;
185#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
Ethan Nicholas95046142021-01-07 10:57:27 -0500186
187 friend class DSLCore;
188 friend class ::AutoDSLContext;
189};
190
191} // namespace dsl
192
193} // namespace SkSL
194
195#endif