1 /*
2 * Copyright 2018 Google Inc.
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
9 #include "include/gpu/GrContext.h"
10
11 #include "include/gpu/GrContextThreadSafeProxy.h"
12 #include "src/gpu/GrContextPriv.h"
13 #include "src/gpu/GrContextThreadSafeProxyPriv.h"
14 #include "src/gpu/GrGpu.h"
15
16 #include "src/gpu/effects/GrSkSLFP.h"
17 #include "src/gpu/gl/GrGLGpu.h"
18 #include "src/gpu/mock/GrMockGpu.h"
19 #include "src/gpu/text/GrStrikeCache.h"
20 #ifdef SK_METAL
21 #include "src/gpu/mtl/GrMtlTrampoline.h"
22 #endif
23 #ifdef SK_VULKAN
24 #include "src/gpu/vk/GrVkGpu.h"
25 #endif
26 #ifdef SK_DIRECT3D
27 #include "src/gpu/d3d/GrD3DGpu.h"
28 #endif
29 #ifdef SK_DAWN
30 #include "src/gpu/dawn/GrDawnGpu.h"
31 #endif
32
33 #ifdef SK_DISABLE_REDUCE_OPLIST_SPLITTING
34 static const bool kDefaultReduceOpsTaskSplitting = false;
35 #else
36 static const bool kDefaultReduceOpsTaskSplitting = false;
37 #endif
38
39 class GrLegacyDirectContext : public GrContext {
40 public:
GrLegacyDirectContext(GrBackendApi backend,const GrContextOptions & options)41 GrLegacyDirectContext(GrBackendApi backend, const GrContextOptions& options)
42 : INHERITED(backend, options)
43 , fAtlasManager(nullptr) {
44 }
45
~GrLegacyDirectContext()46 ~GrLegacyDirectContext() override {
47 // this if-test protects against the case where the context is being destroyed
48 // before having been fully created
49 if (this->priv().getGpu()) {
50 this->flush();
51 }
52
53 delete fAtlasManager;
54 }
55
abandonContext()56 void abandonContext() override {
57 INHERITED::abandonContext();
58 fAtlasManager->freeAll();
59 }
60
releaseResourcesAndAbandonContext()61 void releaseResourcesAndAbandonContext() override {
62 INHERITED::releaseResourcesAndAbandonContext();
63 fAtlasManager->freeAll();
64 }
65
freeGpuResources()66 void freeGpuResources() override {
67 this->flush();
68 fAtlasManager->freeAll();
69
70 INHERITED::freeGpuResources();
71 }
72
73 protected:
init(sk_sp<const GrCaps> caps)74 bool init(sk_sp<const GrCaps> caps) override {
75 SkASSERT(caps);
76 SkASSERT(!fThreadSafeProxy);
77
78 fThreadSafeProxy = GrContextThreadSafeProxyPriv::Make(this->backend(),
79 this->options(),
80 this->contextID(),
81 caps);
82
83 if (!INHERITED::init(std::move(caps))) {
84 return false;
85 }
86
87 bool reduceOpsTaskSplitting = kDefaultReduceOpsTaskSplitting;
88 if (GrContextOptions::Enable::kNo == this->options().fReduceOpsTaskSplitting) {
89 reduceOpsTaskSplitting = false;
90 } else if (GrContextOptions::Enable::kYes == this->options().fReduceOpsTaskSplitting) {
91 reduceOpsTaskSplitting = true;
92 }
93
94 this->setupDrawingManager(true, reduceOpsTaskSplitting);
95
96 SkASSERT(this->caps());
97
98 GrDrawOpAtlas::AllowMultitexturing allowMultitexturing;
99 if (GrContextOptions::Enable::kNo == this->options().fAllowMultipleGlyphCacheTextures ||
100 // multitexturing supported only if range can represent the index + texcoords fully
101 !(this->caps()->shaderCaps()->floatIs32Bits() ||
102 this->caps()->shaderCaps()->integerSupport())) {
103 allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kNo;
104 } else {
105 allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes;
106 }
107
108 GrStrikeCache* glyphCache = this->priv().getGrStrikeCache();
109 GrProxyProvider* proxyProvider = this->priv().proxyProvider();
110
111 fAtlasManager = new GrAtlasManager(proxyProvider, glyphCache,
112 this->options().fGlyphCacheTextureMaximumBytes,
113 allowMultitexturing);
114 this->priv().addOnFlushCallbackObject(fAtlasManager);
115
116 return true;
117 }
118
onGetAtlasManager()119 GrAtlasManager* onGetAtlasManager() override { return fAtlasManager; }
120
121 private:
122 GrAtlasManager* fAtlasManager;
123
124 typedef GrContext INHERITED;
125 };
126
127 #ifdef SK_GL
MakeGL(sk_sp<const GrGLInterface> glInterface)128 sk_sp<GrContext> GrContext::MakeGL(sk_sp<const GrGLInterface> glInterface) {
129 GrContextOptions defaultOptions;
130 return MakeGL(std::move(glInterface), defaultOptions);
131 }
132
MakeGL(const GrContextOptions & options)133 sk_sp<GrContext> GrContext::MakeGL(const GrContextOptions& options) {
134 return MakeGL(nullptr, options);
135 }
136
MakeGL()137 sk_sp<GrContext> GrContext::MakeGL() {
138 GrContextOptions defaultOptions;
139 return MakeGL(nullptr, defaultOptions);
140 }
141
MakeGL(sk_sp<const GrGLInterface> glInterface,const GrContextOptions & options)142 sk_sp<GrContext> GrContext::MakeGL(sk_sp<const GrGLInterface> glInterface,
143 const GrContextOptions& options) {
144 sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kOpenGL, options));
145
146 context->fGpu = GrGLGpu::Make(std::move(glInterface), options, context.get());
147 if (!context->fGpu) {
148 return nullptr;
149 }
150
151 if (!context->init(context->fGpu->refCaps())) {
152 return nullptr;
153 }
154 return context;
155 }
156 #endif
157
MakeMock(const GrMockOptions * mockOptions)158 sk_sp<GrContext> GrContext::MakeMock(const GrMockOptions* mockOptions) {
159 GrContextOptions defaultOptions;
160 return MakeMock(mockOptions, defaultOptions);
161 }
162
MakeMock(const GrMockOptions * mockOptions,const GrContextOptions & options)163 sk_sp<GrContext> GrContext::MakeMock(const GrMockOptions* mockOptions,
164 const GrContextOptions& options) {
165 sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kMock, options));
166
167 context->fGpu = GrMockGpu::Make(mockOptions, options, context.get());
168 if (!context->fGpu) {
169 return nullptr;
170 }
171
172 if (!context->init(context->fGpu->refCaps())) {
173 return nullptr;
174 }
175
176 return context;
177 }
178
MakeVulkan(const GrVkBackendContext & backendContext)179 sk_sp<GrContext> GrContext::MakeVulkan(const GrVkBackendContext& backendContext) {
180 #ifdef SK_VULKAN
181 GrContextOptions defaultOptions;
182 return MakeVulkan(backendContext, defaultOptions);
183 #else
184 return nullptr;
185 #endif
186 }
187
MakeVulkan(const GrVkBackendContext & backendContext,const GrContextOptions & options)188 sk_sp<GrContext> GrContext::MakeVulkan(const GrVkBackendContext& backendContext,
189 const GrContextOptions& options) {
190 #ifdef SK_VULKAN
191 sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kVulkan, options));
192
193 context->fGpu = GrVkGpu::Make(backendContext, options, context.get());
194 if (!context->fGpu) {
195 return nullptr;
196 }
197
198 if (!context->init(context->fGpu->refCaps())) {
199 return nullptr;
200 }
201 return context;
202 #else
203 return nullptr;
204 #endif
205 }
206
207 #ifdef SK_METAL
MakeMetal(void * device,void * queue)208 sk_sp<GrContext> GrContext::MakeMetal(void* device, void* queue) {
209 GrContextOptions defaultOptions;
210 return MakeMetal(device, queue, defaultOptions);
211 }
212
MakeMetal(void * device,void * queue,const GrContextOptions & options)213 sk_sp<GrContext> GrContext::MakeMetal(void* device, void* queue, const GrContextOptions& options) {
214 sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kMetal, options));
215
216 context->fGpu = GrMtlTrampoline::MakeGpu(context.get(), options, device, queue);
217 if (!context->fGpu) {
218 return nullptr;
219 }
220
221 if (!context->init(context->fGpu->refCaps())) {
222 return nullptr;
223 }
224 return context;
225 }
226 #endif
227
228 #ifdef SK_DIRECT3D
MakeDirect3D(const GrD3DBackendContext & backendContext)229 sk_sp<GrContext> GrContext::MakeDirect3D(const GrD3DBackendContext& backendContext) {
230 GrContextOptions defaultOptions;
231 return MakeDirect3D(backendContext, defaultOptions);
232 }
233
MakeDirect3D(const GrD3DBackendContext & backendContext,const GrContextOptions & options)234 sk_sp<GrContext> GrContext::MakeDirect3D(const GrD3DBackendContext& backendContext,
235 const GrContextOptions& options) {
236 sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kDirect3D, options));
237
238 context->fGpu = GrD3DGpu::Make(backendContext, options, context.get());
239 if (!context->fGpu) {
240 return nullptr;
241 }
242
243 if (!context->init(context->fGpu->refCaps())) {
244 return nullptr;
245 }
246 return context;
247 }
248 #endif
249
250 #ifdef SK_DAWN
MakeDawn(const wgpu::Device & device)251 sk_sp<GrContext> GrContext::MakeDawn(const wgpu::Device& device) {
252 GrContextOptions defaultOptions;
253 return MakeDawn(device, defaultOptions);
254 }
255
MakeDawn(const wgpu::Device & device,const GrContextOptions & options)256 sk_sp<GrContext> GrContext::MakeDawn(const wgpu::Device& device, const GrContextOptions& options) {
257 sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kDawn, options));
258
259 context->fGpu = GrDawnGpu::Make(device, options, context.get());
260 if (!context->fGpu) {
261 return nullptr;
262 }
263
264 if (!context->init(context->fGpu->refCaps())) {
265 return nullptr;
266 }
267 return context;
268 }
269 #endif
270