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