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>
10 #include "include/gpu/ganesh/gl/GrGLInterface.h"
11 #include "tools/window/DisplayParams.h"
12 #include "tools/window/GLWindowContext.h"
13 #include "tools/window/android/WindowContextFactory_android.h"
14
15 #define EGL_PROTECTED_CONTENT_EXT 0x32C0
16
17 using skwindow::DisplayParams;
18
19 namespace {
20 class GLWindowContext_android : public skwindow::internal::GLWindowContext {
21 public:
22 GLWindowContext_android(ANativeWindow*, std::unique_ptr<const DisplayParams>);
23
24 ~GLWindowContext_android() override;
25
26 sk_sp<const GrGLInterface> onInitializeContext() override;
27 void onDestroyContext() override;
28
29 private:
30 void onSwapBuffers() override;
31
32 EGLDisplay fDisplay;
33 EGLContext fEGLContext;
34 EGLSurface fSurfaceAndroid;
35
36 // For setDisplayParams and resize which call onInitializeContext with null platformData
37 ANativeWindow* fNativeWindow = nullptr;
38 };
39
GLWindowContext_android(ANativeWindow * window,std::unique_ptr<const DisplayParams> params)40 GLWindowContext_android::GLWindowContext_android(ANativeWindow* window,
41 std::unique_ptr<const DisplayParams> params)
42 : GLWindowContext(std::move(params))
43 , fDisplay(EGL_NO_DISPLAY)
44 , fEGLContext(EGL_NO_CONTEXT)
45 , fSurfaceAndroid(EGL_NO_SURFACE)
46 , fNativeWindow(window) {
47 // any config code here (particularly for msaa)?
48
49 this->initializeContext();
50 }
51
~GLWindowContext_android()52 GLWindowContext_android::~GLWindowContext_android() {
53 this->destroyContext();
54 }
55
onInitializeContext()56 sk_sp<const GrGLInterface> GLWindowContext_android::onInitializeContext() {
57 fWidth = ANativeWindow_getWidth(fNativeWindow);
58 fHeight = ANativeWindow_getHeight(fNativeWindow);
59
60 fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
61
62 EGLint majorVersion;
63 EGLint minorVersion;
64 eglInitialize(fDisplay, &majorVersion, &minorVersion);
65
66 const char* extensions = eglQueryString(fDisplay, EGL_EXTENSIONS);
67
68 if (fDisplayParams->createProtectedNativeBackend() &&
69 !strstr(extensions, "EGL_EXT_protected_content")) {
70 SkDebugf("Protected Context requested but no protected support\n");
71 fDisplayParams = skwindow::DisplayParamsBuilder(fDisplayParams.get())
72 .createProtectedNativeBackend(false)
73 .build();
74 }
75
76 SkAssertResult(eglBindAPI(EGL_OPENGL_ES_API));
77
78 EGLint numConfigs = 0;
79 EGLint eglSampleCnt =
80 fDisplayParams->msaaSampleCount() > 1 ? fDisplayParams->msaaSampleCount() > 1 : 0;
81 const EGLint configAttribs[] = {
82 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
83 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
84 EGL_RED_SIZE, 8,
85 EGL_GREEN_SIZE, 8,
86 EGL_BLUE_SIZE, 8,
87 EGL_ALPHA_SIZE, 8,
88 EGL_STENCIL_SIZE, 8,
89 EGL_SAMPLE_BUFFERS, eglSampleCnt ? 1 : 0,
90 EGL_SAMPLES, eglSampleCnt,
91 EGL_NONE
92 };
93
94 EGLConfig surfaceConfig;
95 SkAssertResult(eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs));
96 SkASSERT(numConfigs > 0);
97
98 std::vector<EGLint> kEGLContextAttribsForOpenGLES = {
99 EGL_CONTEXT_CLIENT_VERSION, 2,
100 };
101
102 if (fDisplayParams->createProtectedNativeBackend()) {
103 kEGLContextAttribsForOpenGLES.push_back(EGL_PROTECTED_CONTENT_EXT);
104 kEGLContextAttribsForOpenGLES.push_back(EGL_TRUE);
105 }
106
107 kEGLContextAttribsForOpenGLES.push_back(EGL_NONE);
108
109 fEGLContext = eglCreateContext(
110 fDisplay, surfaceConfig, nullptr, kEGLContextAttribsForOpenGLES.data());
111 SkASSERT(EGL_NO_CONTEXT != fEGLContext);
112
113 // SkDebugf("EGL: %d.%d", majorVersion, minorVersion);
114 // SkDebugf("Vendor: %s", eglQueryString(fDisplay, EGL_VENDOR));
115 // SkDebugf("Extensions: %s", eglQueryString(fDisplay, EGL_EXTENSIONS));
116
117 const EGLint surfaceAttribs[] = {
118 fDisplayParams->createProtectedNativeBackend() ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
119 fDisplayParams->createProtectedNativeBackend() ? EGL_TRUE : EGL_NONE,
120 EGL_NONE};
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->disableVsync() ? 0 : 1);
140
141 return GrGLMakeNativeInterface();
142 }
143
onDestroyContext()144 void 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
onSwapBuffers()155 void GLWindowContext_android::onSwapBuffers() {
156 if (fDisplay && fEGLContext && fSurfaceAndroid) {
157 eglSwapBuffers(fDisplay, fSurfaceAndroid);
158 }
159 }
160
161 } // anonymous namespace
162
163 namespace skwindow {
164
MakeGLForAndroid(ANativeWindow * window,std::unique_ptr<const DisplayParams> params)165 std::unique_ptr<WindowContext> MakeGLForAndroid(ANativeWindow* window,
166 std::unique_ptr<const DisplayParams> params) {
167 std::unique_ptr<WindowContext> ctx(new GLWindowContext_android(window, std::move(params)));
168 if (!ctx->isValid()) {
169 return nullptr;
170 }
171 return ctx;
172 }
173
174 } // namespace skwindow
175