1 /*
2 * Copyright (c) 2024 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/egl.h>
17 #include <EGL/eglext.h>
18 #include <EGL/eglplatform.h>
19 #include <GLES3/gl3.h>
20 #include <hilog/log.h>
21 #include <algorithm>
22 #include "egl_core.h"
23 #include "plugin_render.h"
24 #include "common.h"
25
26 namespace OHOS {
EglContextInit(void * window,int width,int height)27 bool EGLCore::EglContextInit(void *window, int width, int height)
28 {
29 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "EglContextInit execute");
30 if ((window == nullptr) || (width <= 0) || (height <= 0)) {
31 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "EglContextInit: param error");
32 return false;
33 }
34
35 width_ = width;
36 height_ = height;
37 widthpercent_ = FIFTY_PERCENT * height_ / width_;
38 eglwindow_ = static_cast<EGLNativeWindowType>(window);
39
40 // Init display.
41 egldisplay_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
42 if (egldisplay_ == EGL_NO_DISPLAY) {
43 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglGetDisplay: unable to get EGL display");
44 return false;
45 }
46
47 EGLint majorVersion;
48 EGLint minorVersion;
49 if (!eglInitialize(egldisplay_, &majorVersion, &minorVersion)) {
50 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore",
51 "eglInitialize: unable to get initialize EGL display");
52 return false;
53 }
54
55 // Select configuration.
56 const EGLint maxConfigSize = 1;
57 EGLint numConfigs;
58 if (!eglChooseConfig(egldisplay_, ATTRIB_LIST, &eglconfig_, maxConfigSize, &numConfigs)) {
59 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglChooseConfig: unable to choose configs");
60 return false;
61 }
62
63 return CreateEnvironment();
64 }
65
CreateEnvironment()66 bool EGLCore::CreateEnvironment()
67 {
68 if (eglwindow_ == nullptr) {
69 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglwindow_ is null");
70 return false;
71 }
72 eglsurface_ = eglCreateWindowSurface(egldisplay_, eglconfig_, eglwindow_, nullptr);
73 if (eglsurface_ == nullptr) {
74 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore",
75 "eglCreateWindowSurface: unable to create WindowSurface");
76 return false;
77 }
78
79 // Create context.
80 eglcontext_ = eglCreateContext(egldisplay_, eglconfig_, EGL_NO_CONTEXT, CONTEXT_ATTRIBS);
81 if (!eglMakeCurrent(egldisplay_, eglsurface_, eglsurface_, eglcontext_)) {
82 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglMakeCurrent failed");
83 return false;
84 }
85
86 // Create program.
87 program_ = CreateProgram(VERTEX_SHADER, FRAGMENT_SHADER);
88 if (program_ == PROGRAM_ERROR) {
89 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "CreateProgram: unable to create program");
90 return false;
91 }
92 return true;
93 }
94
CreateProgram(const char * vertexShader,const char * fragShader)95 GLuint EGLCore::CreateProgram(const char *vertexShader, const char *fragShader)
96 {
97 if ((vertexShader == nullptr) || (fragShader == nullptr)) {
98 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore",
99 "createProgram: vertexShader or fragShader is null");
100 return PROGRAM_ERROR;
101 }
102
103 GLuint vertex = LoadShader(GL_VERTEX_SHADER, vertexShader);
104 if (vertex == PROGRAM_ERROR) {
105 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram vertex error");
106 return PROGRAM_ERROR;
107 }
108
109 GLuint fragment = LoadShader(GL_FRAGMENT_SHADER, fragShader);
110 if (fragment == PROGRAM_ERROR) {
111 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram fragment error");
112 return PROGRAM_ERROR;
113 }
114
115 GLuint program = glCreateProgram();
116 if (program == PROGRAM_ERROR) {
117 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram program error");
118 glDeleteShader(vertex);
119 glDeleteShader(fragment);
120 return PROGRAM_ERROR;
121 }
122
123 glAttachShader(program, vertex);
124 glAttachShader(program, fragment);
125 glLinkProgram(program);
126
127 GLint linked;
128 glGetProgramiv(program, GL_LINK_STATUS, &linked);
129 if (linked != 0) {
130 glDeleteShader(vertex);
131 glDeleteShader(fragment);
132 return program;
133 }
134
135 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram linked error");
136 GLint infoLen = 0;
137 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
138 if (infoLen > 1) {
139 char *infoLog = static_cast<char*>(malloc(sizeof(char) * (infoLen + 1)));
140 std::fill(infoLog, infoLog + infoLen, 0);
141 glGetProgramInfoLog(program, infoLen, nullptr, infoLog);
142 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glLinkProgram error = %s", infoLog);
143 free(infoLog);
144 infoLog = nullptr;
145 }
146 glDeleteShader(vertex);
147 glDeleteShader(fragment);
148 glDeleteProgram(program);
149 return PROGRAM_ERROR;
150 }
151
LoadShader(GLenum type,const char * shaderSrc)152 GLuint EGLCore::LoadShader(GLenum type, const char *shaderSrc)
153 {
154 if ((type <= 0) || (shaderSrc == nullptr)) {
155 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCreateShader type or shaderSrc error");
156 return PROGRAM_ERROR;
157 }
158
159 GLuint shader = glCreateShader(type);
160 if (shader == 0) {
161 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCreateShader unable to load shader");
162 return PROGRAM_ERROR;
163 }
164
165 // The gl function has no return value.
166 glShaderSource(shader, 1, &shaderSrc, nullptr);
167 glCompileShader(shader);
168
169 GLint compiled;
170 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
171 if (compiled != 0) {
172 return shader;
173 }
174
175 GLint infoLen = 0;
176 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
177 if (infoLen <= 1) {
178 glDeleteShader(shader);
179 return PROGRAM_ERROR;
180 }
181
182 char *infoLog = static_cast<char*>(malloc(sizeof(char) * (infoLen + 1)));
183 if (infoLog != nullptr) {
184 std::fill(infoLog, infoLog + infoLen, 0);
185 glGetShaderInfoLog(shader, infoLen, nullptr, infoLog);
186 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCompileShader error = %s", infoLog);
187 free(infoLog);
188 infoLog = nullptr;
189 }
190 glDeleteShader(shader);
191 return PROGRAM_ERROR;
192 }
193
Draw()194 void EGLCore::Draw()
195 {
196 flag_ = false;
197 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "Draw");
198 GLint position = PrepareDraw();
199 if (position == POSITION_ERROR) {
200 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw get position failed");
201 return;
202 }
203
204 if (!ExecuteDraw(position, BACKGROUND_COLOR, BACKGROUND_RECTANGLE_VERTICES,
205 sizeof(BACKGROUND_RECTANGLE_VERTICES))) {
206 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw background failed");
207 return;
208 }
209
210 const GLfloat rectangleVertices[] = {
211 -widthpercent_, FIFTY_PERCENT,
212 widthpercent_, FIFTY_PERCENT,
213 widthpercent_, -FIFTY_PERCENT,
214 -widthpercent_, -FIFTY_PERCENT
215 };
216 if (!ExecuteDraw(position, DRAW_COLOR, rectangleVertices, sizeof(rectangleVertices))) {
217 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw rectangle failed");
218 return;
219 }
220
221 if (!FinishDraw()) {
222 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw FinishDraw failed");
223 return;
224 }
225
226 flag_ = true;
227 }
228
PrepareDraw()229 GLint EGLCore::PrepareDraw()
230 {
231 if ((egldisplay_ == nullptr) || (eglsurface_ == nullptr) || (eglcontext_ == nullptr) ||
232 (!eglMakeCurrent(egldisplay_, eglsurface_, eglsurface_, eglcontext_))) {
233 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "PrepareDraw: param error");
234 return POSITION_ERROR;
235 }
236
237 // The gl function has no return value.
238 glViewport(0, 0, width_, height_);
239 glClearColor(0, 255, 0, 1); //255 is color value, 1 is transparency
240 glClear(GL_COLOR_BUFFER_BIT);
241 glUseProgram(program_);
242
243 return glGetAttribLocation(program_, "a_position");
244 }
245
ExecuteDraw(GLint position,const GLfloat * color,const GLfloat rectangleVertices[],unsigned long vertSize)246 bool EGLCore::ExecuteDraw(GLint position, const GLfloat *color, const GLfloat rectangleVertices[],
247 unsigned long vertSize)
248 {
249 if ((position < 0) || (color == nullptr) || (vertSize / sizeof(rectangleVertices[0]) != RECTANGLE_VERTICES_SIZE)) {
250 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error");
251 return false;
252 }
253
254 // The gl function has no return value.
255 glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, rectangleVertices);
256 glEnableVertexAttribArray(position);
257 glVertexAttrib4fv(1, color);
258 glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE);
259 glDisableVertexAttribArray(position);
260
261 return true;
262 }
263
FinishDraw()264 bool EGLCore::FinishDraw()
265 {
266 // The gl function has no return value.
267 glFlush();
268 glFinish();
269 return eglSwapBuffers(egldisplay_, eglsurface_);
270 }
271
Release()272 void EGLCore::Release()
273 {
274 if ((egldisplay_ == nullptr) || (eglsurface_ == nullptr) || (!eglDestroySurface(egldisplay_, eglsurface_))) {
275 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroySurface failed");
276 }
277
278 if ((egldisplay_ == nullptr) || (eglcontext_ == nullptr) || (!eglDestroyContext(egldisplay_, eglcontext_))) {
279 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroyContext failed");
280 }
281
282 if ((egldisplay_ == nullptr) || (!eglTerminate(egldisplay_))) {
283 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglTerminate failed");
284 }
285 }
286 } // namespace OHOS