| /* |
| * 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/gpu/ganesh/gl/GrGLDirectContext.h" |
| |
| #include "include/gpu/GrContextOptions.h" |
| #include "include/gpu/GrDirectContext.h" |
| #include "include/gpu/GrTypes.h" |
| #include "include/gpu/gl/GrGLConfig.h" |
| #include "include/gpu/gl/GrGLFunctions.h" |
| #include "include/gpu/gl/GrGLInterface.h" |
| #include "include/gpu/gl/GrGLTypes.h" |
| |
| #include "src/gpu/ganesh/GrContextThreadSafeProxyPriv.h" |
| #include "src/gpu/ganesh/GrDirectContextPriv.h" |
| #include "src/gpu/ganesh/gl/GrGLDefines.h" |
| #include "src/gpu/ganesh/gl/GrGLGpu.h" |
| |
| #include <utility> |
| |
| #if defined(GR_TEST_UTILS) |
| # include "src/base/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/base/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(GR_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(GR_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 |