| /* | |
| * Copyright 2023 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "include/core/SkContext.h" | |
| #include "include/gpu/ganesh/gl/GrGLDirectContext.h" | |
| #include "include/gpu/ganesh/GrContextOptions.h" | |
| #include "include/gpu/ganesh/GrDirectContext.h" | |
| #include "include/gpu/ganesh/GrTypes.h" | |
| #include "include/gpu/ganesh/gl/GrGLConfig.h" | |
| #include "include/gpu/ganesh/gl/GrGLFunctions.h" | |
| #include "include/gpu/ganesh/gl/GrGLInterface.h" | |
| #include "include/gpu/ganesh/gl/GrGLTypes.h" | |
| #include "src/core/SkContextPriv.h" | |
| #include "src/gpu/ganesh/GrContextThreadSafeProxyPriv.h" | |
| #include "src/gpu/ganesh/GrDirectContextPriv.h" | |
| #include "src/gpu/ganesh/SkGaneshGPUContextAdapter.h" | |
| #include "src/gpu/ganesh/gl/GrGLDefines.h" | |
| #include "src/gpu/ganesh/gl/GrGLGpu.h" | |
| #include <utility> | |
| #if defined(GPU_TEST_UTILS) | |
| # include "src/core/SkRandom.h" | |
| # if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS) | |
| # include <sanitizer/lsan_interface.h> | |
| # endif | |
| #endif | |
| #if defined(SK_DISABLE_LEGACY_GL_MAKE_NATIVE_INTERFACE) | |
| #include "include/private/SkAssert.h" | |
| #endif | |
| namespace GrDirectContexts { | |
| sk_sp<GrDirectContext> MakeGL(sk_sp<const GrGLInterface> glInterface) { | |
| GrContextOptions defaultOptions; | |
| return MakeGL(std::move(glInterface), defaultOptions); | |
| } | |
| #if !defined(SK_DISABLE_LEGACY_GL_MAKE_NATIVE_INTERFACE) | |
| sk_sp<GrDirectContext> MakeGL(const GrContextOptions& options) { | |
| return MakeGL(nullptr, options); | |
| } | |
| sk_sp<GrDirectContext> MakeGL() { | |
| GrContextOptions defaultOptions; | |
| return MakeGL(nullptr, defaultOptions); | |
| } | |
| #endif | |
| #if defined(GPU_TEST_UTILS) | |
| GrGLFunction<GrGLGetErrorFn> make_get_error_with_random_oom(GrGLFunction<GrGLGetErrorFn> original) { | |
| // A SkRandom and a GrGLFunction<GrGLGetErrorFn> are too big to be captured by a | |
| // GrGLFunction<GrGLGetError> (surprise, surprise). So we make a context object and | |
| // capture that by pointer. However, GrGLFunction doesn't support calling a destructor | |
| // on the thing it captures. So we leak the context. | |
| struct GetErrorContext { | |
| SkRandom fRandom; | |
| GrGLFunction<GrGLGetErrorFn> fGetError; | |
| }; | |
| auto errorContext = new GetErrorContext; | |
| #if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS) | |
| __lsan_ignore_object(errorContext); | |
| #endif | |
| errorContext->fGetError = original; | |
| return GrGLFunction<GrGLGetErrorFn>([errorContext]() { | |
| GrGLenum error = errorContext->fGetError(); | |
| if (error == GR_GL_NO_ERROR && (errorContext->fRandom.nextU() % 300) == 0) { | |
| error = GR_GL_OUT_OF_MEMORY; | |
| } | |
| return error; | |
| }); | |
| } | |
| #endif | |
| sk_sp<GrDirectContext> MakeGL(sk_sp<const GrGLInterface> glInterface, | |
| const GrContextOptions& options) { | |
| #if defined(SK_DISABLE_LEGACY_GL_MAKE_NATIVE_INTERFACE) | |
| SkASSERT(glInterface); | |
| #endif | |
| auto direct = GrDirectContextPriv::Make( | |
| GrBackendApi::kOpenGL, | |
| options, | |
| GrContextThreadSafeProxyPriv::Make(GrBackendApi::kOpenGL, options)); | |
| #if defined(GPU_TEST_UTILS) | |
| if (options.fRandomGLOOM) { | |
| auto copy = sk_make_sp<GrGLInterface>(*glInterface); | |
| copy->fFunctions.fGetError = | |
| make_get_error_with_random_oom(glInterface->fFunctions.fGetError); | |
| #if GR_GL_CHECK_ERROR | |
| // Suppress logging GL errors since we'll be synthetically generating them. | |
| copy->suppressErrorLogging(); | |
| #endif | |
| glInterface = std::move(copy); | |
| } | |
| #endif | |
| GrDirectContextPriv::SetGpu(direct, | |
| GrGLGpu::Make(std::move(glInterface), options, direct.get())); | |
| if (!GrDirectContextPriv::Init(direct)) { | |
| return nullptr; | |
| } | |
| return direct; | |
| } | |
| } // namespace GrDirectContexts | |
| namespace SkContexts { | |
| std::unique_ptr<SkContext> MakeGanesh(sk_sp<const GrGLInterface> glInterface, | |
| const SkContextOptions& contextOptions, | |
| const GrContextOptions& grOptions) { | |
| auto direct = GrDirectContexts::MakeGL(std::move(glInterface), grOptions); | |
| if (!direct) { | |
| return nullptr; | |
| } | |
| return SkContextCtorAccessor::MakeContext( | |
| contextOptions, std::make_unique<SkGaneshGPUContextAdapter>(std::move(direct))); | |
| } | |
| } // namespace SkContexts |