blob: 8959f152c03717d5350a1ea732477c03b30e6232 [file] [log] [blame]
Ethan Nicholasc8452722021-10-07 10:47:32 -04001/*
2 * Copyright 2021 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_THREADCONTEXT
9#define SKSL_THREADCONTEXT
10
11#include "include/core/SkStringView.h"
12#include "include/private/SkSLModifiers.h"
13#include "src/sksl/SkSLMangler.h"
14#include "src/sksl/ir/SkSLProgram.h"
15#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
16#include "src/gpu/GrFragmentProcessor.h"
17#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
18#include <list>
19#include <stack>
20
21namespace SkSL {
22
23class Compiler;
24class Context;
25class IRGenerator;
26struct ParsedModule;
27class ProgramElement;
28class SymbolTable;
29class Type;
30class Variable;
31
32namespace dsl {
33
34class DSLCore;
35class DSLWriter;
36
37} // namespace dsl
38
39/**
40 * Thread-safe class that tracks per-thread state associated with SkSL output.
41 */
42class ThreadContext {
43public:
44 ThreadContext(SkSL::Compiler* compiler, SkSL::ProgramKind kind,
45 const SkSL::ProgramSettings& settings, SkSL::ParsedModule module, bool isModule);
46
47 ~ThreadContext();
48
49 /**
50 * Returns true if the DSL has been started.
51 */
52 static bool IsActive();
53
54 /**
55 * Returns the Compiler used by DSL operations in the current thread.
56 */
57 static SkSL::Compiler& Compiler() { return *Instance().fCompiler; }
58
59 /**
60 * Returns the IRGenerator used by DSL operations in the current thread.
61 */
62 static SkSL::IRGenerator& IRGenerator();
63
64 /**
65 * Returns the Context used by DSL operations in the current thread.
66 */
67 static SkSL::Context& Context();
68
69 /**
70 * Returns the Settings used by DSL operations in the current thread.
71 */
72 static SkSL::ProgramSettings& Settings();
73
74 /**
75 * Returns the Program::Inputs used by the current thread.
76 */
77 static SkSL::Program::Inputs& Inputs();
78
79 /**
80 * Returns the collection to which DSL program elements in this thread should be appended.
81 */
82 static std::vector<std::unique_ptr<SkSL::ProgramElement>>& ProgramElements() {
83 return Instance().fProgramElements;
84 }
85
86 static std::vector<const ProgramElement*>& SharedElements() {
87 return Instance().fSharedElements;
88 }
89
90 /**
91 * Returns the SymbolTable of the current thread's IRGenerator.
92 */
93 static const std::shared_ptr<SkSL::SymbolTable>& SymbolTable();
94
95 /**
96 * Returns the current memory pool.
97 */
98 static std::unique_ptr<Pool>& MemoryPool() { return Instance().fPool; }
99
100 /**
101 * Returns the current modifiers pool.
102 */
103 static std::unique_ptr<ModifiersPool>& GetModifiersPool() { return Instance().fModifiersPool; }
104
105 /**
106 * Returns the current ProgramConfig.
107 */
108 static std::unique_ptr<ProgramConfig>& GetProgramConfig() { return Instance().fConfig; }
109
110 static bool IsModule() { return GetProgramConfig()->fIsBuiltinCode; }
111
112 /**
113 * Returns the final pointer to a pooled Modifiers object that should be used to represent the
114 * given modifiers.
115 */
116 static const SkSL::Modifiers* Modifiers(const SkSL::Modifiers& modifiers);
117
118#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
119 /**
120 * Returns the fragment processor for which DSL output is being generated for the current
121 * thread.
122 */
123 static GrFragmentProcessor::ProgramImpl* CurrentProcessor() {
124 SkASSERTF(!Instance().fStack.empty(), "This feature requires a FragmentProcessor");
125 return Instance().fStack.top().fProcessor;
126 }
127
128 /**
129 * Returns the EmitArgs for fragment processor output in the current thread.
130 */
131 static GrFragmentProcessor::ProgramImpl::EmitArgs* CurrentEmitArgs() {
132 SkASSERTF(!Instance().fStack.empty(), "This feature requires a FragmentProcessor");
133 return Instance().fStack.top().fEmitArgs;
134 }
135
136 static bool InFragmentProcessor() {
137 return !Instance().fStack.empty();
138 }
139
140 /**
141 * Pushes a new processor / emitArgs pair for the current thread.
142 */
143 static void StartFragmentProcessor(GrFragmentProcessor::ProgramImpl* processor,
144 GrFragmentProcessor::ProgramImpl::EmitArgs* emitArgs);
145
146 /**
147 * Pops the processor / emitArgs pair associated with the current thread.
148 */
149 static void EndFragmentProcessor();
150#else
151 static bool InFragmentProcessor() {
152 return false;
153 }
154#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
155
156 /**
157 * Returns the ErrorReporter associated with the current thread. This object will be notified
158 * when any DSL errors occur.
159 */
160 static ErrorReporter& GetErrorReporter() {
161 return *Context().fErrors;
162 }
163
164 static void SetErrorReporter(ErrorReporter* errorReporter);
165
166 /**
167 * Notifies the current ErrorReporter that an error has occurred. The default error handler
168 * prints the message to stderr and aborts.
169 */
170 static void ReportError(skstd::string_view msg, PositionInfo info = PositionInfo::Capture());
171
172 /**
173 * Forwards any pending errors to the DSL ErrorReporter.
174 */
175 static void ReportErrors(PositionInfo pos);
176
177 static ThreadContext& Instance();
178
179 static void SetInstance(std::unique_ptr<ThreadContext> instance);
180
181private:
182 class DefaultErrorReporter : public ErrorReporter {
183 void handleError(skstd::string_view msg, PositionInfo pos) override;
184 };
185
186 std::unique_ptr<SkSL::ProgramConfig> fConfig;
187 std::unique_ptr<SkSL::ModifiersPool> fModifiersPool;
188 SkSL::Compiler* fCompiler;
189 std::unique_ptr<Pool> fPool;
190 SkSL::ProgramConfig* fOldConfig;
191 SkSL::ModifiersPool* fOldModifiersPool;
192 std::vector<std::unique_ptr<SkSL::ProgramElement>> fProgramElements;
193 std::vector<const SkSL::ProgramElement*> fSharedElements;
194 DefaultErrorReporter fDefaultErrorReporter;
195 ErrorReporter& fOldErrorReporter;
196 ProgramSettings fSettings;
197 Mangler fMangler;
198#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
199 struct StackFrame {
200 GrFragmentProcessor::ProgramImpl* fProcessor;
201 GrFragmentProcessor::ProgramImpl::EmitArgs* fEmitArgs;
202 SkSL::StatementArray fSavedDeclarations;
203 };
204 std::stack<StackFrame, std::list<StackFrame>> fStack;
205#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
206
207 friend class dsl::DSLCore;
208 friend class dsl::DSLWriter;
209};
210
211} // namespace SkSL
212
213#endif