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