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:
28     GrDirectContext(GrBackendApi backend)
29             : INHERITED(backend)
30             , fAtlasManager(nullptr) {
31     }
32 
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 
43     void abandonContext() override {
44         INHERITED::abandonContext();
45         fAtlasManager->freeAll();
46     }
47 
48     void releaseResourcesAndAbandonContext() override {
49         INHERITED::releaseResourcesAndAbandonContext();
50         fAtlasManager->freeAll();
51     }
52 
53     void freeGpuResources() override {
54         this->flush();
55         fAtlasManager->freeAll();
56 
57         INHERITED::freeGpuResources();
58     }
59 
60 protected:
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 
94     GrAtlasManager* onGetAtlasManager() override { return fAtlasManager; }
95 
96 private:
97     GrAtlasManager* fAtlasManager;
98 
99     typedef GrContext INHERITED;
100 };
101 
102 sk_sp<GrContext> GrContext::MakeGL(sk_sp<const GrGLInterface> interface) {
103     GrContextOptions defaultOptions;
104     return MakeGL(std::move(interface), defaultOptions);
105 }
106 
107 sk_sp<GrContext> GrContext::MakeGL(const GrContextOptions& options) {
108     return MakeGL(nullptr, options);
109 }
110 
111 sk_sp<GrContext> GrContext::MakeGL() {
112     GrContextOptions defaultOptions;
113     return MakeGL(nullptr, defaultOptions);
114 }
115 
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 
132 sk_sp<GrContext> GrContext::MakeMock(const GrMockOptions* mockOptions) {
133     GrContextOptions defaultOptions;
134     return MakeMock(mockOptions, defaultOptions);
135 }
136 
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 
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 
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
184 sk_sp<GrContext> GrContext::MakeMetal(void* device, void* queue) {
185     GrContextOptions defaultOptions;
186     return MakeMetal(device, queue, defaultOptions);
187 }
188 
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