1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "egl_manager.h"
17
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21
22 namespace OHOS {
23 namespace Rosen {
24 using namespace std;
25
GetConfig(int version,EGLDisplay eglDisplay)26 EGLConfig EglManager::GetConfig(int version, EGLDisplay eglDisplay)
27 {
28 int attribList[] = {
29 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
30 EGL_RED_SIZE, 8,
31 EGL_GREEN_SIZE, 8,
32 EGL_BLUE_SIZE, 8,
33 EGL_ALPHA_SIZE, 8,
34 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
35 EGL_NONE
36 };
37 EGLConfig configs = NULL;
38 int numConfigs;
39 if (!eglChooseConfig(eglDisplay, attribList, &configs, 1, &numConfigs)) {
40 LOGE("eglChooseConfig ERROR");
41 return NULL;
42 }
43 return configs;
44 }
45
RetryEGLContext()46 bool EglManager::RetryEGLContext()
47 {
48 if (!IsEGLContextInCurrentThread(EGLDisplay_, EGLContext_)) {
49 LOGW("retry eglMakeCurrent.");
50 eglMakeCurrent(EGLDisplay_, currentSurface_, currentSurface_, EGLContext_);
51 int error = eglGetError();
52 if (error != EGL_SUCCESS) {
53 Deinit();
54 return false;
55 }
56 return true;
57 }
58 return true;
59 }
60
InitializeEGLDisplay()61 bool EglManager::InitializeEGLDisplay()
62 {
63 EGLDisplay_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
64 if (EGLDisplay_ == EGL_NO_DISPLAY) {
65 LOGE("EglManager Init unable to get EGL display.");
66 return false;
67 }
68
69 EGLint eglMajVers, eglMinVers;
70 if (!eglInitialize(EGLDisplay_, &eglMajVers, &eglMinVers)) {
71 EGLDisplay_ = EGL_NO_DISPLAY;
72 LOGE("EglManager Init unable to initialize display.");
73 return false;
74 }
75
76 LOGI("EglManager Init eglMinVers = %{public}u", eglMinVers);
77 int version = EGL_SUPPORT_VERSION;
78 if (eglMinVers >= EGL_LIMIT_VERSION) {
79 version = EGL_SUPPORT_VERSION;
80 }
81
82 EGLConfig_ = EglManager::GetConfig(version, EGLDisplay_);
83 if (EGLConfig_ == NULL) {
84 LOGE("EglManager Init config ERROR");
85 return false;
86 }
87
88 return true;
89 }
90
CreateEGLSurface()91 bool EglManager::CreateEGLSurface()
92 {
93 #ifndef ANDROID_PLATFORM
94 if (EGLWindow_ != nullptr) {
95 LOGI("EglManager Init eglSurface from eglWindow");
96 currentSurface_ = eglCreateWindowSurface(EGLDisplay_, EGLConfig_, EGLWindow_, NULL);
97 if (currentSurface_ == NULL) {
98 LOGE("EglManager Init eglSurface = null");
99 return false;
100 }
101 } else {
102 LOGI("EglManager Init eglSurface from PBuffer width = %{public}d, height = %{public}d", EGLWidth_, EGLHeight_);
103 int surfaceAttributes[] = { EGL_WIDTH, EGLWidth_, EGL_HEIGHT, EGLHeight_, EGL_NONE };
104 currentSurface_ = eglCreatePbufferSurface(EGLDisplay_, EGLConfig_, surfaceAttributes);
105 if (currentSurface_ == NULL) {
106 LOGE("EglManager Init eglCreateContext eglSurface = null");
107 return false;
108 }
109 }
110 #else
111 LOGI("EglManager Init eglSurface from PBuffer width = %{public}d, height = %{public}d", EGLWidth_, EGLHeight_);
112 int surfaceAttributes[] = { EGL_WIDTH, EGLWidth_, EGL_HEIGHT, EGLHeight_, EGL_NONE };
113 currentSurface_ = eglCreatePbufferSurface(EGLDisplay_, EGLConfig_, surfaceAttributes);
114 if (currentSurface_ == NULL) {
115 LOGE("EglManager Init eglCreateContext eglSurface = null");
116 return false;
117 }
118 #endif
119 return true;
120 }
121
CreateAndSetEGLContext()122 bool EglManager::CreateAndSetEGLContext()
123 {
124 int attrib3List[] = { EGL_CONTEXT_CLIENT_VERSION, EGL_SUPPORT_VERSION, EGL_NONE };
125 EGLContext_ = eglCreateContext(EGLDisplay_, EGLConfig_, nullptr, attrib3List);
126 int error = eglGetError();
127 if (error == EGL_SUCCESS) {
128 LOGI("EglManager Init Create EGLContext_ ok");
129 } else {
130 LOGE("EglManager Init eglCreateContext error %x", error);
131 return false;
132 }
133 eglMakeCurrent(EGLDisplay_, currentSurface_, currentSurface_, EGLContext_);
134 error = eglGetError();
135 return error == EGL_SUCCESS;
136 }
137
Init()138 EGLBoolean EglManager::Init()
139 {
140 if (initialized_) {
141 if (RetryEGLContext()) {
142 return EGL_TRUE;
143 }
144 }
145
146 initialized_ = true;
147 LOGI("EglManager ----- Init.\n");
148
149 if (EGLContext_ != EGL_NO_CONTEXT && EGLContext_ != nullptr) {
150 LOGW("EglManager Init EGLContext_ is already init.\n");
151 }
152
153 if (!InitializeEGLDisplay()) {
154 return EGL_FALSE;
155 }
156
157 if (!CreateEGLSurface()) {
158 return EGL_FALSE;
159 }
160
161 if (!CreateAndSetEGLContext()) {
162 return EGL_FALSE;
163 }
164 return EGL_TRUE;
165 }
166
Deinit()167 void EglManager::Deinit()
168 {
169 LOGW("Deinit");
170
171 if (EGLDisplay_ == EGL_NO_DISPLAY) {
172 return;
173 }
174
175 eglDestroyContext(EGLDisplay_, EGLContext_);
176 if (currentSurface_ != EGL_NO_SURFACE) {
177 eglDestroySurface(EGLDisplay_, currentSurface_);
178 }
179 eglMakeCurrent(EGLDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
180 eglTerminate(EGLDisplay_);
181 eglReleaseThread();
182
183 EGLDisplay_ = EGL_NO_DISPLAY;
184 EGLContext_ = EGL_NO_CONTEXT;
185 currentSurface_ = EGL_NO_SURFACE;
186 initialized_ = false;
187 }
188
IsEGLContextInCurrentThread(EGLDisplay display,EGLContext context)189 EGLBoolean EglManager::IsEGLContextInCurrentThread(EGLDisplay display, EGLContext context)
190 {
191 if (display == EGL_NO_DISPLAY) {
192 LOGE("EglManager IsEGLContextInCurrentThread display is EGL_NO_DISPLAY");
193 return EGL_FALSE;
194 }
195
196 if (context == EGL_NO_CONTEXT) {
197 LOGE("EglManager IsEGLContextInCurrentThread context is EGL_NO_CONTEXT");
198 return EGL_FALSE;
199 }
200
201 EGLBoolean isContextInCurrent = EGL_FALSE;
202 EGLint isContextLost = 0;
203
204 eglQueryContext(display, context, EGL_CONTEXT_LOST, &isContextLost);
205
206 if (!isContextLost && eglGetCurrentContext() == context) {
207 isContextInCurrent = EGL_TRUE;
208 }
209
210 return isContextInCurrent;
211 }
212 } // namespace Rosen
213 } // namespace OHOS
214
215 #ifdef __cplusplus
216 }
217 #endif
218