• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define GL_GLEXT_PROTOTYPES
17 #define EGL_EGLEXT_PROTOTYPES
18 
19 #include "gl_utils.h"
20 #include "surface_buffer.h"
21 #include "native_window.h"
22 #include "effect_trace.h"
23 #include "effect_log.h"
24 
25 #include <GLES2/gl2ext.h>
26 
27 #include <cmath>
28 #include <string>
29 #include <cstdlib>
30 #include "effect_log.h"
31 
32 namespace OHOS {
33 namespace Media {
34 namespace Effect {
35 constexpr const int MSG_SIZE = 512;
36 constexpr const int BYTES_OF_RGBA16F = 8;
37 constexpr const int BYTES_OF_R32F = 4;
38 constexpr const int BYTES_OF_R8 = 1;
39 constexpr const int BYTES_OF_RGB565 = 2;
40 constexpr const int BYTES_OF_RGBA4 = 2;
41 constexpr const EGLenum FENCE_TYPE = 0x3144;
42 
CreateTexture2D(GLsizei width,GLsizei height,GLsizei levels,GLenum internalFormat,GLint minFilter,GLint magFilter,GLint wrapS,GLint wrapT)43 GLuint GLUtils::CreateTexture2D(GLsizei width, GLsizei height, GLsizei levels, GLenum internalFormat, GLint minFilter,
44     GLint magFilter, GLint wrapS, GLint wrapT)
45 {
46     GLuint textureId = 0;
47     glGenTextures(1, &textureId);
48     glBindTexture(GL_TEXTURE_2D, textureId);
49     glTexStorage2D(GL_TEXTURE_2D, levels, internalFormat, width, height);
50     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
51     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
52     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
53     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
54     glBindTexture(GL_TEXTURE_2D, GL_NONE);
55     CheckError(__FILE__, __LINE__);
56     return textureId;
57 }
58 
CreateDefaultTexture(GLsizei width,GLsizei height,GLenum internalFormat,GLuint textureId)59 void GLUtils::CreateDefaultTexture(GLsizei width, GLsizei height, GLenum internalFormat, GLuint textureId)
60 {
61     glBindTexture(GL_TEXTURE_2D, textureId);
62     glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, width, height);
63     glBindTexture(GL_TEXTURE_2D, GL_NONE);
64     CheckError(__FILE__, __LINE__);
65 }
66 
GetTexWidth(GLuint texture)67 unsigned int GLUtils::GetTexWidth(GLuint texture)
68 {
69     GLint textureWidth = 0;
70     glBindTexture(GL_TEXTURE_2D, texture);
71     glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &textureWidth);
72     glBindTexture(GL_TEXTURE_2D, 0);
73     return textureWidth;
74 }
75 
GetTexHeight(GLuint texture)76 unsigned int GLUtils::GetTexHeight(GLuint texture)
77 {
78     GLint textureHeight = 0;
79     glBindTexture(GL_TEXTURE_2D, texture);
80     glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &textureHeight);
81     glBindTexture(GL_TEXTURE_2D, 0);
82     return textureHeight;
83 }
84 
GetTexFormat(GLuint texture)85 unsigned int GLUtils::GetTexFormat(GLuint texture)
86 {
87     GLint textureFormat = 0;
88     glBindTexture(GL_TEXTURE_2D, texture);
89     glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &textureFormat);
90     glBindTexture(GL_TEXTURE_2D, 0);
91     return textureFormat;
92 }
93 
CreateFramebuffer(unsigned int textureId)94 unsigned int GLUtils::CreateFramebuffer(unsigned int textureId)
95 {
96     GLuint fboId;
97     glGenFramebuffers(1, &fboId);
98     if (textureId != 0) {
99         glBindFramebuffer(GL_FRAMEBUFFER, fboId);
100         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);
101         glBindFramebuffer(GL_FRAMEBUFFER, GL_NONE);
102     }
103     return fboId;
104 }
105 
CreateFramebufferWithTarget(unsigned int textureId,GLenum target)106 unsigned int GLUtils::CreateFramebufferWithTarget(unsigned int textureId, GLenum target)
107 {
108     GLuint fboId;
109     glGenFramebuffers(1, &fboId);
110     if (textureId != 0) {
111         glBindFramebuffer(GL_FRAMEBUFFER, fboId);
112         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, textureId, 0);
113         glBindFramebuffer(GL_FRAMEBUFFER, GL_NONE);
114     }
115     return fboId;
116 }
117 
DeleteFboOnly(unsigned int fbo)118 void GLUtils::DeleteFboOnly(unsigned int fbo)
119 {
120     glDeleteFramebuffers(1, &fbo);
121 }
122 
DeleteTexture(unsigned int textureId)123 void GLUtils::DeleteTexture(unsigned int textureId)
124 {
125     if (textureId == 0) {
126         return;
127     }
128     glDeleteTextures(1, &textureId);
129 }
130 
CreateTexWithStorage(GLenum target,int levels,GLenum internalFormat,int width,int height)131 GLuint GLUtils::CreateTexWithStorage(GLenum target, int levels, GLenum internalFormat,
132     int width, int height)
133 {
134     GLuint textureId = 0;
135     glGenTextures(1, &textureId);
136     glBindTexture(target, textureId);
137     glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
138     glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
139     glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
140     glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
141     glTexStorage2D(target, levels, internalFormat, width, height);
142     glBindTexture(target, 0);
143     return textureId;
144 }
145 
CheckError(const char * file,int line)146 void GLUtils::CheckError(const char *file, int line)
147 {
148     GLenum status = glGetError();
149     if (status != GL_NO_ERROR) {
150         EFFECT_LOGE("GL Error: 0x%{public}x, [%{public}s : %{public}d]", status, file, line);
151     }
152 }
153 
GetInternalFormatPixelByteSize(GLenum internalFormat)154 size_t GLUtils::GetInternalFormatPixelByteSize(GLenum internalFormat)
155 {
156     int ret = 0;
157     switch (internalFormat) {
158         case GL_RGBA8:
159         case GL_R32F:
160         case GL_RGB10_A2:
161             ret = BYTES_OF_R32F;
162             break;
163         case GL_RGBA16F:
164             ret = BYTES_OF_RGBA16F;
165             break;
166         case GL_R8:
167             ret = BYTES_OF_R8;
168             break;
169         case GL_RGB565:
170             ret = BYTES_OF_RGB565;
171             break;
172         case GL_RGBA4:
173             ret = BYTES_OF_RGBA4;
174             break;
175         default:
176             break;
177     }
178     return ret;
179 }
180 
LoadShader(const std::string & src,unsigned int shaderType)181 unsigned int GLUtils::LoadShader(const std::string &src, unsigned int shaderType)
182 {
183     const char* tempSrc = src.c_str();
184     unsigned int shader = glCreateShader(shaderType);
185     if (shader == 0) {
186         EFFECT_LOGE("Could Not Create Shader");
187     }
188     glShaderSource(shader, 1, &tempSrc, nullptr);
189     glCompileShader(shader);
190     int status = GL_FALSE;
191     glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
192     if (status == GL_FALSE) {
193         GLchar message[MSG_SIZE] = {0};
194         glGetShaderInfoLog(shader, MSG_SIZE - 1, nullptr, &message[0]);
195         EFFECT_LOGE("LoadShader Error: %{public}s", message);
196         glDeleteShader(shader);
197         shader = 0;
198     }
199     CheckError(__FILE__, __LINE__);
200     return shader;
201 }
202 
CreateProgram(const std::string & vss,const std::string & fss)203 unsigned int GLUtils::CreateProgram(const std::string &vss, const std::string &fss)
204 {
205     unsigned int vs = LoadShader(vss, GL_VERTEX_SHADER);
206     unsigned int fs = LoadShader(fss, GL_FRAGMENT_SHADER);
207     if (vs == 0 || fs == 0) {
208         return 0;
209     }
210     unsigned int program = glCreateProgram();
211     if (program == 0) {
212         EFFECT_LOGE("CreateProgram Failed");
213     }
214     glAttachShader(program, vs);
215     glAttachShader(program, fs);
216     glLinkProgram(program);
217     CheckError(__FILE__, __LINE__);
218     int status = GL_FALSE;
219     glGetProgramiv(program, GL_LINK_STATUS, &status);
220     if (status == GL_FALSE) {
221         GLchar message[MSG_SIZE] = {0};
222         glGetShaderInfoLog(program, MSG_SIZE - 1, nullptr, &message[0]);
223         EFFECT_LOGE("LoadShader Error: %{public}s", message);
224         glDeleteProgram(program);
225         program = 0;
226     }
227     if (vs > 0) {
228         glDetachShader(program, vs);
229         glDeleteShader(vs);
230     }
231     if (fs > 0) {
232         glDetachShader(program, fs);
233         glDeleteShader(fs);
234     }
235     return program;
236 }
237 
CreateEGLImage(EGLDisplay display,SurfaceBuffer * buffer)238 EGLImageKHR GLUtils::CreateEGLImage(EGLDisplay display, SurfaceBuffer *buffer)
239 {
240     NativeWindowBuffer *nBuffer = CreateNativeWindowBufferFromSurfaceBuffer(&buffer);
241     EGLint attrsList[] = {
242         EGL_IMAGE_PRESERVED,
243         EGL_TRUE,
244         EGL_NONE,
245     };
246     EGLint *attrs = attrsList;
247     EGLImageKHR img = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_OHOS, nBuffer, attrs);
248     if (img == EGL_NO_IMAGE_KHR) {
249         EGLint error = eglGetError();
250         EFFECT_LOGE("CreateEGLImage Error: %{public}d", error);
251         eglTerminate(display);
252     }
253     CheckError(__FILE__, __LINE__);
254     DestroyNativeWindowBuffer(nBuffer);
255     return img;
256 }
257 
CreateTextureFromImage(EGLImageKHR img)258 GLuint GLUtils::CreateTextureFromImage(EGLImageKHR img)
259 {
260     GLuint textureId = 0;
261     glGenTextures(1, &textureId);
262     glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
263     glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, static_cast<GLeglImageOES>(img));
264     glBindTexture(GL_TEXTURE_EXTERNAL_OES, GL_NONE);
265     CheckError(__FILE__, __LINE__);
266     return textureId;
267 }
268 
DestroyImage(EGLImageKHR img)269 void GLUtils::DestroyImage(EGLImageKHR img)
270 {
271     eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), img);
272 }
273 
DestroySyncKHR(EGLSyncKHR sync)274 void GLUtils::DestroySyncKHR(EGLSyncKHR sync)
275 {
276     if (sync != EGL_NO_SYNC_KHR) {
277         eglDestroySyncKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), sync);
278     }
279 }
280 
CreateSyncKHR(EGLSyncKHR & sync)281 void GLUtils::CreateSyncKHR(EGLSyncKHR &sync)
282 {
283     DestroySyncKHR(sync);
284     sync = eglCreateSyncKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), FENCE_TYPE, nullptr);
285 }
286 
GetEGLFenceFd(EGLSyncKHR sync)287 int32_t GLUtils::GetEGLFenceFd(EGLSyncKHR sync)
288 {
289     int32_t glFenceFd = -1;
290     if (sync != EGL_NO_SYNC_KHR) {
291         glFenceFd = eglDupNativeFenceFDANDROID(eglGetDisplay(EGL_DEFAULT_DISPLAY), sync);
292         glFenceFd = glFenceFd >= 0 ? glFenceFd : -1;
293     }
294 
295     return glFenceFd;
296 }
297 
CreateTextureFromSurfaceBuffer(SurfaceBuffer * buffer)298 GLuint GLUtils::CreateTextureFromSurfaceBuffer(SurfaceBuffer *buffer)
299 {
300     if (buffer == nullptr) {
301         return 0;
302     }
303     EGLImageKHR img = CreateEGLImage(eglGetDisplay(EGL_DEFAULT_DISPLAY), buffer);
304     GLuint tex = CreateTextureFromImage(img);
305     return tex;
306 }
307 } // namespace Effect
308 } // namespace Media
309 } // namespace OHOS