• 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/SkTypes.h"
12 #include "include/sksl/SkSLErrorReporter.h"
13 #include "include/sksl/SkSLPosition.h"
14 #include "src/sksl/SkSLContext.h"
15 #include "src/sksl/SkSLProgramSettings.h"
16 #include "src/sksl/ir/SkSLProgram.h"
17 
18 #include <cstdint>
19 #include <memory>
20 #include <string_view>
21 #include <vector>
22 
23 namespace SkSL {
24 
25 class Compiler;
26 class ModifiersPool;
27 class Pool;
28 class ProgramElement;
29 class SymbolTable;
30 class Variable;
31 enum class ProgramKind : int8_t;
32 struct Modifiers;
33 struct Module;
34 
35 namespace dsl {
36 
37 class DSLCore;
38 
39 } // namespace dsl
40 
41 /**
42  * Thread-safe class that tracks per-thread state associated with SkSL output.
43  */
44 class ThreadContext {
45 public:
46     ThreadContext(SkSL::Compiler* compiler,
47                   SkSL::ProgramKind kind,
48                   const SkSL::ProgramSettings& settings,
49                   const SkSL::Module* module,
50                   bool isModule);
51     ~ThreadContext();
52 
53     /**
54      * Returns true if the DSL has been started.
55      */
56     static bool IsActive();
57 
58     /**
59      * Returns the Compiler used by DSL operations in the current thread.
60      */
Compiler()61     static SkSL::Compiler& Compiler() { return *Instance().fCompiler; }
62 
63     /**
64      * Returns the Context used by DSL operations in the current thread.
65      */
66     static SkSL::Context& Context();
67 
68     /**
69      * Returns the Settings used by DSL operations in the current thread.
70      */
71     static const SkSL::ProgramSettings& Settings();
72 
73     /**
74      * Returns the Program::Inputs used by the current thread.
75      */
Inputs()76     static SkSL::Program::Inputs& Inputs() { return Instance().fInputs; }
77 
78     /**
79      * Returns the collection to which DSL program elements in this thread should be appended.
80      */
ProgramElements()81     static std::vector<std::unique_ptr<SkSL::ProgramElement>>& ProgramElements() {
82         return Instance().fProgramElements;
83     }
84 
SharedElements()85     static std::vector<const ProgramElement*>& SharedElements() {
86         return Instance().fSharedElements;
87     }
88 
89     /**
90      * Returns the current SymbolTable.
91      */
92     static std::shared_ptr<SkSL::SymbolTable>& SymbolTable();
93 
94     /**
95      * Returns the current memory pool.
96      */
MemoryPool()97     static std::unique_ptr<Pool>& MemoryPool() { return Instance().fPool; }
98 
99     /**
100      * Returns the current modifiers pool.
101      */
GetModifiersPool()102     static std::unique_ptr<ModifiersPool>& GetModifiersPool() { return Instance().fModifiersPool; }
103 
104     /**
105      * Returns the current ProgramConfig.
106      */
GetProgramConfig()107     static const std::unique_ptr<ProgramConfig>& GetProgramConfig() { return Instance().fConfig; }
108 
IsModule()109     static bool IsModule() { return GetProgramConfig()->fIsBuiltinCode; }
110 
111     /**
112      * Returns the final pointer to a pooled Modifiers object that should be used to represent the
113      * given modifiers.
114      */
115     static const SkSL::Modifiers* Modifiers(const SkSL::Modifiers& modifiers);
116 
117     struct RTAdjustData {
118         // Points to a standalone sk_RTAdjust variable, if one exists.
119         const Variable* fVar = nullptr;
120         // Points to the interface block containing an sk_RTAdjust field, if one exists.
121         const Variable* fInterfaceBlock = nullptr;
122         // If fInterfaceBlock is non-null, contains the index of the sk_RTAdjust field within it.
123         int fFieldIndex = -1;
124     };
125 
126     /**
127      * Returns a struct containing information about the RTAdjust variable.
128      */
129     static RTAdjustData& RTAdjustState();
130 
131     /**
132      * Returns the ErrorReporter associated with the current thread. This object will be notified
133      * when any DSL errors occur.
134      */
GetErrorReporter()135     static ErrorReporter& GetErrorReporter() {
136         return *Context().fErrors;
137     }
138 
139     static void SetErrorReporter(ErrorReporter* errorReporter);
140 
141     /**
142      * Notifies the current ErrorReporter that an error has occurred. The default error handler
143      * prints the message to stderr and aborts.
144      */
145     static void ReportError(std::string_view msg, Position pos = Position{});
146 
147     static ThreadContext& Instance();
148 
149     static void SetInstance(std::unique_ptr<ThreadContext> instance);
150 
151 private:
152     class DefaultErrorReporter : public ErrorReporter {
153         void handleError(std::string_view msg, Position pos) override;
154     };
155 
156     void setupSymbolTable();
157 
158     std::unique_ptr<SkSL::ProgramConfig> fConfig;
159     std::unique_ptr<SkSL::ModifiersPool> fModifiersPool;
160     SkSL::Compiler* fCompiler;
161     std::unique_ptr<Pool> fPool;
162     SkSL::ProgramConfig* fOldConfig;
163     SkSL::ModifiersPool* fOldModifiersPool;
164     std::vector<std::unique_ptr<SkSL::ProgramElement>> fProgramElements;
165     std::vector<const SkSL::ProgramElement*> fSharedElements;
166     DefaultErrorReporter fDefaultErrorReporter;
167     ErrorReporter& fOldErrorReporter;
168     ProgramSettings fSettings;
169     RTAdjustData fRTAdjust;
170     Program::Inputs fInputs;
171 
172     friend class dsl::DSLCore;
173 };
174 
175 } // namespace SkSL
176 
177 #endif
178