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;
70 EGLint eglMinVers;
71 if (!eglInitialize(EGLDisplay_, &eglMajVers, &eglMinVers)) {
72 EGLDisplay_ = EGL_NO_DISPLAY;
73 LOGE("EglManager Init unable to initialize display.");
74 return false;
75 }
76
77 LOGI("EglManager Init eglMinVers = %{public}u", eglMinVers);
78 int version = EGL_SUPPORT_VERSION;
79 if (eglMinVers >= EGL_LIMIT_VERSION) {
80 version = EGL_SUPPORT_VERSION;
81 }
82
83 EGLConfig_ = EglManager::GetConfig(version, EGLDisplay_);
84 if (EGLConfig_ == NULL) {
85 LOGE("EglManager Init config ERROR");
86 return false;
87 }
88
89 return true;
90 }
91
CreateEGLSurface()92 bool EglManager::CreateEGLSurface()
93 {
94 #ifndef ANDROID_PLATFORM
95 if (EGLWindow_ != nullptr) {
96 LOGI("EglManager Init eglSurface from eglWindow");
97 currentSurface_ = eglCreateWindowSurface(EGLDisplay_, EGLConfig_, EGLWindow_, NULL);
98 if (currentSurface_ == NULL) {
99 LOGE("EglManager Init eglSurface = null");
100 return false;
101 }
102 } else {
103 LOGI("EglManager Init eglSurface from PBuffer width = %{public}d, height = %{public}d", EGLWidth_, EGLHeight_);
104 int surfaceAttributes[] = { EGL_WIDTH, EGLWidth_, EGL_HEIGHT, EGLHeight_, EGL_NONE };
105 currentSurface_ = eglCreatePbufferSurface(EGLDisplay_, EGLConfig_, surfaceAttributes);
106 if (currentSurface_ == NULL) {
107 LOGE("EglManager Init eglCreateContext eglSurface = null");
108 return false;
109 }
110 }
111 #else
112 LOGI("EglManager Init eglSurface from PBuffer width = %{public}d, height = %{public}d", EGLWidth_, EGLHeight_);
113 int surfaceAttributes[] = { EGL_WIDTH, EGLWidth_, EGL_HEIGHT, EGLHeight_, EGL_NONE };
114 currentSurface_ = eglCreatePbufferSurface(EGLDisplay_, EGLConfig_, surfaceAttributes);
115 if (currentSurface_ == NULL) {
116 LOGE("EglManager Init eglCreateContext eglSurface = null");
117 return false;
118 }
119 #endif
120 return true;
121 }
122
CreateAndSetEGLContext()123 bool EglManager::CreateAndSetEGLContext()
124 {
125 int attrib3List[] = { EGL_CONTEXT_CLIENT_VERSION, EGL_SUPPORT_VERSION, EGL_NONE };
126 EGLContext_ = eglCreateContext(EGLDisplay_, EGLConfig_, nullptr, attrib3List);
127 int error = eglGetError();
128 if (error == EGL_SUCCESS) {
129 LOGI("EglManager Init Create EGLContext_ ok");
130 } else {
131 LOGE("EglManager Init eglCreateContext error %x", error);
132 return false;
133 }
134 eglMakeCurrent(EGLDisplay_, currentSurface_, currentSurface_, EGLContext_);
135 error = eglGetError();
136 return error == EGL_SUCCESS;
137 }
138
Init()139 EGLBoolean EglManager::Init()
140 {
141 if (initialized_) {
142 if (RetryEGLContext()) {
143 return EGL_TRUE;
144 }
145 }
146
147 initialized_ = true;
148 LOGI("EglManager ----- Init.\n");
149
150 if (EGLContext_ != EGL_NO_CONTEXT && EGLContext_ != nullptr) {
151 LOGW("EglManager Init EGLContext_ is already init.\n");
152 }
153
154 if (!InitializeEGLDisplay()) {
155 return EGL_FALSE;
156 }
157
158 if (!CreateEGLSurface()) {
159 return EGL_FALSE;
160 }
161
162 if (!CreateAndSetEGLContext()) {
163 return EGL_FALSE;
164 }
165 return EGL_TRUE;
166 }
167
Deinit()168 void EglManager::Deinit()
169 {
170 LOGW("Deinit");
171
172 if (EGLDisplay_ == EGL_NO_DISPLAY) {
173 return;
174 }
175
176 eglDestroyContext(EGLDisplay_, EGLContext_);
177 if (currentSurface_ != EGL_NO_SURFACE) {
178 eglDestroySurface(EGLDisplay_, currentSurface_);
179 }
180 eglMakeCurrent(EGLDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
181 eglTerminate(EGLDisplay_);
182 eglReleaseThread();
183
184 EGLDisplay_ = EGL_NO_DISPLAY;
185 EGLContext_ = EGL_NO_CONTEXT;
186 currentSurface_ = EGL_NO_SURFACE;
187 initialized_ = false;
188 }
189
IsEGLContextInCurrentThread(EGLDisplay display,EGLContext context)190 EGLBoolean EglManager::IsEGLContextInCurrentThread(EGLDisplay display, EGLContext context)
191 {
192 if (display == EGL_NO_DISPLAY) {
193 LOGE("EglManager IsEGLContextInCurrentThread display is EGL_NO_DISPLAY");
194 return EGL_FALSE;
195 }
196
197 if (context == EGL_NO_CONTEXT) {
198 LOGE("EglManager IsEGLContextInCurrentThread context is EGL_NO_CONTEXT");
199 return EGL_FALSE;
200 }
201
202 EGLBoolean isContextInCurrent = EGL_FALSE;
203 EGLint isContextLost = 0;
204
205 eglQueryContext(display, context, EGL_CONTEXT_LOST, &isContextLost);
206
207 if (!isContextLost && eglGetCurrentContext() == context) {
208 isContextInCurrent = EGL_TRUE;
209 }
210
211 return isContextInCurrent;
212 }
213 } // namespace Rosen
214 } // namespace OHOS
215
216 #ifdef __cplusplus
217 }
218 #endif
219