xref: /aosp_15_r20/external/skia/tools/window/android/GLWindowContext_android.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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