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