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 if (EGLWindow_ != nullptr) {
94 LOGI("EglManager Init eglSurface from eglWindow");
95 currentSurface_ = eglCreateWindowSurface(EGLDisplay_, EGLConfig_, EGLWindow_, NULL);
96 if (currentSurface_ == NULL) {
97 LOGE("EglManager Init eglSurface = null");
98 return false;
99 }
100 } else {
101 LOGI("EglManager Init eglSurface from PBuffer width = %{public}d, height = %{public}d", EGLWidth_, EGLHeight_);
102 int surfaceAttributes[] = { EGL_WIDTH, EGLWidth_, EGL_HEIGHT, EGLHeight_, EGL_NONE };
103 currentSurface_ = eglCreatePbufferSurface(EGLDisplay_, EGLConfig_, surfaceAttributes);
104 if (currentSurface_ == NULL) {
105 LOGE("EglManager Init eglCreateContext eglSurface = null");
106 return false;
107 }
108 }
109
110 return true;
111 }
112
CreateAndSetEGLContext()113 bool EglManager::CreateAndSetEGLContext()
114 {
115 int attrib3List[] = { EGL_CONTEXT_CLIENT_VERSION, EGL_SUPPORT_VERSION, EGL_NONE };
116 EGLContext_ = eglCreateContext(EGLDisplay_, EGLConfig_, nullptr, attrib3List);
117 int error = eglGetError();
118 if (error == EGL_SUCCESS) {
119 LOGI("EglManager Init Create EGLContext_ ok");
120 } else {
121 LOGE("EglManager Init eglCreateContext error %x", error);
122 return false;
123 }
124 eglMakeCurrent(EGLDisplay_, currentSurface_, currentSurface_, EGLContext_);
125 error = eglGetError();
126 return error == EGL_SUCCESS;
127 }
128
Init()129 EGLBoolean EglManager::Init()
130 {
131 if (initialized_) {
132 if (RetryEGLContext()) {
133 return EGL_TRUE;
134 }
135 }
136
137 initialized_ = true;
138 LOGI("EglManager ----- Init.\n");
139
140 if (EGLContext_ != EGL_NO_CONTEXT && EGLContext_ != nullptr) {
141 LOGW("EglManager Init EGLContext_ is already init.\n");
142 }
143
144 if (!InitializeEGLDisplay()) {
145 return EGL_FALSE;
146 }
147
148 if (!CreateEGLSurface()) {
149 return EGL_FALSE;
150 }
151
152 if (!CreateAndSetEGLContext()) {
153 return EGL_FALSE;
154 }
155 return EGL_TRUE;
156 }
157
Deinit()158 void EglManager::Deinit()
159 {
160 LOGW("Deinit");
161
162 if (EGLDisplay_ == EGL_NO_DISPLAY) {
163 return;
164 }
165
166 eglDestroyContext(EGLDisplay_, EGLContext_);
167 if (currentSurface_ != EGL_NO_SURFACE) {
168 eglDestroySurface(EGLDisplay_, currentSurface_);
169 }
170 eglMakeCurrent(EGLDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
171 eglTerminate(EGLDisplay_);
172 eglReleaseThread();
173
174 EGLDisplay_ = EGL_NO_DISPLAY;
175 EGLContext_ = EGL_NO_CONTEXT;
176 currentSurface_ = EGL_NO_SURFACE;
177 initialized_ = false;
178 }
179
IsEGLContextInCurrentThread(EGLDisplay display,EGLContext context)180 EGLBoolean EglManager::IsEGLContextInCurrentThread(EGLDisplay display, EGLContext context)
181 {
182 EGLBoolean isContextInCurrent = EGL_FALSE;
183 EGLint isContextLost = 0;
184
185 eglQueryContext(display, context, EGL_CONTEXT_LOST, &isContextLost);
186
187 if (!isContextLost && eglGetCurrentContext() == context) {
188 isContextInCurrent = EGL_TRUE;
189 }
190
191 return isContextInCurrent;
192 }
193 } // namespace Rosen
194 } // namespace OHOS
195
196 #ifdef __cplusplus
197 }
198 #endif
199