1 /*
2 * Copyright 2023 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "include/gpu/ganesh/gl/GrGLDirectContext.h"
9
10 #include "include/gpu/ganesh/GrContextOptions.h"
11 #include "include/gpu/ganesh/GrDirectContext.h"
12 #include "include/gpu/ganesh/GrTypes.h"
13 #include "include/gpu/ganesh/gl/GrGLConfig.h"
14 #include "include/gpu/ganesh/gl/GrGLFunctions.h"
15 #include "include/gpu/ganesh/gl/GrGLInterface.h"
16 #include "include/gpu/ganesh/gl/GrGLTypes.h"
17
18 #include "src/gpu/ganesh/GrContextThreadSafeProxyPriv.h"
19 #include "src/gpu/ganesh/GrDirectContextPriv.h"
20 #include "src/gpu/ganesh/gl/GrGLDefines.h"
21 #include "src/gpu/ganesh/gl/GrGLGpu.h"
22
23 #include <utility>
24
25 #if defined(GPU_TEST_UTILS)
26 # include "src/base/SkRandom.h"
27 # if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
28 # include <sanitizer/lsan_interface.h>
29 # endif
30 #endif
31
32 #if defined(SK_DISABLE_LEGACY_GL_MAKE_NATIVE_INTERFACE)
33 #include "include/private/base/SkAssert.h"
34 #endif
35
36 namespace GrDirectContexts {
37
MakeGL(sk_sp<const GrGLInterface> glInterface)38 sk_sp<GrDirectContext> MakeGL(sk_sp<const GrGLInterface> glInterface) {
39 GrContextOptions defaultOptions;
40 return MakeGL(std::move(glInterface), defaultOptions);
41 }
42
43 #if !defined(SK_DISABLE_LEGACY_GL_MAKE_NATIVE_INTERFACE)
MakeGL(const GrContextOptions & options)44 sk_sp<GrDirectContext> MakeGL(const GrContextOptions& options) {
45 return MakeGL(nullptr, options);
46 }
47
MakeGL()48 sk_sp<GrDirectContext> MakeGL() {
49 GrContextOptions defaultOptions;
50 return MakeGL(nullptr, defaultOptions);
51 }
52 #endif
53
54 #if defined(GPU_TEST_UTILS)
make_get_error_with_random_oom(GrGLFunction<GrGLGetErrorFn> original)55 GrGLFunction<GrGLGetErrorFn> make_get_error_with_random_oom(GrGLFunction<GrGLGetErrorFn> original) {
56 // A SkRandom and a GrGLFunction<GrGLGetErrorFn> are too big to be captured by a
57 // GrGLFunction<GrGLGetError> (surprise, surprise). So we make a context object and
58 // capture that by pointer. However, GrGLFunction doesn't support calling a destructor
59 // on the thing it captures. So we leak the context.
60 struct GetErrorContext {
61 SkRandom fRandom;
62 GrGLFunction<GrGLGetErrorFn> fGetError;
63 };
64
65 auto errorContext = new GetErrorContext;
66
67 #if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
68 __lsan_ignore_object(errorContext);
69 #endif
70
71 errorContext->fGetError = original;
72
73 return GrGLFunction<GrGLGetErrorFn>([errorContext]() {
74 GrGLenum error = errorContext->fGetError();
75 if (error == GR_GL_NO_ERROR && (errorContext->fRandom.nextU() % 300) == 0) {
76 error = GR_GL_OUT_OF_MEMORY;
77 }
78 return error;
79 });
80 }
81 #endif
82
MakeGL(sk_sp<const GrGLInterface> glInterface,const GrContextOptions & options)83 sk_sp<GrDirectContext> MakeGL(sk_sp<const GrGLInterface> glInterface,
84 const GrContextOptions& options) {
85 #if defined(SK_DISABLE_LEGACY_GL_MAKE_NATIVE_INTERFACE)
86 SkASSERT(glInterface);
87 #endif
88 auto direct = GrDirectContextPriv::Make(
89 GrBackendApi::kOpenGL,
90 options,
91 GrContextThreadSafeProxyPriv::Make(GrBackendApi::kOpenGL, options));
92 #if defined(GPU_TEST_UTILS)
93 if (options.fRandomGLOOM) {
94 auto copy = sk_make_sp<GrGLInterface>(*glInterface);
95 copy->fFunctions.fGetError =
96 make_get_error_with_random_oom(glInterface->fFunctions.fGetError);
97 #if GR_GL_CHECK_ERROR
98 // Suppress logging GL errors since we'll be synthetically generating them.
99 copy->suppressErrorLogging();
100 #endif
101 glInterface = std::move(copy);
102 }
103 #endif
104 GrDirectContextPriv::SetGpu(direct,
105 GrGLGpu::Make(std::move(glInterface), options, direct.get()));
106 if (!GrDirectContextPriv::Init(direct)) {
107 return nullptr;
108 }
109 return direct;
110 }
111
112 } // namespace GrDirectContexts
113