1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 // #define LOG_NDEBUG 0
18 #define LOG_TAG "EglDisplayContext"
19 #define EGL_EGLEXT_PROTOTYPES
20 #define GL_GLEXT_PROTOTYPES
21
22 #include "EglDisplayContext.h"
23
24 #include "EGL/egl.h"
25 #include "EglDisplayContext.h"
26 #include "EglFramebuffer.h"
27 #include "log/log.h"
28
29 namespace android {
30 namespace companion {
31 namespace virtualcamera {
32
EglDisplayContext(std::shared_ptr<ANativeWindow> nativeWindow)33 EglDisplayContext::EglDisplayContext(std::shared_ptr<ANativeWindow> nativeWindow)
34 : mEglDisplay(EGL_NO_DISPLAY),
35 mEglSurface(EGL_NO_SURFACE),
36 mEglContext(EGL_NO_CONTEXT),
37 mEglConfig(nullptr) {
38 EGLBoolean result;
39
40 mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
41 if (mEglDisplay == EGL_NO_DISPLAY) {
42 ALOGE("eglGetDisplay failed: %#x", eglGetError());
43 return;
44 }
45
46 EGLint majorVersion, minorVersion;
47 result = eglInitialize(mEglDisplay, &majorVersion, &minorVersion);
48 if (result != EGL_TRUE) {
49 ALOGE("eglInitialize failed: %#x", eglGetError());
50 return;
51 }
52 ALOGV("Initialized EGL v%d.%d", majorVersion, minorVersion);
53
54 EGLint numConfigs = 0;
55 EGLint configAttribs[] = {
56 EGL_SURFACE_TYPE,
57 nativeWindow == nullptr
58 ? EGL_PBUFFER_BIT // Render into individual AHardwareBuffer
59 : EGL_WINDOW_BIT, // Render into Surface (ANativeWindow)
60 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE,
61 8, EGL_BLUE_SIZE, 8,
62 // no alpha
63 EGL_NONE};
64
65 result =
66 eglChooseConfig(mEglDisplay, configAttribs, &mEglConfig, 1, &numConfigs);
67 if (result != EGL_TRUE) {
68 ALOGE("eglChooseConfig error: %#x", eglGetError());
69 return;
70 }
71
72 EGLint contextAttribs[] = {EGL_CONTEXT_MAJOR_VERSION_KHR, 3, EGL_NONE};
73 mEglContext =
74 eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, contextAttribs);
75 if (mEglContext == EGL_NO_CONTEXT) {
76 ALOGE("eglCreateContext error: %#x", eglGetError());
77 return;
78 }
79
80 if (nativeWindow != nullptr) {
81 mEglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig,
82 nativeWindow.get(), NULL);
83 if (mEglSurface == EGL_NO_SURFACE) {
84 ALOGE("eglCreateWindowSurface error: %#x", eglGetError());
85 }
86 }
87
88 // EGL is a big state machine. Now that we have a configuration ready, we set
89 // this state machine to that configuration (we make it the "current"
90 // configuration).
91 if (!makeCurrent()) {
92 ALOGE(
93 "Failed to set newly initialized EGLContext and EGLDisplay connection "
94 "as current.");
95 } else {
96 ALOGV("EGL successfully initialized.");
97 }
98 }
99
~EglDisplayContext()100 EglDisplayContext::~EglDisplayContext() {
101 eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
102 if (mEglSurface != EGL_NO_SURFACE) {
103 eglDestroySurface(mEglDisplay, mEglSurface);
104 }
105 if (mEglContext != EGL_NO_CONTEXT) {
106 eglDestroyContext(mEglDisplay, mEglContext);
107 }
108 if (mEglDisplay != EGL_NO_DISPLAY) {
109 eglTerminate(mEglDisplay);
110 }
111 }
112
getEglDisplay() const113 EGLDisplay EglDisplayContext::getEglDisplay() const {
114 return mEglDisplay;
115 }
116
isInitialized() const117 bool EglDisplayContext::isInitialized() const {
118 return mEglContext != EGL_NO_CONTEXT && mEglDisplay != EGL_NO_DISPLAY;
119 }
120
swapBuffers() const121 void EglDisplayContext::swapBuffers() const {
122 if (mEglSurface != EGL_NO_SURFACE) {
123 eglSwapBuffers(mEglDisplay, mEglSurface);
124 }
125 }
126
makeCurrent()127 bool EglDisplayContext::makeCurrent() {
128 if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
129 ALOGE("eglMakeCurrent failed: %#x", eglGetError());
130 return false;
131 }
132 return true;
133 }
134
135 } // namespace virtualcamera
136 } // namespace companion
137 } // namespace android
138