1 /*
2  * Copyright (c) 2021-2023 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 "util/egl_manager.h"
17 
18 #include <cstddef>
19 #include "EGL/egl.h"
20 #include "EGL/eglplatform.h"
21 #include "__config"
22 #include "util/log.h"
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 namespace OHOS {
29 namespace Rosen {
30 namespace {
31     const int OPENGL_ES2_VERSION = 2;
32     const int OPENGL_ES3_VERSION = 3;
33 }
34 using namespace std;
35 
GetConfig(int version,EGLDisplay eglDisplay)36 EGLConfig EglManager::GetConfig(int version, EGLDisplay eglDisplay)
37 {
38     EGLint renderableType = EGL_OPENGL_ES2_BIT;
39     if (version == OPENGL_ES3_VERSION) {
40         renderableType = EGL_OPENGL_ES3_BIT;
41     }
42     int attribList[] = {
43         EGL_SURFACE_TYPE, EGL_PBUFFER_BIT | EGL_WINDOW_BIT,
44         EGL_RENDERABLE_TYPE, renderableType,
45         EGL_RED_SIZE, 8,
46         EGL_GREEN_SIZE, 8,
47         EGL_BLUE_SIZE, 8,
48         EGL_ALPHA_SIZE, 8,
49         EGL_DEPTH_SIZE, 24,
50         EGL_NONE
51     };
52     EGLConfig configs = NULL;
53     int numConfigs;
54     if (!eglChooseConfig(eglDisplay, attribList, &configs, 1, &numConfigs)) {
55         LOGE("eglChooseConfig ERROR");
56         return NULL;
57     }
58     return configs;
59 }
60 
MakeCurrentIfNeeded(EGLSurface newEGLSurface)61 void EglManager::MakeCurrentIfNeeded(EGLSurface newEGLSurface)
62 {
63     if (currentSurface_ != newEGLSurface) {
64         currentSurface_ = newEGLSurface;
65         eglMakeCurrent(eglDisplay_, currentSurface_, currentSurface_, eglContext_);
66     }
67 }
68 
CreateSurface(NativeWindow * window)69 EGLSurface EglManager::CreateSurface(NativeWindow* window)
70 {
71     EGLSurface eglSurface = nullptr;
72     if (window) {
73         LOGD("EglManager CreateSurface from eglWindow");
74         eglSurface = eglCreateWindowSurface(eglDisplay_, eglConfig_, window, NULL);
75     } else {
76         LOGD("EglManager CreateSurface from PBuffer width = %{public}d, height = %{public}d",
77             eglWidth_, eglHeight_);
78         int surfaceAttributes[] = {
79             EGL_WIDTH, eglWidth_,
80             EGL_HEIGHT, eglHeight_,
81             EGL_NONE
82         };
83         eglSurface = eglCreatePbufferSurface(eglDisplay_, eglConfig_, surfaceAttributes);
84     }
85     if (eglSurface == NULL) {
86         LOGE("EglManager CreateSurface eglSurface = null error %{public}d", eglGetError());
87     }
88     return eglSurface;
89 }
90 
CreateContext(int version)91 void EglManager::CreateContext(int version)
92 {
93     if (eglWindow_) {
94         LOGD("EglManager Init eglSurface from eglWindow");
95         currentSurface_ = eglCreateWindowSurface(eglDisplay_, eglConfig_, eglWindow_, NULL);
96         if (currentSurface_ == NULL) {
97             LOGE("EglManager Init eglSurface = null");
98             return;
99         }
100     } else {
101         LOGD("EglManager Init eglSurface from PBuffer width = %{public}d, height = %{public}d",
102             eglWidth_, eglHeight_);
103         int surfaceAttributes[] = {
104             EGL_WIDTH, eglWidth_,
105             EGL_HEIGHT, eglHeight_,
106             EGL_NONE
107         };
108         currentSurface_ = eglCreatePbufferSurface(eglDisplay_, eglConfig_, surfaceAttributes);
109         if (currentSurface_ == NULL) {
110             LOGE("EglManager Init eglCreateContext eglSurface = null");
111             return;
112         }
113     }
114 
115     int attrib3List[] = {
116         EGL_CONTEXT_CLIENT_VERSION, version,
117         EGL_NONE
118     };
119     eglContext_ = eglCreateContext(eglDisplay_, eglConfig_, nullptr, attrib3List);
120     int error = eglGetError();
121     if (error == EGL_SUCCESS) {
122         LOGD("EglManager Init Create mEGLContext ok");
123     } else {
124         LOGE("EglManager Init eglCreateContext error %{public}x", error);
125         return;
126     }
127     eglMakeCurrent(eglDisplay_, currentSurface_, currentSurface_, eglContext_);
128 }
129 
Init()130 void EglManager::Init()
131 {
132     if (initialized_) {
133         return;
134     }
135     initialized_ = true;
136     LOGD("EglManager Init.");
137     if (eglContext_ != nullptr) {
138         LOGE("EglManager Init mEGLContext is already init.");
139         return;
140     }
141 
142     eglDisplay_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
143     if (eglDisplay_ == EGL_NO_DISPLAY) {
144         LOGE("EglManager Init unable to get EGL display.");
145         return;
146     }
147 
148     EGLint eglMajVers, eglMinVers;
149     if (!eglInitialize(eglDisplay_, &eglMajVers, &eglMinVers)) {
150         eglDisplay_ = EGL_NO_DISPLAY;
151         LOGE("EglManager Init unable to initialize display");
152         return;
153     }
154 
155     int version = OPENGL_ES3_VERSION;
156     eglConfig_ = EglManager::GetConfig(version, eglDisplay_);
157     if (eglConfig_ == NULL) {
158         LOGE("EglManager Init config ERROR, try again");
159         version = OPENGL_ES2_VERSION;
160         eglConfig_ = EglManager::GetConfig(version, eglDisplay_);
161         if (eglConfig_ == NULL) {
162             LOGE("EglManager Init config ERROR again");
163             return;
164         }
165     }
166     CreateContext(version);
167 }
168 } // namespace Rosen
169 } // namespace OHOS
170 #ifdef __cplusplus
171 }
172 #endif
173