/* * 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/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/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 #if defined(GPU_TEST_UTILS) # include "src/base/SkRandom.h" # if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS) # include # endif #endif #if defined(SK_DISABLE_LEGACY_GL_MAKE_NATIVE_INTERFACE) #include "include/private/base/SkAssert.h" #endif namespace GrDirectContexts { sk_sp MakeGL(sk_sp glInterface) { GrContextOptions defaultOptions; return MakeGL(std::move(glInterface), defaultOptions); } #if !defined(SK_DISABLE_LEGACY_GL_MAKE_NATIVE_INTERFACE) sk_sp MakeGL(const GrContextOptions& options) { return MakeGL(nullptr, options); } sk_sp MakeGL() { GrContextOptions defaultOptions; return MakeGL(nullptr, defaultOptions); } #endif #if defined(GPU_TEST_UTILS) GrGLFunction make_get_error_with_random_oom(GrGLFunction original) { // A SkRandom and a GrGLFunction are too big to be captured by a // GrGLFunction (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 fGetError; }; auto errorContext = new GetErrorContext; #if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS) __lsan_ignore_object(errorContext); #endif errorContext->fGetError = original; return GrGLFunction([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 MakeGL(sk_sp 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(*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