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