1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2023 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include <EGL/egl.h>
9*c8dee2aaSAndroid Build Coastguard Worker #include <GLES/gl.h>
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/gl/GrGLInterface.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "tools/window/DisplayParams.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "tools/window/GLWindowContext.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "tools/window/android/WindowContextFactory_android.h"
14*c8dee2aaSAndroid Build Coastguard Worker
15*c8dee2aaSAndroid Build Coastguard Worker #define EGL_PROTECTED_CONTENT_EXT 0x32C0
16*c8dee2aaSAndroid Build Coastguard Worker
17*c8dee2aaSAndroid Build Coastguard Worker using skwindow::DisplayParams;
18*c8dee2aaSAndroid Build Coastguard Worker
19*c8dee2aaSAndroid Build Coastguard Worker namespace {
20*c8dee2aaSAndroid Build Coastguard Worker class GLWindowContext_android : public skwindow::internal::GLWindowContext {
21*c8dee2aaSAndroid Build Coastguard Worker public:
22*c8dee2aaSAndroid Build Coastguard Worker GLWindowContext_android(ANativeWindow*, std::unique_ptr<const DisplayParams>);
23*c8dee2aaSAndroid Build Coastguard Worker
24*c8dee2aaSAndroid Build Coastguard Worker ~GLWindowContext_android() override;
25*c8dee2aaSAndroid Build Coastguard Worker
26*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrGLInterface> onInitializeContext() override;
27*c8dee2aaSAndroid Build Coastguard Worker void onDestroyContext() override;
28*c8dee2aaSAndroid Build Coastguard Worker
29*c8dee2aaSAndroid Build Coastguard Worker private:
30*c8dee2aaSAndroid Build Coastguard Worker void onSwapBuffers() override;
31*c8dee2aaSAndroid Build Coastguard Worker
32*c8dee2aaSAndroid Build Coastguard Worker EGLDisplay fDisplay;
33*c8dee2aaSAndroid Build Coastguard Worker EGLContext fEGLContext;
34*c8dee2aaSAndroid Build Coastguard Worker EGLSurface fSurfaceAndroid;
35*c8dee2aaSAndroid Build Coastguard Worker
36*c8dee2aaSAndroid Build Coastguard Worker // For setDisplayParams and resize which call onInitializeContext with null platformData
37*c8dee2aaSAndroid Build Coastguard Worker ANativeWindow* fNativeWindow = nullptr;
38*c8dee2aaSAndroid Build Coastguard Worker };
39*c8dee2aaSAndroid Build Coastguard Worker
GLWindowContext_android(ANativeWindow * window,std::unique_ptr<const DisplayParams> params)40*c8dee2aaSAndroid Build Coastguard Worker GLWindowContext_android::GLWindowContext_android(ANativeWindow* window,
41*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<const DisplayParams> params)
42*c8dee2aaSAndroid Build Coastguard Worker : GLWindowContext(std::move(params))
43*c8dee2aaSAndroid Build Coastguard Worker , fDisplay(EGL_NO_DISPLAY)
44*c8dee2aaSAndroid Build Coastguard Worker , fEGLContext(EGL_NO_CONTEXT)
45*c8dee2aaSAndroid Build Coastguard Worker , fSurfaceAndroid(EGL_NO_SURFACE)
46*c8dee2aaSAndroid Build Coastguard Worker , fNativeWindow(window) {
47*c8dee2aaSAndroid Build Coastguard Worker // any config code here (particularly for msaa)?
48*c8dee2aaSAndroid Build Coastguard Worker
49*c8dee2aaSAndroid Build Coastguard Worker this->initializeContext();
50*c8dee2aaSAndroid Build Coastguard Worker }
51*c8dee2aaSAndroid Build Coastguard Worker
~GLWindowContext_android()52*c8dee2aaSAndroid Build Coastguard Worker GLWindowContext_android::~GLWindowContext_android() {
53*c8dee2aaSAndroid Build Coastguard Worker this->destroyContext();
54*c8dee2aaSAndroid Build Coastguard Worker }
55*c8dee2aaSAndroid Build Coastguard Worker
onInitializeContext()56*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrGLInterface> GLWindowContext_android::onInitializeContext() {
57*c8dee2aaSAndroid Build Coastguard Worker fWidth = ANativeWindow_getWidth(fNativeWindow);
58*c8dee2aaSAndroid Build Coastguard Worker fHeight = ANativeWindow_getHeight(fNativeWindow);
59*c8dee2aaSAndroid Build Coastguard Worker
60*c8dee2aaSAndroid Build Coastguard Worker fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
61*c8dee2aaSAndroid Build Coastguard Worker
62*c8dee2aaSAndroid Build Coastguard Worker EGLint majorVersion;
63*c8dee2aaSAndroid Build Coastguard Worker EGLint minorVersion;
64*c8dee2aaSAndroid Build Coastguard Worker eglInitialize(fDisplay, &majorVersion, &minorVersion);
65*c8dee2aaSAndroid Build Coastguard Worker
66*c8dee2aaSAndroid Build Coastguard Worker const char* extensions = eglQueryString(fDisplay, EGL_EXTENSIONS);
67*c8dee2aaSAndroid Build Coastguard Worker
68*c8dee2aaSAndroid Build Coastguard Worker if (fDisplayParams->createProtectedNativeBackend() &&
69*c8dee2aaSAndroid Build Coastguard Worker !strstr(extensions, "EGL_EXT_protected_content")) {
70*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Protected Context requested but no protected support\n");
71*c8dee2aaSAndroid Build Coastguard Worker fDisplayParams = skwindow::DisplayParamsBuilder(fDisplayParams.get())
72*c8dee2aaSAndroid Build Coastguard Worker .createProtectedNativeBackend(false)
73*c8dee2aaSAndroid Build Coastguard Worker .build();
74*c8dee2aaSAndroid Build Coastguard Worker }
75*c8dee2aaSAndroid Build Coastguard Worker
76*c8dee2aaSAndroid Build Coastguard Worker SkAssertResult(eglBindAPI(EGL_OPENGL_ES_API));
77*c8dee2aaSAndroid Build Coastguard Worker
78*c8dee2aaSAndroid Build Coastguard Worker EGLint numConfigs = 0;
79*c8dee2aaSAndroid Build Coastguard Worker EGLint eglSampleCnt =
80*c8dee2aaSAndroid Build Coastguard Worker fDisplayParams->msaaSampleCount() > 1 ? fDisplayParams->msaaSampleCount() > 1 : 0;
81*c8dee2aaSAndroid Build Coastguard Worker const EGLint configAttribs[] = {
82*c8dee2aaSAndroid Build Coastguard Worker EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
83*c8dee2aaSAndroid Build Coastguard Worker EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
84*c8dee2aaSAndroid Build Coastguard Worker EGL_RED_SIZE, 8,
85*c8dee2aaSAndroid Build Coastguard Worker EGL_GREEN_SIZE, 8,
86*c8dee2aaSAndroid Build Coastguard Worker EGL_BLUE_SIZE, 8,
87*c8dee2aaSAndroid Build Coastguard Worker EGL_ALPHA_SIZE, 8,
88*c8dee2aaSAndroid Build Coastguard Worker EGL_STENCIL_SIZE, 8,
89*c8dee2aaSAndroid Build Coastguard Worker EGL_SAMPLE_BUFFERS, eglSampleCnt ? 1 : 0,
90*c8dee2aaSAndroid Build Coastguard Worker EGL_SAMPLES, eglSampleCnt,
91*c8dee2aaSAndroid Build Coastguard Worker EGL_NONE
92*c8dee2aaSAndroid Build Coastguard Worker };
93*c8dee2aaSAndroid Build Coastguard Worker
94*c8dee2aaSAndroid Build Coastguard Worker EGLConfig surfaceConfig;
95*c8dee2aaSAndroid Build Coastguard Worker SkAssertResult(eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs));
96*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(numConfigs > 0);
97*c8dee2aaSAndroid Build Coastguard Worker
98*c8dee2aaSAndroid Build Coastguard Worker std::vector<EGLint> kEGLContextAttribsForOpenGLES = {
99*c8dee2aaSAndroid Build Coastguard Worker EGL_CONTEXT_CLIENT_VERSION, 2,
100*c8dee2aaSAndroid Build Coastguard Worker };
101*c8dee2aaSAndroid Build Coastguard Worker
102*c8dee2aaSAndroid Build Coastguard Worker if (fDisplayParams->createProtectedNativeBackend()) {
103*c8dee2aaSAndroid Build Coastguard Worker kEGLContextAttribsForOpenGLES.push_back(EGL_PROTECTED_CONTENT_EXT);
104*c8dee2aaSAndroid Build Coastguard Worker kEGLContextAttribsForOpenGLES.push_back(EGL_TRUE);
105*c8dee2aaSAndroid Build Coastguard Worker }
106*c8dee2aaSAndroid Build Coastguard Worker
107*c8dee2aaSAndroid Build Coastguard Worker kEGLContextAttribsForOpenGLES.push_back(EGL_NONE);
108*c8dee2aaSAndroid Build Coastguard Worker
109*c8dee2aaSAndroid Build Coastguard Worker fEGLContext = eglCreateContext(
110*c8dee2aaSAndroid Build Coastguard Worker fDisplay, surfaceConfig, nullptr, kEGLContextAttribsForOpenGLES.data());
111*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(EGL_NO_CONTEXT != fEGLContext);
112*c8dee2aaSAndroid Build Coastguard Worker
113*c8dee2aaSAndroid Build Coastguard Worker // SkDebugf("EGL: %d.%d", majorVersion, minorVersion);
114*c8dee2aaSAndroid Build Coastguard Worker // SkDebugf("Vendor: %s", eglQueryString(fDisplay, EGL_VENDOR));
115*c8dee2aaSAndroid Build Coastguard Worker // SkDebugf("Extensions: %s", eglQueryString(fDisplay, EGL_EXTENSIONS));
116*c8dee2aaSAndroid Build Coastguard Worker
117*c8dee2aaSAndroid Build Coastguard Worker const EGLint surfaceAttribs[] = {
118*c8dee2aaSAndroid Build Coastguard Worker fDisplayParams->createProtectedNativeBackend() ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
119*c8dee2aaSAndroid Build Coastguard Worker fDisplayParams->createProtectedNativeBackend() ? EGL_TRUE : EGL_NONE,
120*c8dee2aaSAndroid Build Coastguard Worker EGL_NONE};
121*c8dee2aaSAndroid Build Coastguard Worker
122*c8dee2aaSAndroid Build Coastguard Worker fSurfaceAndroid = eglCreateWindowSurface(fDisplay, surfaceConfig, fNativeWindow,
123*c8dee2aaSAndroid Build Coastguard Worker surfaceAttribs);
124*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(EGL_NO_SURFACE != fSurfaceAndroid);
125*c8dee2aaSAndroid Build Coastguard Worker
126*c8dee2aaSAndroid Build Coastguard Worker SkAssertResult(eglMakeCurrent(fDisplay, fSurfaceAndroid, fSurfaceAndroid, fEGLContext));
127*c8dee2aaSAndroid Build Coastguard Worker // GLWindowContext::initializeContext will call GrGLMakeNativeInterface so we
128*c8dee2aaSAndroid Build Coastguard Worker // won't call it here.
129*c8dee2aaSAndroid Build Coastguard Worker
130*c8dee2aaSAndroid Build Coastguard Worker glClearStencil(0);
131*c8dee2aaSAndroid Build Coastguard Worker glClearColor(0, 0, 0, 0);
132*c8dee2aaSAndroid Build Coastguard Worker glStencilMask(0xffffffff);
133*c8dee2aaSAndroid Build Coastguard Worker glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
134*c8dee2aaSAndroid Build Coastguard Worker
135*c8dee2aaSAndroid Build Coastguard Worker eglGetConfigAttrib(fDisplay, surfaceConfig, EGL_STENCIL_SIZE, &fStencilBits);
136*c8dee2aaSAndroid Build Coastguard Worker eglGetConfigAttrib(fDisplay, surfaceConfig, EGL_SAMPLES, &fSampleCount);
137*c8dee2aaSAndroid Build Coastguard Worker fSampleCount = std::max(fSampleCount, 1);
138*c8dee2aaSAndroid Build Coastguard Worker
139*c8dee2aaSAndroid Build Coastguard Worker eglSwapInterval(fDisplay, fDisplayParams->disableVsync() ? 0 : 1);
140*c8dee2aaSAndroid Build Coastguard Worker
141*c8dee2aaSAndroid Build Coastguard Worker return GrGLMakeNativeInterface();
142*c8dee2aaSAndroid Build Coastguard Worker }
143*c8dee2aaSAndroid Build Coastguard Worker
onDestroyContext()144*c8dee2aaSAndroid Build Coastguard Worker void GLWindowContext_android::onDestroyContext() {
145*c8dee2aaSAndroid Build Coastguard Worker if (!fDisplay || !fEGLContext || !fSurfaceAndroid) {
146*c8dee2aaSAndroid Build Coastguard Worker return;
147*c8dee2aaSAndroid Build Coastguard Worker }
148*c8dee2aaSAndroid Build Coastguard Worker eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
149*c8dee2aaSAndroid Build Coastguard Worker SkAssertResult(eglDestroySurface(fDisplay, fSurfaceAndroid));
150*c8dee2aaSAndroid Build Coastguard Worker SkAssertResult(eglDestroyContext(fDisplay, fEGLContext));
151*c8dee2aaSAndroid Build Coastguard Worker fEGLContext = EGL_NO_CONTEXT;
152*c8dee2aaSAndroid Build Coastguard Worker fSurfaceAndroid = EGL_NO_SURFACE;
153*c8dee2aaSAndroid Build Coastguard Worker }
154*c8dee2aaSAndroid Build Coastguard Worker
onSwapBuffers()155*c8dee2aaSAndroid Build Coastguard Worker void GLWindowContext_android::onSwapBuffers() {
156*c8dee2aaSAndroid Build Coastguard Worker if (fDisplay && fEGLContext && fSurfaceAndroid) {
157*c8dee2aaSAndroid Build Coastguard Worker eglSwapBuffers(fDisplay, fSurfaceAndroid);
158*c8dee2aaSAndroid Build Coastguard Worker }
159*c8dee2aaSAndroid Build Coastguard Worker }
160*c8dee2aaSAndroid Build Coastguard Worker
161*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
162*c8dee2aaSAndroid Build Coastguard Worker
163*c8dee2aaSAndroid Build Coastguard Worker namespace skwindow {
164*c8dee2aaSAndroid Build Coastguard Worker
MakeGLForAndroid(ANativeWindow * window,std::unique_ptr<const DisplayParams> params)165*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<WindowContext> MakeGLForAndroid(ANativeWindow* window,
166*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<const DisplayParams> params) {
167*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<WindowContext> ctx(new GLWindowContext_android(window, std::move(params)));
168*c8dee2aaSAndroid Build Coastguard Worker if (!ctx->isValid()) {
169*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
170*c8dee2aaSAndroid Build Coastguard Worker }
171*c8dee2aaSAndroid Build Coastguard Worker return ctx;
172*c8dee2aaSAndroid Build Coastguard Worker }
173*c8dee2aaSAndroid Build Coastguard Worker
174*c8dee2aaSAndroid Build Coastguard Worker } // namespace skwindow
175