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
CreateTexture2D(GLsizei width,GLsizei height,GLsizei levels,GLenum internalFormat,GLint minFilter,GLint magFilter,GLint wrapS,GLint wrapT)42 GLuint GLUtils::CreateTexture2D(GLsizei width, GLsizei height, GLsizei levels, GLenum internalFormat, GLint minFilter,
43 GLint magFilter, GLint wrapS, GLint wrapT)
44 {
45 GLuint textureId = 0;
46 glGenTextures(1, &textureId);
47 glBindTexture(GL_TEXTURE_2D, textureId);
48 glTexStorage2D(GL_TEXTURE_2D, levels, internalFormat, width, height);
49 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
50 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
51 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
52 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
53 glBindTexture(GL_TEXTURE_2D, GL_NONE);
54 CheckError(__FILE__, __LINE__);
55 return textureId;
56 }
57
CreateFramebuffer(unsigned int textureId)58 unsigned int GLUtils::CreateFramebuffer(unsigned int textureId)
59 {
60 GLuint fboId;
61 glGenFramebuffers(1, &fboId);
62 if (textureId != 0) {
63 glBindFramebuffer(GL_FRAMEBUFFER, fboId);
64 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);
65 glBindFramebuffer(GL_FRAMEBUFFER, GL_NONE);
66 }
67 return fboId;
68 }
69
CreateFramebufferWithTarget(unsigned int textureId,GLenum target)70 unsigned int GLUtils::CreateFramebufferWithTarget(unsigned int textureId, GLenum target)
71 {
72 GLuint fboId;
73 glGenFramebuffers(1, &fboId);
74 if (textureId != 0) {
75 glBindFramebuffer(GL_FRAMEBUFFER, fboId);
76 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, textureId, 0);
77 glBindFramebuffer(GL_FRAMEBUFFER, GL_NONE);
78 }
79 return fboId;
80 }
81
DeleteFboOnly(unsigned int fbo)82 void GLUtils::DeleteFboOnly(unsigned int fbo)
83 {
84 glDeleteFramebuffers(1, &fbo);
85 }
86
DeleteTexture(unsigned int textureId)87 void GLUtils::DeleteTexture(unsigned int textureId)
88 {
89 if (textureId == 0) {
90 return;
91 }
92 glDeleteTextures(1, &textureId);
93 }
94
CreateTexWithStorage(GLenum target,int levels,GLenum internalFormat,int width,int height)95 GLuint GLUtils::CreateTexWithStorage(GLenum target, int levels, GLenum internalFormat,
96 int width, int height)
97 {
98 GLuint textureId = 0;
99 glGenTextures(1, &textureId);
100 glBindTexture(target, textureId);
101 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
102 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
103 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
104 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
105 glTexStorage2D(target, levels, internalFormat, width, height);
106 glBindTexture(target, 0);
107 return textureId;
108 }
109
CheckError(const char * file,int line)110 void GLUtils::CheckError(const char *file, int line)
111 {
112 GLenum status = glGetError();
113 if (status != GL_NO_ERROR) {
114 EFFECT_LOGE("GL Error: 0x%{public}x, [%{public}s : %{public}d]", status, file, line);
115 }
116 }
117
GetInternalFormatPixelByteSize(GLenum internalFormat)118 size_t GLUtils::GetInternalFormatPixelByteSize(GLenum internalFormat)
119 {
120 int ret = 0;
121 switch (internalFormat) {
122 case GL_RGBA8:
123 case GL_R32F:
124 ret = BYTES_OF_R32F;
125 break;
126 case GL_RGBA16F:
127 ret = BYTES_OF_RGBA16F;
128 break;
129 case GL_R8:
130 ret = BYTES_OF_R8;
131 break;
132 case GL_RGB565:
133 ret = BYTES_OF_RGB565;
134 break;
135 case GL_RGBA4:
136 ret = BYTES_OF_RGBA4;
137 break;
138 default:
139 break;
140 }
141 return ret;
142 }
143
LoadShader(const std::string & src,unsigned int shaderType)144 unsigned int GLUtils::LoadShader(const std::string &src, unsigned int shaderType)
145 {
146 const char* tempSrc = src.c_str();
147 unsigned int shader = glCreateShader(shaderType);
148 if (shader == 0) {
149 EFFECT_LOGE("Could Not Create Shader");
150 }
151 glShaderSource(shader, 1, &tempSrc, nullptr);
152 glCompileShader(shader);
153 int status = GL_FALSE;
154 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
155 if (status == GL_FALSE) {
156 GLchar message[MSG_SIZE] = {0};
157 glGetShaderInfoLog(shader, MSG_SIZE - 1, nullptr, &message[0]);
158 EFFECT_LOGE("LoadShader Error: %{public}s", message);
159 glDeleteShader(shader);
160 shader = 0;
161 }
162 CheckError(__FILE__, __LINE__);
163 return shader;
164 }
165
CreateProgram(const std::string & vss,const std::string & fss)166 unsigned int GLUtils::CreateProgram(const std::string &vss, const std::string &fss)
167 {
168 unsigned int vs = LoadShader(vss, GL_VERTEX_SHADER);
169 unsigned int fs = LoadShader(fss, GL_FRAGMENT_SHADER);
170 if (vs == 0 || fs == 0) {
171 return 0;
172 }
173 unsigned int program = glCreateProgram();
174 if (program == 0) {
175 EFFECT_LOGE("CreateProgram Failed");
176 }
177 glAttachShader(program, vs);
178 glAttachShader(program, fs);
179 glLinkProgram(program);
180 CheckError(__FILE__, __LINE__);
181 int status = GL_FALSE;
182 glGetProgramiv(program, GL_LINK_STATUS, &status);
183 if (status == GL_FALSE) {
184 GLchar message[MSG_SIZE] = {0};
185 glGetShaderInfoLog(program, MSG_SIZE - 1, nullptr, &message[0]);
186 EFFECT_LOGE("LoadShader Error: %{public}s", message);
187 glDeleteProgram(program);
188 program = 0;
189 }
190 if (vs > 0) {
191 glDetachShader(program, vs);
192 glDeleteShader(vs);
193 }
194 if (fs > 0) {
195 glDetachShader(program, fs);
196 glDeleteShader(fs);
197 }
198 return program;
199 }
200
CreateEGLImage(EGLDisplay display,SurfaceBuffer * buffer)201 EGLImageKHR GLUtils::CreateEGLImage(EGLDisplay display, SurfaceBuffer *buffer)
202 {
203 NativeWindowBuffer *nBuffer = CreateNativeWindowBufferFromSurfaceBuffer(&buffer);
204 EGLint attrsList[] = {
205 EGL_IMAGE_PRESERVED,
206 EGL_TRUE,
207 EGL_NONE,
208 };
209 EGLint *attrs = attrsList;
210 EGLImageKHR img = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_OHOS, nBuffer, attrs);
211 if (img == EGL_NO_IMAGE_KHR) {
212 EGLint error = eglGetError();
213 EFFECT_LOGE("CreateEGLImage Error: %{public}d", error);
214 eglTerminate(display);
215 }
216 CheckError(__FILE__, __LINE__);
217 DestroyNativeWindowBuffer(nBuffer);
218 return img;
219 }
220
CreateTextureFromImage(EGLImageKHR img)221 GLuint GLUtils::CreateTextureFromImage(EGLImageKHR img)
222 {
223 GLuint textureId = 0;
224 glGenTextures(1, &textureId);
225 glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
226 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, static_cast<GLeglImageOES>(img));
227 glBindTexture(GL_TEXTURE_EXTERNAL_OES, GL_NONE);
228 CheckError(__FILE__, __LINE__);
229 return textureId;
230 }
231
DestroyImage(EGLImageKHR img)232 void GLUtils::DestroyImage(EGLImageKHR img)
233 {
234 eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), img);
235 }
236
CreateTextureFromSurfaceBuffer(SurfaceBuffer * buffer)237 GLuint GLUtils::CreateTextureFromSurfaceBuffer(SurfaceBuffer *buffer)
238 {
239 if (buffer == nullptr) {
240 return 0;
241 }
242 EGLImageKHR img = CreateEGLImage(eglGetDisplay(EGL_DEFAULT_DISPLAY), buffer);
243 GLuint tex = CreateTextureFromImage(img);
244 return tex;
245 }
246 } // namespace Effect
247 } // namespace Media
248 } // namespace OHOS