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