• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }