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