blob: d0406dd6f6eb5d31367958421cfecf20cdc0aa81 [file] [log] [blame]
Robert Phillipsa3457b82018-03-08 11:30:12 -05001/*
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#include "GrContext.h"
9
10#include "GrContextPriv.h"
11#include "GrGpu.h"
12
13#include "gl/GrGLGpu.h"
14#include "mock/GrMockGpu.h"
15#include "text/GrGlyphCache.h"
16#ifdef SK_METAL
17#include "mtl/GrMtlTrampoline.h"
18#endif
19#ifdef SK_VULKAN
20#include "vk/GrVkGpu.h"
21#endif
22
23class SK_API GrDirectContext : public GrContext {
24public:
25 GrDirectContext(GrBackend backend)
26 : INHERITED(backend)
27 , fAtlasManager(nullptr) {
28 }
29
30 ~GrDirectContext() override {
31 // this if-test protects against the case where the context is being destroyed
32 // before having been fully created
33 if (this->contextPriv().getGpu()) {
34 this->flush();
35 }
36
37 delete fAtlasManager;
38 }
39
40 void abandonContext() override {
41 INHERITED::abandonContext();
42 fAtlasManager->freeAll();
43 }
44
45 void releaseResourcesAndAbandonContext() override {
46 INHERITED::releaseResourcesAndAbandonContext();
47 fAtlasManager->freeAll();
48 }
49
50 void freeGpuResources() override {
51 this->flush();
52 fAtlasManager->freeAll();
53
54 INHERITED::freeGpuResources();
55 }
56
57protected:
58 bool init(const GrContextOptions& options) override {
59 SkASSERT(fCaps); // should've been set in ctor
60 SkASSERT(!fThreadSafeProxy);
61
62 fThreadSafeProxy.reset(new GrContextThreadSafeProxy(fCaps, this->uniqueID(),
63 fBackend, options));
64
65 if (!INHERITED::initCommon(options)) {
66 return false;
67 }
68
69 GrDrawOpAtlas::AllowMultitexturing allowMultitexturing;
70 if (GrContextOptions::Enable::kNo == options.fAllowMultipleGlyphCacheTextures ||
71 // multitexturing supported only if range can represent the index + texcoords fully
72 !(fCaps->shaderCaps()->floatIs32Bits() || fCaps->shaderCaps()->integerSupport())) {
73 allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kNo;
74 } else {
75 allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes;
76 }
77
78 GrGlyphCache* glyphCache = this->contextPriv().getGlyphCache();
79 GrProxyProvider* proxyProvider = this->contextPriv().proxyProvider();
80
81 fAtlasManager = new GrAtlasManager(proxyProvider, glyphCache,
82 options.fGlyphCacheTextureMaximumBytes,
83 allowMultitexturing);
84 this->contextPriv().addOnFlushCallbackObject(fAtlasManager);
85
86 SkASSERT(glyphCache->getGlyphSizeLimit() == fAtlasManager->getGlyphSizeLimit());
87 return true;
88 }
89
90 GrAtlasManager* onGetAtlasManager() override { return fAtlasManager; }
91
92private:
93 GrAtlasManager* fAtlasManager;
94
95 typedef GrContext INHERITED;
96};
97
Robert Phillipsa3457b82018-03-08 11:30:12 -050098sk_sp<GrContext> GrContext::MakeGL(sk_sp<const GrGLInterface> interface) {
99 GrContextOptions defaultOptions;
100 return MakeGL(std::move(interface), defaultOptions);
101}
102
Brian Salomonc1b9c102018-04-06 09:18:00 -0400103sk_sp<GrContext> GrContext::MakeGL(const GrContextOptions& options) {
104 return MakeGL(nullptr, options);
105}
106
107sk_sp<GrContext> GrContext::MakeGL() {
108 GrContextOptions defaultOptions;
109 return MakeGL(nullptr, defaultOptions);
110}
111
Robert Phillipsa3457b82018-03-08 11:30:12 -0500112sk_sp<GrContext> GrContext::MakeGL(sk_sp<const GrGLInterface> interface,
113 const GrContextOptions& options) {
114 sk_sp<GrContext> context(new GrDirectContext(kOpenGL_GrBackend));
115
116 context->fGpu = GrGLGpu::Make(std::move(interface), options, context.get());
117 if (!context->fGpu) {
118 return nullptr;
119 }
120
121 context->fCaps = context->fGpu->refCaps();
122 if (!context->init(options)) {
123 return nullptr;
124 }
125 return context;
126}
127
128sk_sp<GrContext> GrContext::MakeMock(const GrMockOptions* mockOptions) {
129 GrContextOptions defaultOptions;
130 return MakeMock(mockOptions, defaultOptions);
131}
132
133sk_sp<GrContext> GrContext::MakeMock(const GrMockOptions* mockOptions,
134 const GrContextOptions& options) {
135 sk_sp<GrContext> context(new GrDirectContext(kMock_GrBackend));
136
137 context->fGpu = GrMockGpu::Make(mockOptions, options, context.get());
138 if (!context->fGpu) {
139 return nullptr;
140 }
141
142 context->fCaps = context->fGpu->refCaps();
143 if (!context->init(options)) {
144 return nullptr;
145 }
146 return context;
147}
148
149#ifdef SK_VULKAN
Greg Daniel10a83da2018-06-14 09:31:11 -0400150sk_sp<GrContext> GrContext::MakeVulkan(const GrVkBackendContext& backendContext) {
151 GrContextOptions defaultOptions;
152 return MakeVulkan(backendContext, defaultOptions);
153}
154
155sk_sp<GrContext> GrContext::MakeVulkan(const GrVkBackendContext& backendContext,
156 const GrContextOptions& options) {
157 sk_sp<GrContext> context(new GrDirectContext(kVulkan_GrBackend));
158
159 sk_sp<GrVkBackendContext> backendContextRef(new GrVkBackendContext());
160 backendContextRef->fInstance = backendContext.fInstance;
161 backendContextRef->fPhysicalDevice = backendContext.fPhysicalDevice;
162 backendContextRef->fDevice = backendContext.fDevice;
163 backendContextRef->fQueue = backendContext.fQueue;
164 backendContextRef->fGraphicsQueueIndex = backendContext.fGraphicsQueueIndex;
165 backendContextRef->fMinAPIVersion = backendContext.fMinAPIVersion;
166 backendContextRef->fExtensions = backendContext.fExtensions;
167 backendContextRef->fFeatures = backendContext.fFeatures;
168 backendContextRef->fInterface = backendContext.fInterface;
169 backendContextRef->fMemoryAllocator = backendContext.fMemoryAllocator;
170
171 SkASSERT(!backendContext.fOwnsInstanceAndDevice);
172 backendContextRef->fOwnsInstanceAndDevice = false;
173
174 context->fGpu = GrVkGpu::Make(std::move(backendContextRef), options, context.get());
175 if (!context->fGpu) {
176 return nullptr;
177 }
178
179 context->fCaps = context->fGpu->refCaps();
180 if (!context->init(options)) {
181 return nullptr;
182 }
183 return context;
184}
185
Robert Phillipsa3457b82018-03-08 11:30:12 -0500186sk_sp<GrContext> GrContext::MakeVulkan(sk_sp<const GrVkBackendContext> backendContext) {
187 GrContextOptions defaultOptions;
188 return MakeVulkan(std::move(backendContext), defaultOptions);
189}
190
191sk_sp<GrContext> GrContext::MakeVulkan(sk_sp<const GrVkBackendContext> backendContext,
192 const GrContextOptions& options) {
193 sk_sp<GrContext> context(new GrDirectContext(kVulkan_GrBackend));
194
195 context->fGpu = GrVkGpu::Make(std::move(backendContext), options, context.get());
196 if (!context->fGpu) {
197 return nullptr;
198 }
199
200 context->fCaps = context->fGpu->refCaps();
201 if (!context->init(options)) {
202 return nullptr;
203 }
204 return context;
205}
206#endif
207
208#ifdef SK_METAL
209sk_sp<GrContext> GrContext::MakeMetal(void* device, void* queue) {
210 GrContextOptions defaultOptions;
211 return MakeMetal(device, queue, defaultOptions);
212}
213
214sk_sp<GrContext> GrContext::MakeMetal(void* device, void* queue, const GrContextOptions& options) {
215 sk_sp<GrContext> context(new GrDirectContext(kMetal_GrBackend));
216
217 context->fGpu = GrMtlTrampoline::MakeGpu(context.get(), options, device, queue);
218 if (!context->fGpu) {
219 return nullptr;
220 }
221 if (!context->init(options)) {
222 return nullptr;
223 }
224 return context;
225}
226#endif
227