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