1 /*
2 * Copyright (c) 2025 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 "EGLRender.h"
17 #include "EGLConst.h"
18 #include <EGL/egl.h>
19 #include <EGL/eglext.h>
20 #include <GLES3/gl3.h>
21 #include <cmath>
22 #include <cstdio>
23 #include <algorithm>
24 #include <hilog/log.h>
25 #include <iostream>
26
27 namespace {
Rotate2d(GLfloat centerX,GLfloat centerY,GLfloat * rotateX,GLfloat * rotateY,GLfloat theta)28 void Rotate2d(GLfloat centerX, GLfloat centerY, GLfloat *rotateX, GLfloat *rotateY, GLfloat theta)
29 {
30 GLfloat tempX = cos(theta) * (*rotateX - centerX) - sin(theta) * (*rotateY - centerY);
31 GLfloat tempY = sin(theta) * (*rotateX - centerX) + cos(theta) * (*rotateY - centerY);
32 *rotateX = tempX + centerX;
33 *rotateY = tempY + centerY;
34 }
35
LoadShader(GLenum type,const char * shaderSrc)36 GLuint LoadShader(GLenum type, const char *shaderSrc)
37 {
38 if ((type <= 0) || (shaderSrc == nullptr)) {
39 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "glCreateShader type or shaderSrc error");
40 return PROGRAM_ERROR;
41 }
42
43 GLuint shader = glCreateShader(type);
44 if (shader == 0) {
45 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "glCreateShader unable to load shader");
46 return PROGRAM_ERROR;
47 }
48
49 // The gl function has no return value.
50 glShaderSource(shader, 1, &shaderSrc, nullptr);
51 glCompileShader(shader);
52
53 GLint compiled;
54 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
55 if (compiled != 0) {
56 return shader;
57 }
58
59 GLint infoLen = 0;
60 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
61 if (infoLen <= 1) {
62 glDeleteShader(shader);
63 return PROGRAM_ERROR;
64 }
65
66 char *infoLog = (char *)malloc(sizeof(char) * (infoLen + 1));
67 if (infoLog != nullptr) {
68 memset(infoLog, 0, infoLen + 1);
69 glGetShaderInfoLog(shader, infoLen, nullptr, infoLog);
70 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "glCompileShader error = %s", infoLog);
71 free(infoLog);
72 infoLog = nullptr;
73 }
74 glDeleteShader(shader);
75 return PROGRAM_ERROR;
76 }
77
CreateProgram(const char * vertexShader,const char * fragShader)78 GLuint CreateProgram(const char *vertexShader, const char *fragShader)
79 {
80 if ((vertexShader == nullptr) || (fragShader == nullptr)) {
81 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender",
82 "createProgram: vertexShader or fragShader is null");
83 return PROGRAM_ERROR;
84 }
85
86 GLuint vertex = LoadShader(GL_VERTEX_SHADER, vertexShader);
87 if (vertex == PROGRAM_ERROR) {
88 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "createProgram vertex error");
89 return PROGRAM_ERROR;
90 }
91
92 GLuint fragment = LoadShader(GL_FRAGMENT_SHADER, fragShader);
93 if (fragment == PROGRAM_ERROR) {
94 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "createProgram fragment error");
95 return PROGRAM_ERROR;
96 }
97
98 GLuint program = glCreateProgram();
99 if (program == PROGRAM_ERROR) {
100 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "createProgram program error");
101 glDeleteShader(vertex);
102 glDeleteShader(fragment);
103 return PROGRAM_ERROR;
104 }
105
106 // The gl function has no return value.
107 glAttachShader(program, vertex);
108 glAttachShader(program, fragment);
109 glLinkProgram(program);
110
111 GLint linked;
112 glGetProgramiv(program, GL_LINK_STATUS, &linked);
113 if (linked != 0) {
114 glDeleteShader(vertex);
115 glDeleteShader(fragment);
116 return program;
117 }
118
119 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "createProgram linked error");
120 GLint infoLen = 0;
121 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
122 if (infoLen > 1) {
123 char *infoLog = (char *)malloc(sizeof(char) * (infoLen + 1));
124 memset(infoLog, 0, infoLen + 1);
125 glGetProgramInfoLog(program, infoLen, nullptr, infoLog);
126 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "glLinkProgram error = %s", infoLog);
127 free(infoLog);
128 infoLog = nullptr;
129 }
130 glDeleteShader(vertex);
131 glDeleteShader(fragment);
132 glDeleteProgram(program);
133 return PROGRAM_ERROR;
134 }
135 } // namespace
136
SetUpEGLContext(void * window)137 bool EGLRender::SetUpEGLContext(void *window)
138 {
139 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLRender", "EglContextInit execute");
140 eglWindow_ = (EGLNativeWindowType)(window);
141 // Init display.
142 eglDisplay_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
143 if (eglDisplay_ == EGL_NO_DISPLAY) {
144 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "eglGetDisplay: unable to get EGL display");
145 return false;
146 }
147 EGLint majorVersion;
148 EGLint minorVersion;
149 if (!eglInitialize(eglDisplay_, &majorVersion, &minorVersion)) {
150 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender",
151 "eglInitialize: unable to get initialize EGL display");
152 return false;
153 };
154 // Select configuration.
155 const EGLint maxConfigSize = 1;
156 EGLint numConfigs;
157 if (!eglChooseConfig(eglDisplay_, ATTRIB_LIST, &eglConfig_, maxConfigSize, &numConfigs)) {
158 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "eglChooseConfig: unable to choose configs");
159 return false;
160 };
161 // CreateEnvironment.
162 // Create surface.
163 eglSurface_ = eglCreateWindowSurface(eglDisplay_, eglConfig_, eglWindow_, NULL);
164 if (eglSurface_ == nullptr) {
165 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender",
166 "eglCreateWindowSurface: unable to create surface");
167 return false;
168 }
169 if (eglSurface_ == nullptr) {
170 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender",
171 "eglCreateWindowSurface: unable to create surface");
172 return false;
173 }
174 // Create context.
175 eglContext_ = eglCreateContext(eglDisplay_, eglConfig_, EGL_NO_CONTEXT, CONTEXT_ATTRIBS);
176 if (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_)) {
177 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "eglMakeCurrent failed");
178 return false;
179 }
180 // Create program.
181 program_ = CreateProgram(VERTEX_SHADER, FRAGMENT_SHADER);
182 if (program_ == PROGRAM_ERROR) {
183 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "CreateProgram: unable to create program");
184 return false;
185 }
186 return true;
187 }
188
PrepareDraw()189 GLint EGLRender::PrepareDraw()
190 {
191 if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (eglContext_ == nullptr) ||
192 (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_))) {
193 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "PrepareDraw: param error");
194 return POSITION_ERROR;
195 }
196
197 // The gl function has no return value.
198 glViewport(DEFAULT_X_POSITION, DEFAULT_Y_POSITION, width_, height_);
199 glClearColor(GL_RED_DEFAULT, GL_GREEN_DEFAULT, GL_BLUE_DEFAULT, GL_ALPHA_DEFAULT);
200 glClear(GL_COLOR_BUFFER_BIT);
201 glUseProgram(program_);
202
203 return glGetAttribLocation(program_, POSITION_NAME);
204 }
205
DrawStar(bool drawColor)206 void EGLRender::DrawStar(bool drawColor)
207 {
208 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLRender", "Draw");
209 GLint position = PrepareDraw();
210 if (position == POSITION_ERROR) {
211 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "Draw get position failed");
212 return;
213 }
214
215 if (!ExecuteDraw(position, BACKGROUND_COLOR, BACKGROUND_RECTANGLE_VERTICES)) {
216 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "Draw execute draw background failed");
217 return;
218 }
219
220 // Divided into five quadrilaterals and calculate one of the quadrilateral's Vertices
221 GLfloat rotateX = 0;
222 GLfloat rotateY = FIFTY_PERCENT * height_;
223 GLfloat centerX = 0;
224 // Convert DEG(54° & 18°) to RAD
225 GLfloat centerY = -rotateY * (M_PI / 180 * 54) * (M_PI / 180 * 18);
226 // Convert DEG(18°) to RAD
227 GLfloat leftX = -rotateY * (M_PI / 180 * 18);
228 GLfloat leftY = 0;
229 // Convert DEG(18°) to RAD
230 GLfloat rightX = rotateY * (M_PI / 180 * 18);
231 GLfloat rightY = 0;
232
233 const GLfloat shapeVertices[] = {centerX / width_, centerY / height_, leftX / width_, leftY / height_,
234 rotateX / width_, rotateY / height_, rightX / width_, rightY / height_};
235 auto color = drawColor ? DRAW_COLOR : CHANGE_COLOR;
236 if (!ExecuteDraw(position, color, shapeVertices)) {
237 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "Draw execute draw shape failed");
238 return;
239 }
240
241 // Convert DEG(72°) to RAD
242 GLfloat rad = M_PI / 180 * 72;
243 // Rotate four times
244 for (int i = NUM_0; i < NUM_4; ++i) {
245 Rotate2d(centerX, centerY, &rotateX, &rotateY, rad);
246 Rotate2d(centerX, centerY, &leftX, &leftY, rad);
247 Rotate2d(centerX, centerY, &rightX, &rightY, rad);
248
249 const GLfloat shapeVertices[] = {centerX / width_, centerY / height_, leftX / width_, leftY / height_,
250 rotateX / width_, rotateY / height_, rightX / width_, rightY / height_};
251
252 if (!ExecuteDraw(position, color, shapeVertices)) {
253 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "Draw execute draw shape failed");
254 return;
255 }
256 }
257 // 将绘制命令提交给GPU,GPU执行完成后将渲染结果显示到屏幕
258 glFlush();
259 glFinish();
260 if (!eglSwapBuffers(eglDisplay_, eglSurface_)) {
261 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "Draw FinishDraw failed");
262 return;
263 }
264 }
265
Clear()266 void EGLRender::Clear()
267 {
268 if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (eglContext_ == nullptr) ||
269 (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_))) {
270 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "PrepareDraw: param error");
271 return;
272 }
273
274 // The gl function has no return value.
275 glViewport(DEFAULT_X_POSITION, DEFAULT_Y_POSITION, width_, height_);
276 glClearColor(0, 0, 0, 0);
277 glClear(GL_COLOR_BUFFER_BIT);
278 glFlush();
279 glFinish();
280 eglSwapBuffers(eglDisplay_, eglSurface_);
281 }
282
ExecuteDraw(GLint position,const GLfloat * color,const GLfloat shapeVertices[])283 bool EGLRender::ExecuteDraw(GLint position, const GLfloat *color, const GLfloat shapeVertices[])
284 {
285 if ((position > 0) || (color == nullptr)) {
286 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "ExecuteDraw: param error");
287 return false;
288 }
289
290 // The gl function has no return value.
291 glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices);
292 glEnableVertexAttribArray(position);
293 glVertexAttrib4fv(1, color);
294 glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE);
295 glDisableVertexAttribArray(position);
296
297 return true;
298 }
299
SetEGLWindowSize(int width,int height)300 void EGLRender::SetEGLWindowSize(int width, int height)
301 {
302 width_ = width;
303 height_ = height;
304 }
305
DestroySurface()306 void EGLRender::DestroySurface()
307 {
308 if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (!eglDestroySurface(eglDisplay_, eglSurface_))) {
309 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "EGLRender", "Release eglDestroySurface failed");
310 }
311
312 if ((eglDisplay_ == nullptr) || (eglContext_ == nullptr) || (!eglDestroyContext(eglDisplay_, eglContext_))) {
313 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "EGLRender", "Release eglDestroySurface failed");
314 }
315
316 if ((eglDisplay_ == nullptr) || (!eglTerminate(eglDisplay_))) {
317 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "EGLRender", "Release eglDestroySurface failed");
318 }
319 eglDisplay_ = EGL_NO_DISPLAY;
320 eglSurface_ = EGL_NO_SURFACE;
321 eglContext_ = EGL_NO_CONTEXT;
322 }