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 #include <GLES3/gl3.h>
17 #include <cstdint>
18 #include "gl_utils.h"
19 #include "third_party/externals/oboe/samples/RhythmGame/third_party/glm/gtc/matrix_transform.hpp"
20
21 constexpr uint32_t MESSAGE_MAX_SIZE = 511;
22
23 namespace OHOS {
24 namespace Media {
25 namespace {
26 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_VIDEOEDITOR, "VideoEditorRender"};
27 }
CreateTexture2D(GLsizei width,GLsizei height,GLenum internalFormat,GLint minFilter,GLint magFilter)28 GLuint GLUtils::CreateTexture2D(GLsizei width, GLsizei height, GLenum internalFormat, GLint minFilter,
29 GLint magFilter)
30 {
31 GLuint textureId = 0;
32 glGenTextures(1, &textureId);
33 glBindTexture(GL_TEXTURE_2D, textureId);
34 glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, width, height);
35 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
36 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
37 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
38 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
39 glBindTexture(GL_TEXTURE_2D, GL_NONE);
40 return textureId;
41 }
42
CreateTexture2DNoStorage(GLint minFilter,GLint magFilter,GLint wrapS,GLint wrapT)43 GLuint GLUtils::CreateTexture2DNoStorage(GLint minFilter, GLint magFilter, GLint wrapS, GLint wrapT)
44 {
45 GLuint tex;
46 glGenTextures(1, &tex);
47 glBindTexture(GL_TEXTURE_2D, tex);
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 GLUtils::CheckError(__FILE_NAME__, __LINE__);
53 return tex;
54 }
55
CreateFramebuffer(GLuint textureId)56 GLuint GLUtils::CreateFramebuffer(GLuint textureId)
57 {
58 GLuint fboId;
59 glGenFramebuffers(1, &fboId);
60 if (textureId != 0) {
61 glBindFramebuffer(GL_FRAMEBUFFER, fboId);
62 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);
63 glBindFramebuffer(GL_FRAMEBUFFER, GL_NONE);
64 }
65 return fboId;
66 }
67
DeleteTexture(GLuint texture)68 void GLUtils::DeleteTexture(GLuint texture)
69 {
70 if (texture == 0) {
71 return;
72 }
73 glDeleteTextures(1, &texture);
74 }
75
DeleteFboOnly(GLuint fbo)76 void GLUtils::DeleteFboOnly(GLuint fbo)
77 {
78 glDeleteFramebuffers(1, &fbo);
79 }
80
CopyTexture(GLuint srcTexId,GLuint dstTexId,GLint width,GLint height)81 void GLUtils::CopyTexture(GLuint srcTexId, GLuint dstTexId, GLint width, GLint height)
82 {
83 glBindTexture(GL_TEXTURE_2D, dstTexId);
84 GLuint tempFbo;
85 glGenFramebuffers(1, &tempFbo);
86 glBindFramebuffer(GL_FRAMEBUFFER, tempFbo);
87 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcTexId, 0);
88 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
89
90 glBindTexture(GL_TEXTURE_2D, GL_NONE);
91 glBindFramebuffer(GL_FRAMEBUFFER, GL_NONE);
92 glDeleteFramebuffers(1, &tempFbo);
93 }
94
CreateTexNoStorage(GLenum target)95 GLuint GLUtils::CreateTexNoStorage(GLenum target)
96 {
97 GLuint tex;
98 glGenTextures(1, &tex);
99 glBindTexture(target, tex);
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 glBindTexture(target, 0);
105 return tex;
106 }
107
GetInternalFormatPixelByteSize(GLenum internalFormat)108 size_t GLUtils::GetInternalFormatPixelByteSize(GLenum internalFormat)
109 {
110 size_t ret = 0;
111 const int32_t ARGS_TWO = 2;
112 const int32_t ARGS_EIGHT = 8;
113 const int32_t ARGS_FOUR = 4;
114 switch (internalFormat) {
115 case GL_RGBA8:
116 case GL_R32F:
117 ret = ARGS_FOUR;
118 break;
119 case GL_RGBA16F:
120 ret = ARGS_EIGHT;
121 break;
122 case GL_R8:
123 ret = 1;
124 break;
125 case GL_RGB565:
126 ret = ARGS_TWO;
127 break;
128 case GL_RGBA4:
129 ret = ARGS_TWO;
130 break;
131 default:
132 break;
133 }
134 return ret;
135 }
136
LoadShader(const std::string & src,uint32_t shaderType)137 GLuint GLUtils::LoadShader(const std::string& src, uint32_t shaderType)
138 {
139 const char* tempSrc = src.c_str();
140 GLuint shader = glCreateShader(shaderType);
141 if (shader == 0) {
142 MEDIA_LOGE("Could Not Create Shader!");
143 return shader;
144 }
145 glShaderSource(shader, 1, &tempSrc, nullptr);
146 glCompileShader(shader);
147 GLint status = GL_FALSE;
148 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
149 if (status == GL_FALSE) {
150 GLchar message[MESSAGE_MAX_SIZE + 1] = {0};
151 glGetShaderInfoLog(shader, MESSAGE_MAX_SIZE, nullptr, &message[0]);
152 MEDIA_LOGE("Load Shader Error: %{public}s", message);
153 glDeleteShader(shader);
154 shader = 0;
155 }
156 return shader;
157 }
158
CreateProgram(const std::string & vss,const std::string & fss)159 GLuint GLUtils::CreateProgram(const std::string& vss, const std::string& fss)
160 {
161 GLuint vs = LoadShader(vss, GL_VERTEX_SHADER);
162 GLuint fs = LoadShader(fss, GL_FRAGMENT_SHADER);
163 if (vs == 0 || fs == 0) {
164 return 0;
165 }
166 GLuint program = glCreateProgram();
167 if (program == 0) {
168 MEDIA_LOGE("Could Not Create Program!");
169 return program;
170 }
171 glAttachShader(program, vs);
172 glAttachShader(program, fs);
173 glLinkProgram(program);
174 GLint linkStatus = GL_FALSE;
175 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
176 if (linkStatus == GL_FALSE) {
177 GLchar message[MESSAGE_MAX_SIZE + 1] = {0};
178 glGetShaderInfoLog(program, MESSAGE_MAX_SIZE, nullptr, &message[0]);
179 MEDIA_LOGE("Create Program Error: %{public}s", message);
180 glDeleteProgram(program);
181 program = 0;
182 return program;
183 }
184 if (vs > 0) {
185 glDetachShader(program, vs);
186 glDeleteShader(vs);
187 }
188 if (vs > 0) {
189 glDetachShader(program, fs);
190 glDeleteShader(fs);
191 }
192 return program;
193 }
194
GetOesSamplingMatrix(Vec2 bufferWH,Vec2 displayWH,int32_t angle,bool flip)195 Mat4x4 GLUtils::GetOesSamplingMatrix(Vec2 bufferWH, Vec2 displayWH, int32_t angle, bool flip)
196 {
197 const float half = 0.5;
198 Mat4x4 result(1);
199 angle = angle / 90 * 90; // 默认旋转角度是90的整数倍
200 Vec2 dataWH = (angle == 90 || angle == 270) ? Vec2{ displayWH.y, displayWH.x } : displayWH;
201 Vec2 ratioWH = Vec2(dataWH.x / bufferWH.x, dataWH.y / bufferWH.y);
202 result = glm::translate(result, Vec3(half, half, 0.0));
203 result = glm::rotate(result, glm::radians(-(float)angle), Vec3(0.0, 0.0, 1.0));
204 result = glm::translate(result, Vec3(-half, -half, 0.0));
205 result[0][0] *= ratioWH.x;
206 result[1][1] *= ratioWH.y;
207 return result;
208 }
209
CheckError(const char * file,int32_t line)210 void GLUtils::CheckError(const char* file, int32_t line)
211 {
212 GLenum status = glGetError();
213 if (status != GL_NO_ERROR) {
214 MEDIA_LOGE("[Render] GL Error: 0x%{public}x [%{public}s:%{public}d]\n", status, file, line);
215 }
216 }
217
218 }
219 }