blob: 0baf059979e1318d8bf8ff9bb6b78fb582ad0e3a [file] [log] [blame]
/*
* 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