/*
|
* 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 "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 GrDirectContext : public GrContext {
|
public:
|
GrDirectContext(GrBackendApi backend)
|
: INHERITED(backend)
|
, fAtlasManager(nullptr) {
|
}
|
|
~GrDirectContext() override {
|
// this if-test protects against the case where the context is being destroyed
|
// before having been fully created
|
if (this->contextPriv().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(const GrContextOptions& options) override {
|
SkASSERT(fCaps); // should've been set in ctor
|
SkASSERT(!fThreadSafeProxy);
|
SkASSERT(!fFPFactoryCache);
|
fFPFactoryCache.reset(new GrSkSLFPFactoryCache());
|
fThreadSafeProxy.reset(new GrContextThreadSafeProxy(fCaps, this->contextID(),
|
this->backend(),
|
options, fFPFactoryCache));
|
|
if (!INHERITED::initCommon(options)) {
|
return false;
|
}
|
|
GrDrawOpAtlas::AllowMultitexturing allowMultitexturing;
|
if (GrContextOptions::Enable::kNo == options.fAllowMultipleGlyphCacheTextures ||
|
// multitexturing supported only if range can represent the index + texcoords fully
|
!(fCaps->shaderCaps()->floatIs32Bits() || fCaps->shaderCaps()->integerSupport())) {
|
allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kNo;
|
} else {
|
allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes;
|
}
|
|
GrStrikeCache* glyphCache = this->contextPriv().getGlyphCache();
|
GrProxyProvider* proxyProvider = this->contextPriv().proxyProvider();
|
|
fAtlasManager = new GrAtlasManager(proxyProvider, glyphCache,
|
options.fGlyphCacheTextureMaximumBytes,
|
allowMultitexturing);
|
this->contextPriv().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 GrDirectContext(GrBackendApi::kOpenGL));
|
|
context->fGpu = GrGLGpu::Make(std::move(interface), options, context.get());
|
if (!context->fGpu) {
|
return nullptr;
|
}
|
|
context->fCaps = context->fGpu->refCaps();
|
if (!context->init(options)) {
|
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 GrDirectContext(GrBackendApi::kMock));
|
|
context->fGpu = GrMockGpu::Make(mockOptions, options, context.get());
|
if (!context->fGpu) {
|
return nullptr;
|
}
|
|
context->fCaps = context->fGpu->refCaps();
|
if (!context->init(options)) {
|
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 GrDirectContext(GrBackendApi::kVulkan));
|
|
context->fGpu = GrVkGpu::Make(backendContext, options, context.get());
|
if (!context->fGpu) {
|
return nullptr;
|
}
|
|
context->fCaps = context->fGpu->refCaps();
|
if (!context->init(options)) {
|
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 GrDirectContext(GrBackendApi::kMetal));
|
|
context->fGpu = GrMtlTrampoline::MakeGpu(context.get(), options, device, queue);
|
if (!context->fGpu) {
|
return nullptr;
|
}
|
|
context->fCaps = context->fGpu->refCaps();
|
if (!context->init(options)) {
|
return nullptr;
|
}
|
return context;
|
}
|
#endif
|