/* * Copyright 2018 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "GrContext.h" #include "GrContextPriv.h" #include "GrContextThreadSafeProxy.h" #include "GrContextThreadSafeProxyPriv.h" #include "GrGpu.h" #include "effects/GrSkSLFP.h" #include "gl/GrGLGpu.h" #include "mock/GrMockGpu.h" #include "text/GrStrikeCache.h" #ifdef SK_METAL #include "mtl/GrMtlTrampoline.h" #endif #ifdef SK_VULKAN #include "vk/GrVkGpu.h" #endif class SK_API GrLegacyDirectContext : public GrContext { public: GrLegacyDirectContext(GrBackendApi backend, const GrContextOptions& options) : INHERITED(backend, options) , fAtlasManager(nullptr) { } ~GrLegacyDirectContext() override { // this if-test protects against the case where the context is being destroyed // before having been fully created if (this->priv().getGpu()) { this->flush(); } delete fAtlasManager; } void abandonContext() override { INHERITED::abandonContext(); fAtlasManager->freeAll(); } void releaseResourcesAndAbandonContext() override { INHERITED::releaseResourcesAndAbandonContext(); fAtlasManager->freeAll(); } void freeGpuResources() override { this->flush(); fAtlasManager->freeAll(); INHERITED::freeGpuResources(); } protected: bool init(sk_sp<const GrCaps> caps, sk_sp<GrSkSLFPFactoryCache> FPFactoryCache) override { SkASSERT(caps && !FPFactoryCache); SkASSERT(!fThreadSafeProxy); FPFactoryCache.reset(new GrSkSLFPFactoryCache()); fThreadSafeProxy = GrContextThreadSafeProxyPriv::Make(this->backend(), this->options(), this->contextID(), caps, FPFactoryCache); if (!INHERITED::init(std::move(caps), std::move(FPFactoryCache))) { return false; } bool sortOpLists = this->explicitlyAllocateGPUResources(); if (GrContextOptions::Enable::kNo == this->options().fSortRenderTargets) { sortOpLists = false; } else if (GrContextOptions::Enable::kYes == this->options().fSortRenderTargets) { sortOpLists = true; } this->setupDrawingManager(this->explicitlyAllocateGPUResources(), sortOpLists); SkASSERT(this->caps()); GrDrawOpAtlas::AllowMultitexturing allowMultitexturing; if (GrContextOptions::Enable::kNo == this->options().fAllowMultipleGlyphCacheTextures || // multitexturing supported only if range can represent the index + texcoords fully !(this->caps()->shaderCaps()->floatIs32Bits() || this->caps()->shaderCaps()->integerSupport())) { allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kNo; } else { allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes; } GrStrikeCache* glyphCache = this->priv().getGrStrikeCache(); GrProxyProvider* proxyProvider = this->priv().proxyProvider(); fAtlasManager = new GrAtlasManager(proxyProvider, glyphCache, this->options().fGlyphCacheTextureMaximumBytes, allowMultitexturing); this->priv().addOnFlushCallbackObject(fAtlasManager); return true; } GrAtlasManager* onGetAtlasManager() override { return fAtlasManager; } private: GrAtlasManager* fAtlasManager; typedef GrContext INHERITED; }; sk_sp<GrContext> GrContext::MakeGL(sk_sp<const GrGLInterface> interface) { GrContextOptions defaultOptions; return MakeGL(std::move(interface), defaultOptions); } sk_sp<GrContext> GrContext::MakeGL(const GrContextOptions& options) { return MakeGL(nullptr, options); } sk_sp<GrContext> GrContext::MakeGL() { GrContextOptions defaultOptions; return MakeGL(nullptr, defaultOptions); } sk_sp<GrContext> GrContext::MakeGL(sk_sp<const GrGLInterface> interface, const GrContextOptions& options) { sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kOpenGL, options)); context->fGpu = GrGLGpu::Make(std::move(interface), options, context.get()); if (!context->fGpu) { return nullptr; } if (!context->init(context->fGpu->refCaps(), nullptr)) { return nullptr; } return context; } sk_sp<GrContext> GrContext::MakeMock(const GrMockOptions* mockOptions) { GrContextOptions defaultOptions; return MakeMock(mockOptions, defaultOptions); } sk_sp<GrContext> GrContext::MakeMock(const GrMockOptions* mockOptions, const GrContextOptions& options) { sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kMock, options)); context->fGpu = GrMockGpu::Make(mockOptions, options, context.get()); if (!context->fGpu) { return nullptr; } if (!context->init(context->fGpu->refCaps(), nullptr)) { return nullptr; } return context; } sk_sp<GrContext> GrContext::MakeVulkan(const GrVkBackendContext& backendContext) { #ifdef SK_VULKAN GrContextOptions defaultOptions; return MakeVulkan(backendContext, defaultOptions); #else return nullptr; #endif } sk_sp<GrContext> GrContext::MakeVulkan(const GrVkBackendContext& backendContext, const GrContextOptions& options) { #ifdef SK_VULKAN GrContextOptions defaultOptions; sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kVulkan, options)); context->fGpu = GrVkGpu::Make(backendContext, options, context.get()); if (!context->fGpu) { return nullptr; } if (!context->init(context->fGpu->refCaps(), nullptr)) { return nullptr; } return context; #else return nullptr; #endif } #ifdef SK_METAL sk_sp<GrContext> GrContext::MakeMetal(void* device, void* queue) { GrContextOptions defaultOptions; return MakeMetal(device, queue, defaultOptions); } sk_sp<GrContext> GrContext::MakeMetal(void* device, void* queue, const GrContextOptions& options) { sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kMetal, options)); context->fGpu = GrMtlTrampoline::MakeGpu(context.get(), options, device, queue); if (!context->fGpu) { return nullptr; } if (!context->init(context->fGpu->refCaps(), nullptr)) { return nullptr; } return context; } #endif