1 /*
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 #include "src/sksl/SkSLThreadContext.h"
9
10 #include "include/sksl/DSLSymbols.h"
11 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
12 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
13 #endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
14 #include "src/sksl/SkSLBuiltinMap.h"
15 #include "src/sksl/SkSLCompiler.h"
16 #include "src/sksl/ir/SkSLExternalFunction.h"
17
18 namespace SkSL {
19
ThreadContext(SkSL::Compiler * compiler,SkSL::ProgramKind kind,const SkSL::ProgramSettings & settings,SkSL::ParsedModule module,bool isModule)20 ThreadContext::ThreadContext(SkSL::Compiler* compiler, SkSL::ProgramKind kind,
21 const SkSL::ProgramSettings& settings, SkSL::ParsedModule module, bool isModule)
22 : fCompiler(compiler)
23 , fOldErrorReporter(*fCompiler->fContext->fErrors)
24 , fSettings(settings) {
25 fOldModifiersPool = fCompiler->fContext->fModifiersPool;
26
27 fOldConfig = fCompiler->fContext->fConfig;
28
29 if (!isModule) {
30 if (compiler->context().fCaps.useNodePools() && settings.fDSLUseMemoryPool) {
31 fPool = Pool::Create();
32 fPool->attachToThread();
33 }
34 fModifiersPool = std::make_unique<SkSL::ModifiersPool>();
35 fCompiler->fContext->fModifiersPool = fModifiersPool.get();
36 }
37
38 fConfig = std::make_unique<SkSL::ProgramConfig>();
39 fConfig->fKind = kind;
40 fConfig->fSettings = settings;
41 fConfig->fIsBuiltinCode = isModule;
42 fCompiler->fContext->fConfig = fConfig.get();
43 fCompiler->fContext->fErrors = &fDefaultErrorReporter;
44 fCompiler->fContext->fBuiltins = module.fElements.get();
45 if (fCompiler->fContext->fBuiltins) {
46 fCompiler->fContext->fBuiltins->resetAlreadyIncluded();
47 }
48
49 fCompiler->fSymbolTable = module.fSymbols;
50 this->setupSymbolTable();
51 }
52
~ThreadContext()53 ThreadContext::~ThreadContext() {
54 if (SymbolTable()) {
55 fCompiler->fSymbolTable = nullptr;
56 fProgramElements.clear();
57 } else {
58 // We should only be here with a null symbol table if ReleaseProgram was called
59 SkASSERT(fProgramElements.empty());
60 }
61 fCompiler->fContext->fErrors = &fOldErrorReporter;
62 fCompiler->fContext->fConfig = fOldConfig;
63 fCompiler->fContext->fModifiersPool = fOldModifiersPool;
64 if (fPool) {
65 fPool->detachFromThread();
66 }
67 }
68
setupSymbolTable()69 void ThreadContext::setupSymbolTable() {
70 SkSL::Context& context = *fCompiler->fContext;
71 SymbolTable::Push(&fCompiler->fSymbolTable, context.fConfig->fIsBuiltinCode);
72
73 if (fSettings.fExternalFunctions) {
74 // Add any external values to the new symbol table, so they're only visible to this Program.
75 SkSL::SymbolTable& symbols = *fCompiler->fSymbolTable;
76 for (const std::unique_ptr<ExternalFunction>& ef : *fSettings.fExternalFunctions) {
77 symbols.addWithoutOwnership(ef.get());
78 }
79 }
80 }
81
Context()82 SkSL::Context& ThreadContext::Context() {
83 return Compiler().context();
84 }
85
Settings()86 const SkSL::ProgramSettings& ThreadContext::Settings() {
87 return Context().fConfig->fSettings;
88 }
89
SymbolTable()90 std::shared_ptr<SkSL::SymbolTable>& ThreadContext::SymbolTable() {
91 return Compiler().fSymbolTable;
92 }
93
Modifiers(const SkSL::Modifiers & modifiers)94 const SkSL::Modifiers* ThreadContext::Modifiers(const SkSL::Modifiers& modifiers) {
95 return Context().fModifiersPool->add(modifiers);
96 }
97
RTAdjustState()98 ThreadContext::RTAdjustData& ThreadContext::RTAdjustState() {
99 return Instance().fRTAdjust;
100 }
101
102 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
StartFragmentProcessor(GrFragmentProcessor::ProgramImpl * processor,GrFragmentProcessor::ProgramImpl::EmitArgs * emitArgs)103 void ThreadContext::StartFragmentProcessor(GrFragmentProcessor::ProgramImpl* processor,
104 GrFragmentProcessor::ProgramImpl::EmitArgs* emitArgs) {
105 ThreadContext& instance = ThreadContext::Instance();
106 instance.fStack.push({processor, emitArgs, StatementArray{}});
107 CurrentEmitArgs()->fFragBuilder->fDeclarations.swap(instance.fStack.top().fSavedDeclarations);
108 dsl::PushSymbolTable();
109 }
110
EndFragmentProcessor()111 void ThreadContext::EndFragmentProcessor() {
112 ThreadContext& instance = Instance();
113 SkASSERT(!instance.fStack.empty());
114 CurrentEmitArgs()->fFragBuilder->fDeclarations.swap(instance.fStack.top().fSavedDeclarations);
115 instance.fStack.pop();
116 dsl::PopSymbolTable();
117 }
118 #endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
119
SetErrorReporter(ErrorReporter * errorReporter)120 void ThreadContext::SetErrorReporter(ErrorReporter* errorReporter) {
121 SkASSERT(errorReporter);
122 Context().fErrors = errorReporter;
123 }
124
ReportError(std::string_view msg,PositionInfo info)125 void ThreadContext::ReportError(std::string_view msg, PositionInfo info) {
126 GetErrorReporter().error(msg, info);
127 }
128
handleError(std::string_view msg,PositionInfo pos)129 void ThreadContext::DefaultErrorReporter::handleError(std::string_view msg, PositionInfo pos) {
130 if (pos.line() > -1) {
131 SK_ABORT("error: %s: %d: %.*sNo SkSL error reporter configured, treating this as a fatal "
132 "error\n", pos.file_name(), pos.line(), (int)msg.length(), msg.data());
133 } else {
134 SK_ABORT("error: %.*s\nNo SkSL error reporter configured, treating this as a fatal error\n",
135 (int)msg.length(), msg.data());
136 }
137
138 }
139
ReportErrors(PositionInfo pos)140 void ThreadContext::ReportErrors(PositionInfo pos) {
141 GetErrorReporter().reportPendingErrors(pos);
142 }
143
144 thread_local ThreadContext* instance = nullptr;
145
IsActive()146 bool ThreadContext::IsActive() {
147 return instance != nullptr;
148 }
149
Instance()150 ThreadContext& ThreadContext::Instance() {
151 SkASSERTF(instance, "dsl::Start() has not been called");
152 return *instance;
153 }
154
SetInstance(std::unique_ptr<ThreadContext> newInstance)155 void ThreadContext::SetInstance(std::unique_ptr<ThreadContext> newInstance) {
156 SkASSERT((instance == nullptr) != (newInstance == nullptr));
157 delete instance;
158 instance = newInstance.release();
159 }
160
161 } // namespace SkSL
162