Flutter Engine
The Flutter Engine
GLWindowContext_android.cpp
Go to the documentation of this file.
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 <EGL/egl.h>
9#include <GLES/gl.h>
13
14#define EGL_PROTECTED_CONTENT_EXT 0x32C0
15
16namespace {
17class GLWindowContext_android : public skwindow::internal::GLWindowContext {
18public:
19
20 GLWindowContext_android(ANativeWindow*, const skwindow::DisplayParams&);
21
22 ~GLWindowContext_android() override;
23
25 void onDestroyContext() override;
26
27private:
28 void onSwapBuffers() override;
29
30 EGLDisplay fDisplay;
31 EGLContext fEGLContext;
32 EGLSurface fSurfaceAndroid;
33
34 // For setDisplayParams and resize which call onInitializeContext with null platformData
35 ANativeWindow* fNativeWindow = nullptr;
36
38};
39
40GLWindowContext_android::GLWindowContext_android(ANativeWindow* window,
43 , fDisplay(EGL_NO_DISPLAY)
44 , fEGLContext(EGL_NO_CONTEXT)
45 , fSurfaceAndroid(EGL_NO_SURFACE)
46 , fNativeWindow(window) {
47
48 // any config code here (particularly for msaa)?
49
50 this->initializeContext();
51}
52
53GLWindowContext_android::~GLWindowContext_android() {
54 this->destroyContext();
55}
56
57sk_sp<const GrGLInterface> GLWindowContext_android::onInitializeContext() {
58 fWidth = ANativeWindow_getWidth(fNativeWindow);
59 fHeight = ANativeWindow_getHeight(fNativeWindow);
60
61 fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
62
63 EGLint majorVersion;
64 EGLint minorVersion;
65 eglInitialize(fDisplay, &majorVersion, &minorVersion);
66
67 const char* extensions = eglQueryString(fDisplay, EGL_EXTENSIONS);
68
69 if (fDisplayParams.fCreateProtectedNativeBackend &&
70 !strstr(extensions, "EGL_EXT_protected_content")) {
71 SkDebugf("Protected Context requested but no protected support\n");
72 fDisplayParams.fCreateProtectedNativeBackend = false;
73 }
74
75 SkAssertResult(eglBindAPI(EGL_OPENGL_ES_API));
76
77 EGLint numConfigs = 0;
78 EGLint eglSampleCnt = fDisplayParams.fMSAASampleCount > 1 ? fDisplayParams.fMSAASampleCount > 1
79 : 0;
80 const EGLint configAttribs[] = {
81 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
82 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
83 EGL_RED_SIZE, 8,
84 EGL_GREEN_SIZE, 8,
85 EGL_BLUE_SIZE, 8,
86 EGL_ALPHA_SIZE, 8,
87 EGL_STENCIL_SIZE, 8,
88 EGL_SAMPLE_BUFFERS, eglSampleCnt ? 1 : 0,
89 EGL_SAMPLES, eglSampleCnt,
90 EGL_NONE
91 };
92
93 EGLConfig surfaceConfig;
94 SkAssertResult(eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs));
95 SkASSERT(numConfigs > 0);
96
97 std::vector<EGLint> kEGLContextAttribsForOpenGLES = {
98 EGL_CONTEXT_CLIENT_VERSION, 2,
99 };
100
101 if (fDisplayParams.fCreateProtectedNativeBackend) {
102 kEGLContextAttribsForOpenGLES.push_back(EGL_PROTECTED_CONTENT_EXT);
103 kEGLContextAttribsForOpenGLES.push_back(EGL_TRUE);
104 }
105
106 kEGLContextAttribsForOpenGLES.push_back(EGL_NONE);
107
108 fEGLContext = eglCreateContext(
109 fDisplay, surfaceConfig, nullptr, kEGLContextAttribsForOpenGLES.data());
110 SkASSERT(EGL_NO_CONTEXT != fEGLContext);
111
112// SkDebugf("EGL: %d.%d", majorVersion, minorVersion);
113// SkDebugf("Vendor: %s", eglQueryString(fDisplay, EGL_VENDOR));
114// SkDebugf("Extensions: %s", eglQueryString(fDisplay, EGL_EXTENSIONS));
115
116 const EGLint surfaceAttribs[] = {
117 fDisplayParams.fCreateProtectedNativeBackend ? EGL_PROTECTED_CONTENT_EXT :EGL_NONE,
118 fDisplayParams.fCreateProtectedNativeBackend ? EGL_TRUE : EGL_NONE,
119 EGL_NONE
120 };
121
122 fSurfaceAndroid = eglCreateWindowSurface(fDisplay, surfaceConfig, fNativeWindow,
123 surfaceAttribs);
124 SkASSERT(EGL_NO_SURFACE != fSurfaceAndroid);
125
126 SkAssertResult(eglMakeCurrent(fDisplay, fSurfaceAndroid, fSurfaceAndroid, fEGLContext));
127 // GLWindowContext::initializeContext will call GrGLMakeNativeInterface so we
128 // won't call it here.
129
130 glClearStencil(0);
131 glClearColor(0, 0, 0, 0);
132 glStencilMask(0xffffffff);
133 glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
134
135 eglGetConfigAttrib(fDisplay, surfaceConfig, EGL_STENCIL_SIZE, &fStencilBits);
136 eglGetConfigAttrib(fDisplay, surfaceConfig, EGL_SAMPLES, &fSampleCount);
137 fSampleCount = std::max(fSampleCount, 1);
138
139 eglSwapInterval(fDisplay, fDisplayParams.fDisableVsync ? 0 : 1);
140
142}
143
144void GLWindowContext_android::onDestroyContext() {
145 if (!fDisplay || !fEGLContext || !fSurfaceAndroid) {
146 return;
147 }
148 eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
149 SkAssertResult(eglDestroySurface(fDisplay, fSurfaceAndroid));
150 SkAssertResult(eglDestroyContext(fDisplay, fEGLContext));
151 fEGLContext = EGL_NO_CONTEXT;
152 fSurfaceAndroid = EGL_NO_SURFACE;
153}
154
155void GLWindowContext_android::onSwapBuffers() {
156 if (fDisplay && fEGLContext && fSurfaceAndroid) {
157 eglSwapBuffers(fDisplay, fSurfaceAndroid);
158 }
159}
160
161} // anonymous namespace
162
163namespace skwindow {
164
165std::unique_ptr<WindowContext> MakeGLForAndroid(ANativeWindow* window,
166 const DisplayParams& params) {
167 std::unique_ptr<WindowContext> ctx(new GLWindowContext_android(window, params));
168 if (!ctx->isValid()) {
169 return nullptr;
170 }
171 return ctx;
172}
173
174} // namespace skwindow
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
#define EGL_PROTECTED_CONTENT_EXT
SK_API sk_sp< const GrGLInterface > GrGLMakeNativeInterface()
#define SkASSERT(cond)
Definition: SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define INHERITED(method,...)
Definition: SkRecorder.cpp:128
virtual void onSwapBuffers()=0
virtual sk_sp< const GrGLInterface > onInitializeContext()=0
GLWindowContext(const DisplayParams &)
const EmbeddedViewParams * params
GLFWwindow * window
Definition: main.cc:45
static float max(float r, float g, float b)
Definition: hsl.cpp:49
std::unique_ptr< WindowContext > MakeGLForAndroid(ANativeWindow *window, const DisplayParams &params)
struct ANativeWindow ANativeWindow