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