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 "GrContext.h"
10
11 #include "GrContextPriv.h"
12 #include "GrContextThreadSafeProxy.h"
13 #include "GrContextThreadSafeProxyPriv.h"
14 #include "GrGpu.h"
15
16 #include "effects/GrSkSLFP.h"
17 #include "gl/GrGLGpu.h"
18 #include "mock/GrMockGpu.h"
19 #include "text/GrStrikeCache.h"
20 #ifdef SK_METAL
21 #include "mtl/GrMtlTrampoline.h"
22 #endif
23 #ifdef SK_VULKAN
24 #include "vk/GrVkGpu.h"
25 #endif
26
27 class SK_API GrLegacyDirectContext : public GrContext {
28 public:
GrLegacyDirectContext(GrBackendApi backend,const GrContextOptions & options)29 GrLegacyDirectContext(GrBackendApi backend, const GrContextOptions& options)
30 : INHERITED(backend, options)
31 , fAtlasManager(nullptr) {
32 }
33
~GrLegacyDirectContext()34 ~GrLegacyDirectContext() override {
35 // this if-test protects against the case where the context is being destroyed
36 // before having been fully created
37 if (this->priv().getGpu()) {
38 this->flush();
39 }
40
41 delete fAtlasManager;
42 }
43
abandonContext()44 void abandonContext() override {
45 INHERITED::abandonContext();
46 fAtlasManager->freeAll();
47 }
48
releaseResourcesAndAbandonContext()49 void releaseResourcesAndAbandonContext() override {
50 INHERITED::releaseResourcesAndAbandonContext();
51 fAtlasManager->freeAll();
52 }
53
freeGpuResources()54 void freeGpuResources() override {
55 this->flush();
56 fAtlasManager->freeAll();
57
58 INHERITED::freeGpuResources();
59 }
60
61 protected:
init(sk_sp<const GrCaps> caps,sk_sp<GrSkSLFPFactoryCache> FPFactoryCache)62 bool init(sk_sp<const GrCaps> caps, sk_sp<GrSkSLFPFactoryCache> FPFactoryCache) override {
63 SkASSERT(caps && !FPFactoryCache);
64 SkASSERT(!fThreadSafeProxy);
65
66 FPFactoryCache.reset(new GrSkSLFPFactoryCache());
67 fThreadSafeProxy = GrContextThreadSafeProxyPriv::Make(this->backend(),
68 this->options(),
69 this->contextID(),
70 caps, FPFactoryCache);
71
72 if (!INHERITED::init(std::move(caps), std::move(FPFactoryCache))) {
73 return false;
74 }
75
76 bool sortOpLists = this->explicitlyAllocateGPUResources();
77 if (GrContextOptions::Enable::kNo == this->options().fSortRenderTargets) {
78 sortOpLists = false;
79 } else if (GrContextOptions::Enable::kYes == this->options().fSortRenderTargets) {
80 sortOpLists = true;
81 }
82
83 this->setupDrawingManager(this->explicitlyAllocateGPUResources(), sortOpLists);
84
85 SkASSERT(this->caps());
86
87 GrDrawOpAtlas::AllowMultitexturing allowMultitexturing;
88 if (GrContextOptions::Enable::kNo == this->options().fAllowMultipleGlyphCacheTextures ||
89 // multitexturing supported only if range can represent the index + texcoords fully
90 !(this->caps()->shaderCaps()->floatIs32Bits() ||
91 this->caps()->shaderCaps()->integerSupport())) {
92 allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kNo;
93 } else {
94 allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes;
95 }
96
97 GrStrikeCache* glyphCache = this->priv().getGrStrikeCache();
98 GrProxyProvider* proxyProvider = this->priv().proxyProvider();
99
100 fAtlasManager = new GrAtlasManager(proxyProvider, glyphCache,
101 this->options().fGlyphCacheTextureMaximumBytes,
102 allowMultitexturing);
103 this->priv().addOnFlushCallbackObject(fAtlasManager);
104
105 return true;
106 }
107
onGetAtlasManager()108 GrAtlasManager* onGetAtlasManager() override { return fAtlasManager; }
109
110 private:
111 GrAtlasManager* fAtlasManager;
112
113 typedef GrContext INHERITED;
114 };
115
MakeGL(sk_sp<const GrGLInterface> interface)116 sk_sp<GrContext> GrContext::MakeGL(sk_sp<const GrGLInterface> interface) {
117 GrContextOptions defaultOptions;
118 return MakeGL(std::move(interface), defaultOptions);
119 }
120
MakeGL(const GrContextOptions & options)121 sk_sp<GrContext> GrContext::MakeGL(const GrContextOptions& options) {
122 return MakeGL(nullptr, options);
123 }
124
MakeGL()125 sk_sp<GrContext> GrContext::MakeGL() {
126 GrContextOptions defaultOptions;
127 return MakeGL(nullptr, defaultOptions);
128 }
129
MakeGL(sk_sp<const GrGLInterface> interface,const GrContextOptions & options)130 sk_sp<GrContext> GrContext::MakeGL(sk_sp<const GrGLInterface> interface,
131 const GrContextOptions& options) {
132 sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kOpenGL, options));
133
134 context->fGpu = GrGLGpu::Make(std::move(interface), options, context.get());
135 if (!context->fGpu) {
136 return nullptr;
137 }
138
139 if (!context->init(context->fGpu->refCaps(), nullptr)) {
140 return nullptr;
141 }
142 return context;
143 }
144
MakeMock(const GrMockOptions * mockOptions)145 sk_sp<GrContext> GrContext::MakeMock(const GrMockOptions* mockOptions) {
146 GrContextOptions defaultOptions;
147 return MakeMock(mockOptions, defaultOptions);
148 }
149
MakeMock(const GrMockOptions * mockOptions,const GrContextOptions & options)150 sk_sp<GrContext> GrContext::MakeMock(const GrMockOptions* mockOptions,
151 const GrContextOptions& options) {
152 sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kMock, options));
153
154 context->fGpu = GrMockGpu::Make(mockOptions, options, context.get());
155 if (!context->fGpu) {
156 return nullptr;
157 }
158
159 if (!context->init(context->fGpu->refCaps(), nullptr)) {
160 return nullptr;
161 }
162 return context;
163 }
164
MakeVulkan(const GrVkBackendContext & backendContext)165 sk_sp<GrContext> GrContext::MakeVulkan(const GrVkBackendContext& backendContext) {
166 #ifdef SK_VULKAN
167 GrContextOptions defaultOptions;
168 return MakeVulkan(backendContext, defaultOptions);
169 #else
170 return nullptr;
171 #endif
172 }
173
MakeVulkan(const GrVkBackendContext & backendContext,const GrContextOptions & options)174 sk_sp<GrContext> GrContext::MakeVulkan(const GrVkBackendContext& backendContext,
175 const GrContextOptions& options) {
176 #ifdef SK_VULKAN
177 GrContextOptions defaultOptions;
178 sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kVulkan, options));
179
180 context->fGpu = GrVkGpu::Make(backendContext, options, context.get());
181 if (!context->fGpu) {
182 return nullptr;
183 }
184
185 if (!context->init(context->fGpu->refCaps(), nullptr)) {
186 return nullptr;
187 }
188 return context;
189 #else
190 return nullptr;
191 #endif
192 }
193
194 #ifdef SK_METAL
MakeMetal(void * device,void * queue)195 sk_sp<GrContext> GrContext::MakeMetal(void* device, void* queue) {
196 GrContextOptions defaultOptions;
197 return MakeMetal(device, queue, defaultOptions);
198 }
199
MakeMetal(void * device,void * queue,const GrContextOptions & options)200 sk_sp<GrContext> GrContext::MakeMetal(void* device, void* queue, const GrContextOptions& options) {
201 sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kMetal, options));
202
203 context->fGpu = GrMtlTrampoline::MakeGpu(context.get(), options, device, queue);
204 if (!context->fGpu) {
205 return nullptr;
206 }
207
208 if (!context->init(context->fGpu->refCaps(), nullptr)) {
209 return nullptr;
210 }
211 return context;
212 }
213 #endif
214
215