1 /*
2 * Copyright (C) 2023 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 "pixel_map_gl_shader.h"
17
18 #include <fstream>
19 #include <sstream>
20 #include <string>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <fcntl.h>
24
25 #undef LOG_DOMAIN
26 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
27
28 #undef LOG_TAG
29 #define LOG_TAG "Shader"
30 #define PI 3.1415926
31
32 namespace OHOS {
33 namespace Media {
34 namespace PixelMapGlShader {
35 using namespace GlCommon;
36 const int MAX_SLR_WIN_SIZE = 12;
37 std::string g_shaderPath = "/data/storage/el1/base/";
38 static int g_shaderVersion = 2;
39 const std::string &g_rotateFilePath = g_shaderPath + "pixelMapRotate.shader";
40 unsigned char *RotateShader::shaderBinary_ = nullptr;
41 GLenum RotateShader::binaryFormat_ = 0;
42 GLuint RotateShader::binarySize_ = 0;
43
44 const std::string &g_SlrFilePath = g_shaderPath + "pixelMapSlr.shader";
45 unsigned char *SLRShader::shaderBinary_ = nullptr;
46 GLenum SLRShader::binaryFormat_ = 0;
47 GLuint SLRShader::binarySize_ = 0;
48
49 const std::string &g_LapFilePath = g_shaderPath + "pixelMapLap.shader";
50 unsigned char *LapShader::shaderBinary_ = nullptr;
51 GLenum LapShader::binaryFormat_ = 0;
52 GLuint LapShader::binarySize_ = 0;
53
GeSLRFactor(float x,int a)54 float GeSLRFactor(float x, int a)
55 {
56 if (x >= a || x < -a) {
57 return 0.0f;
58 }
59 if (std::abs(x) < 1e-16) {
60 return 0.0f;
61 }
62 x *= PI;
63 if (std::abs(x * x) < 1e-6 || x * x == 0.0f ||
64 std::abs(a) < 1e-6 || a == 0.0f) {
65 return 0.0f;
66 }
67 return a * std::sin(x) * std::sin(x / a) / (x * x);
68 }
69
getWeights(float coeff,int n)70 static std::shared_ptr<float[]> getWeights(float coeff, int n)
71 {
72 if (std::abs(coeff) < 1e-6 || coeff == 0.0f) {
73 coeff = 1.0f;
74 }
75 float tao = 1.0f / coeff;
76 int a = std::max(2, static_cast<int>(std::floor(tao)));
77
78 int width = 2 * a;
79 width = std::min(width, MAX_SLR_WIN_SIZE);
80 std::shared_ptr<float[]> weights = std::make_shared<float>(n * MAX_SLR_WIN_SIZE);
81 for (auto i = 0; i < n; i++) {
82 if (std::abs(coeff) < 1e-6 || coeff == 0.0f) {
83 coeff = 1.0f;
84 }
85 float eta_i = (i + 0.5) / coeff - 0.5;
86 int eta_i_int = std::floor(eta_i);
87 float sum = 0;
88
89 int k = eta_i_int - a + 1;
90 for (auto j = 0; j < width; ++j) {
91 float f = GeSLRFactor(coeff * (eta_i - (k + j)), a);
92 weights[i * MAX_SLR_WIN_SIZE + j] = f;
93 sum += f;
94 }
95 for (auto j = 0; j < width; ++j) {
96 weights[i * MAX_SLR_WIN_SIZE + j] /= sum;
97 }
98 for (auto h = width; h < MAX_SLR_WIN_SIZE; ++h) {
99 weights[i * MAX_SLR_WIN_SIZE + h] = 0;
100 }
101 }
102 return weights;
103 }
104
checkProgram(GLuint & programId)105 static bool checkProgram(GLuint &programId)
106 {
107 GLint linked;
108 glGetProgramiv(programId, GL_LINK_STATUS, &linked);
109 if (!linked) {
110 GLint infoLen = 0;
111 glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLen);
112 if (infoLen > 0) {
113 char *infoLog = new char[infoLen];
114 if (infoLog == nullptr) {
115 return false;
116 }
117 glGetProgramInfoLog(programId, infoLen, NULL, infoLog);
118 IMAGE_LOGE("slr_gpu checkProgram faied info:%{public}s", infoLog);
119 delete[] infoLog;
120 }
121 IMAGE_LOGE("slr_gpu checkProgram %{public}s %{public}d %{public}x", __func__, __LINE__, glGetError());
122 return false;
123 }
124 return true;
125 }
126
loadShaderFromFile(unsigned char * & shaderBinary,GLenum & binaryFormat,GLuint & binarySize,const char * filePath,int version)127 static bool loadShaderFromFile(unsigned char*&shaderBinary, GLenum &binaryFormat, GLuint &binarySize,
128 const char* filePath, int version)
129 {
130 if (shaderBinary != nullptr) {
131 return true;
132 }
133
134 struct stat fileStat;
135 if (stat(filePath, &fileStat) != 0) {
136 IMAGE_LOGE("slr_gpu shader cache is not exist! error %{public}d", errno);
137 return false;
138 }
139
140 int binaryFd = open(filePath, O_RDONLY);
141 if (binaryFd <= 0) {
142 IMAGE_LOGE("slr_gpu shader cache open failed! error %{public}d", errno);
143 return false;
144 }
145
146 unsigned char *binaryData = new unsigned char[fileStat.st_size];
147 if (binaryData == nullptr) {
148 return false;
149 }
150 int readLen = read(binaryFd, binaryData, fileStat.st_size);
151 close(binaryFd);
152
153 if (readLen != fileStat.st_size) {
154 delete[] binaryData;
155 IMAGE_LOGE("slr_gpu shader cache read failed! error "
156 "%{public}d readnum %{public}d", errno, readLen);
157 return false;
158 }
159 binarySize = fileStat.st_size - sizeof(GLenum) - sizeof(version);
160 binaryFormat = *reinterpret_cast<int *>(binaryData + binarySize);
161 int oldVersion = *reinterpret_cast<int *>(binaryData + fileStat.st_size - sizeof(version));
162 if (oldVersion != version) {
163 IMAGE_LOGI("slr_gpu oldVersion != version:%{public}d binaryFormat:%{public}d "
164 "size:%{public}d oldVersion:%{public}d", version, binaryFormat, binarySize, oldVersion);
165 delete []binaryData;
166 return false;
167 }
168 shaderBinary = binaryData;
169 return true;
170 }
171
saveShaderToFile(unsigned char * & shaderBinary,GLenum & binaryFormat,GLuint & binarySize,const char * filePath,GLuint & programId)172 bool saveShaderToFile(unsigned char*&shaderBinary, GLenum &binaryFormat,
173 GLuint &binarySize, const char* filePath, GLuint &programId)
174 {
175 if (shaderBinary == nullptr) {
176 GLint size = 0;
177 glGetProgramiv(programId, GL_PROGRAM_BINARY_LENGTH, &size);
178 if (size <= 0) {
179 return false;
180 }
181 unsigned char *binary = new unsigned char[size];
182 if (binary == nullptr) {
183 return false;
184 }
185 glGetProgramBinary(programId, size, NULL, &binaryFormat, binary);
186 binarySize = size;
187 shaderBinary = binary;
188 }
189 if (shaderBinary == nullptr) {
190 IMAGE_LOGE("slr_gpu shaderBinary == nullptr saveShaderToFile failed");
191 return false;
192 }
193 if (std::filesystem::exists(filePath)) {
194 std::filesystem::remove(filePath);
195 }
196 int binaryFd = open(filePath, O_WRONLY | O_CREAT, 0666);
197 if (binaryFd <= 0) {
198 IMAGE_LOGE("slr_gpu shader cache open(write) failed! error %{public}d", errno);
199 return false;
200 }
201 write(binaryFd, shaderBinary, binarySize);
202 write(binaryFd, &binaryFormat, sizeof(GLenum));
203 write(binaryFd, &g_shaderVersion, sizeof(g_shaderVersion));
204 close(binaryFd);
205 return true;
206 }
207
Shader()208 Shader::Shader()
209 {
210 glGenFramebuffers(1, &writeFbo_);
211 }
212
213
~Shader()214 Shader::~Shader()
215 {
216 glDeleteFramebuffers(1, &writeFbo_);
217 }
218
Clear()219 bool Shader::Clear()
220 {
221 ImageTrace imageTrace("Shader::Clear");
222 glBindTexture(GL_TEXTURE_2D, 0);
223 if (programId_ != 0) {
224 glDeleteProgram(programId_);
225 }
226 glDeleteShader(vShader_);
227 glDeleteShader(fShader_);
228 if (readTexId_ != 0) {
229 glDeleteTextures(1, &readTexId_);
230 }
231 if (writeTexId_ != 0) {
232 glDeleteTextures(1, &writeTexId_);
233 }
234 GLenum err = glGetError();
235 if (err != GL_NO_ERROR) {
236 IMAGE_LOGE("slr_gpu Shader %{public}s failed gl error: %{public}x", __func__, err);
237 return false;
238 }
239 return true;
240 }
241
loadShader(GLenum type,const char * shaderSrc)242 GLuint Shader::loadShader(GLenum type, const char *shaderSrc)
243 {
244 ImageTrace imageTrace("Shader::loadShader");
245 GLuint shader = glCreateShader(type);
246 if (shader == 0) {
247 IMAGE_LOGE("slr_gpu %{public}s create shader failed (type:%{public}x)", __func__, shader);
248 return 0;
249 }
250 glShaderSource(shader, 1, &shaderSrc, NULL);
251 glCompileShader(shader);
252 GLint compiled;
253 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
254 if (!compiled) {
255 GLint infoLen = 0;
256 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
257 if (infoLen > 1) {
258 char *infoLog = new char[infoLen];
259 if (infoLog == nullptr) {
260 return false;
261 }
262 glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
263 IMAGE_LOGE("slr_gpu Shader::LoadShader failed. info:%{public}s\n", infoLog);
264
265 delete[] infoLog;
266 }
267 glDeleteShader(shader);
268 IMAGE_LOGE("slr_gpu %{public}s create shader failed (type:%{public}x)", __func__, shader);
269 return 0;
270 }
271 return shader;
272 }
273
buildFromSource()274 bool Shader::buildFromSource()
275 {
276 ImageTrace imageTrace("Shader::buildFromSource");
277 if (programId_ == 0) {
278 IMAGE_LOGE("slr_gpu Shader::buildFromSource glCreateProgram");
279 programId_ = glCreateProgram();
280 }
281 glAttachShader(programId_, vShader_);
282 glAttachShader(programId_, fShader_);
283 glLinkProgram(programId_);
284 GLint linked;
285 glGetProgramiv(programId_, GL_LINK_STATUS, &linked);
286 if (!linked) {
287 GLint infoLen = 0;
288 glGetProgramiv(programId_, GL_INFO_LOG_LENGTH, &infoLen);
289 if (infoLen > 1) {
290 char *infoLog = new char[infoLen];
291 if (infoLog == nullptr) {
292 return false;
293 }
294 glGetProgramInfoLog(programId_, infoLen, NULL, infoLog);
295 IMAGE_LOGE("Shader faied info:%{public}s", infoLog);
296 delete[] infoLog;
297 }
298 IMAGE_LOGE("Shader %{public}s %{public}d %{public}x", __func__, __LINE__, glGetError());
299 return false;
300 }
301 return true;
302 }
303
buildFromBinary(unsigned char * & shaderBinary,GLenum & binaryFormat,GLuint & binarySize)304 bool Shader::buildFromBinary(unsigned char*&shaderBinary, GLenum &binaryFormat, GLuint &binarySize)
305 {
306 ImageTrace imageTrace("Shader::buildFromBinary");
307 if (programId_ == 0) {
308 IMAGE_LOGE("slr_gpu BuildLapProgram programLapId_ err ");
309 return false;
310 }
311 if (shaderBinary == nullptr) {
312 IMAGE_LOGE("slr_gpu BuildLapProgram g_shaderBinary is nullptr");
313 return false;
314 } else {
315 glProgramBinary(programId_, binaryFormat, shaderBinary, binarySize);
316 }
317 GLint linked;
318 glGetProgramiv(programId_, GL_LINK_STATUS, &linked);
319 if (!linked) {
320 IMAGE_LOGE("slr_gpu buildFromBinary linked failed");
321 return false;
322 }
323 return true;
324 }
325
BuildWriteTexture()326 bool Shader::BuildWriteTexture()
327 {
328 ImageTrace imageTrace("Shader::BuildWriteTexture");
329
330 if (writeTexId_ != 0) {
331 glDeleteTextures(1, &writeTexId_);
332 }
333 glGenTextures(1, &writeTexId_);
334 glBindTexture(GL_TEXTURE_2D, writeTexId_);
335 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, targetSize_.width, targetSize_.height,
336 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
337
338 GLenum err = glGetError();
339 if (err != GL_NO_ERROR) {
340 IMAGE_LOGE("slr_gpu Shader %{public}s failed gl error: %{public}d %{public}x", __func__, __LINE__, err);
341 return false;
342 }
343 return true;
344 }
345
VertexShader()346 VertexShader::VertexShader()
347 {
348 ImageTrace imageTrace("VertexShader::VertexShader()");
349 type_ = SHADER_VERTEX;
350 glGenBuffers(1, &vbo_);
351 glBindBuffer(GL_ARRAY_BUFFER, vbo_);
352 }
~VertexShader()353 VertexShader::~VertexShader()
354 {
355 }
356
Clear()357 bool VertexShader::Clear()
358 {
359 glDeleteBuffers(1, &vbo_);
360 return true;
361 }
362
Build()363 bool VertexShader::Build()
364 {
365 ImageTrace imageTrace("VertexShader::Build");
366 GLfloat quadVertices[] = {
367 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
368 -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
369 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
370 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
371 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
372 1.0f, 1.0f, 0.0f, 1.0f, 1.0f
373 };
374 glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
375 glEnableVertexAttribArray(0);
376 glVertexAttribPointer(0, NUM_3, GL_FLOAT, GL_FALSE, NUM_5 * sizeof(GLfloat), (GLvoid *)0);
377 glEnableVertexAttribArray(1);
378 glVertexAttribPointer(1, NUM_2, GL_FLOAT, GL_FALSE,
379 NUM_5 * sizeof(GLfloat), (GLvoid *)(NUM_3 * sizeof(GLfloat)));
380
381 GLenum err = glGetError();
382 if (err != GL_NO_ERROR) {
383 IMAGE_LOGE("slr_gpu VertexShader %{public}s failed gl error: %{public}x", __func__, err);
384 return false;
385 }
386 return true;
387 }
388
LoadProgram()389 bool VertexShader::LoadProgram()
390 {
391 return Build();
392 }
393
RotateShader()394 RotateShader::RotateShader()
395 {
396 type_ = SHADER_ROTATE;
397 }
398
~RotateShader()399 RotateShader::~RotateShader()
400 {
401 }
402
Clear()403 bool RotateShader::Clear()
404 {
405 return Shader::Clear();
406 }
407
Build()408 bool RotateShader::Build()
409 {
410 ImageTrace imageTrace("RotateShader::Build");
411 static const char vShaderStr[] =
412 "#version 320 es\n"
413 "layout (location = 0) in vec3 position;\n"
414 "layout (location = 1) in vec2 texCoords;\n"
415 "uniform mat4 transform;\n"
416 "uniform vec2 texClipRatio;\n"
417 "out vec2 vTexCoords;\n"
418 "void main()\n"
419 "{\n"
420 " gl_Position = transform * vec4(position.x, position.y, position.z, 1.0f);\n"
421 " vTexCoords = texCoords * texClipRatio + 0.5 * (vec2(1.0, 1.0) - texClipRatio);\n"
422 "}\n";
423 static const char fShaderStr[] =
424 "#version 320 es\n"
425 "#extension GL_OES_EGL_image_external_essl3 : require\n"
426 "precision mediump float;\n"
427 "in vec2 vTexCoords;\n"
428 "layout (binding = 0) uniform samplerExternalOES nativeTexture;\n"
429 "layout (binding = 1) uniform sampler2D normalTexture;\n"
430 "uniform int useNative;\n"
431 "out vec4 vFragColor;\n"
432 "void main()\n"
433 "{\n"
434 " if (useNative == 1) {\n"
435 " vFragColor = texture(nativeTexture, vTexCoords);\n"
436 " } else {\n"
437 " vFragColor = texture(normalTexture, vTexCoords);\n"
438 " }\n"
439 "}\n";
440 vShader_ = loadShader(GL_VERTEX_SHADER, vShaderStr);
441 fShader_ = loadShader(GL_FRAGMENT_SHADER, fShaderStr);
442 if (vShader_ == 0 || fShader_ == 0) {
443 IMAGE_LOGE("slr_gpu RotateShader LoadShader failed");
444 return false;
445 }
446 if (!buildFromSource()) {
447 return false;
448 }
449 transformLoc_ = glGetUniformLocation(programId_, "transform");
450 texClipRatioLoc_ = glGetUniformLocation(programId_, "texClipRatio");
451 useNativeLoc_ = glGetUniformLocation(programId_, "useNative");
452 GLenum err = glGetError();
453 if (err != GL_NO_ERROR) {
454 IMAGE_LOGE("slr_gpu RotateShader %{public}s failed gl error: %{public}x", __func__, err);
455 return false;
456 }
457 return true;
458 }
459
LoadProgram()460 bool RotateShader::LoadProgram()
461 {
462 ImageTrace imageTrace("RotateShader::LoadProgram");
463 if (programId_ == 0) {
464 programId_ = glCreateProgram();
465 }
466 if (loadShaderFromFile(shaderBinary_, binaryFormat_, binarySize_, g_rotateFilePath.c_str(), g_shaderVersion) &&
467 buildFromBinary(shaderBinary_, binaryFormat_, binarySize_)) {
468 transformLoc_ = glGetUniformLocation(programId_, "transform");
469 texClipRatioLoc_ = glGetUniformLocation(programId_, "texClipRatio");
470 useNativeLoc_ = glGetUniformLocation(programId_, "useNative");
471 if (!checkProgram(programId_)) {
472 return false;
473 }
474 return true;
475 }
476 if (!Build()) {
477 IMAGE_LOGE("slr_gpu RotateShader::LoadProgram Build failed");
478 return false;
479 }
480 if (!saveShaderToFile(shaderBinary_, binaryFormat_, binarySize_,
481 g_rotateFilePath.c_str(), programId_)) {
482 IMAGE_LOGE("slr_gpu RotateShader saveShaderToFile failed");
483 return false;
484 }
485 GLenum err = glGetError();
486 if (err != GL_NO_ERROR) {
487 IMAGE_LOGE("slr_gpu RotateShader %{public}s failed gl error: %{public}x", __func__, err);
488 return false;
489 }
490 return true;
491 }
492
Use()493 bool RotateShader::Use()
494 {
495 ImageTrace imageTrace("RotateShader::Use");
496 if (!Shader::BuildWriteTexture()) {
497 return false;
498 }
499 if (!checkProgram(programId_)) {
500 return false;
501 }
502 glUseProgram(programId_);
503 glBindFramebuffer(GL_FRAMEBUFFER, writeFbo_);
504 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, writeTexId_, 0); //绑定
505 glClearColor(0, 1, 0, 0);
506 glClear(GL_COLOR_BUFFER_BIT);
507 uint32_t calculationTargetHeight = rotateDegreeZ_ !=0 ? targetSize_.width : targetSize_.height;
508 uint32_t calculationTargetWidth = rotateDegreeZ_ !=0 ? targetSize_.height : targetSize_.width;
509 float clipRatioX = sourceSize_.width > sourceSize_.height ?
510 (sourceSize_.height * 1.0f / calculationTargetHeight) * calculationTargetWidth / sourceSize_.width : 1;
511 float clipRatioY = sourceSize_.height > sourceSize_.width ?
512 (sourceSize_.width * 1.0f / calculationTargetWidth) * calculationTargetHeight / sourceSize_.height : 1;
513 glUniform2f(texClipRatioLoc_, clipRatioX, clipRatioY);
514 if (eglImage_ != EGL_NO_IMAGE) {
515 glUniform1i(useNativeLoc_, 1);
516 glActiveTexture(GL_TEXTURE0);
517 glBindTexture(GL_TEXTURE_EXTERNAL_OES, readTexId_);
518 } else {
519 glUniform1i(useNativeLoc_, 0);
520 glBindTexture(GL_TEXTURE_2D, 0);
521 glActiveTexture(GL_TEXTURE1);
522 glBindTexture(GL_TEXTURE_2D, readTexId_);
523 }
524 glViewport(0, 0, targetSize_.width, targetSize_.height);
525 glUniformMatrix4fv(transformLoc_, 1, GL_FALSE, rotateTrans_.GetDataPtr());
526 glDrawArrays(GL_TRIANGLES, 0, NUM_6);
527 glFlush();
528 GLenum err = glGetError();
529 if (err != GL_NO_ERROR) {
530 IMAGE_LOGE("slr_gpu RotateShader %{public}s failed gl error: %{public}x", __func__, err);
531 return false;
532 }
533 return true;
534 }
535
SLRShader()536 SLRShader::SLRShader()
537 {
538 type_ = SHADER_SLR;
539 }
540
~SLRShader()541 SLRShader::~SLRShader()
542 {
543 }
544
Clear()545 bool SLRShader::Clear()
546 {
547 if (texture_[0] != 0) {
548 glDeleteTextures(1, &texture_[0]);
549 }
550 if (texture_[1] != 0) {
551 glDeleteTextures(1, &texture_[1]);
552 }
553 return Shader::Clear();
554 }
555
Build()556 bool SLRShader::Build()
557 {
558 static const char vSlrShaderStr[] =
559 "#version 320 es\n"
560 "layout (location = 0) in vec3 position;\n"
561 "layout (location = 1) in vec2 texCoords;\n"
562 "uniform mat4 transform;\n"
563 "uniform vec2 texClipRatio;\n"
564 "out vec2 vTexCoords;\n"
565 "void main()\n"
566 "{\n"
567 " gl_Position = vec4(position.x, position.y, position.z, 1.0f);\n"
568 " vTexCoords = texCoords;\n"
569 "}\n";
570 static const char fSlrShaderStr[] = R"(#version 320 es
571 precision mediump float;
572 in vec2 vTexCoords;
573 layout (binding = 1) uniform sampler2D utexture;
574 layout (binding = 2) uniform sampler2D utexturew;
575 layout (binding = 3) uniform sampler2D utextureh;
576 uniform ivec2 srcSize;
577 uniform ivec2 dstSize;
578 uniform ivec2 slr_a;
579 uniform ivec2 slr_max;
580 uniform vec2 slr_coeff;
581 uniform vec2 slr_coeff_tao;
582 out vec4 FragColor;
583 void main()
584 {
585 vec2 eta = (gl_FragCoord.xy + vec2(0.5)) * slr_coeff_tao - vec2(0.5);
586 ivec2 eta_c = ivec2(floor(eta.x), floor(eta.y));
587 ivec2 coord_s = ivec2(eta_c.x - slr_a.x + 1, eta_c.y - slr_a.y + 1);
588 vec4 color = vec4(0, 0, 0, 0);
589 for (int i = 0; i < slr_max.y; i++) {
590 float w_i = texelFetch(utextureh, ivec2(i, gl_FragCoord.y), 0).r;
591 vec4 t = vec4(0, 0, 0, 0);
592 for (int j = 0; j < slr_max.x; j++) {
593 float w_j = texelFetch(utexturew, ivec2(j, gl_FragCoord.x), 0).r;
594 t += w_j * texelFetch(utexture, coord_s + ivec2(j, i), 0);
595 }
596 color += t * w_i;
597 }
598 FragColor = color;
599 }
600 )";
601 ImageTrace imageTrace("SLRShader::Build");
602 vShader_ = loadShader(GL_VERTEX_SHADER, vSlrShaderStr);
603 fShader_ = loadShader(GL_FRAGMENT_SHADER, fSlrShaderStr);
604 if (vShader_ == 0 || fShader_ == 0) {
605 IMAGE_LOGE("slr_gpu SLRShader LoadShader failed");
606 return false;
607 }
608 if (!buildFromSource()) {
609 IMAGE_LOGE("slr_gpu SLRShader LoadShader failed");
610 return false;
611 }
612 utexture_ = glGetUniformLocation(programId_, "utexture");
613 utexturew_ = glGetUniformLocation(programId_, "utexturew");
614 utextureh_ = glGetUniformLocation(programId_, "utextureh");
615 slrA_ = glGetUniformLocation(programId_, "slr_a");
616 slrAMax_ = glGetUniformLocation(programId_, "slr_max");
617 slrCoeff_ = glGetUniformLocation(programId_, "slr_coeff");
618 slrCoeffTao_ = glGetUniformLocation(programId_, "slr_coeff_tao");
619 GLenum err = glGetError();
620 if (err != GL_NO_ERROR) {
621 IMAGE_LOGE("slr_gpu SLRShader %{public}s failed gl error: %{public}x", __func__, err);
622 return false;
623 }
624 return true;
625 }
626
LoadProgram()627 bool SLRShader::LoadProgram()
628 {
629 ImageTrace imageTrace("SLRShader::LoadProgram");
630 if (programId_ == 0) {
631 programId_ = glCreateProgram();
632 }
633 if (loadShaderFromFile(shaderBinary_, binaryFormat_, binarySize_, g_SlrFilePath.c_str(), g_shaderVersion) &&
634 buildFromBinary(shaderBinary_, binaryFormat_, binarySize_)) {
635 utexture_ = glGetUniformLocation(programId_, "utexture");
636 utexturew_ = glGetUniformLocation(programId_, "utexturew");
637 utextureh_ = glGetUniformLocation(programId_, "utextureh");
638 slrA_ = glGetUniformLocation(programId_, "slr_a");
639 slrAMax_ = glGetUniformLocation(programId_, "slr_max");
640 slrCoeff_ = glGetUniformLocation(programId_, "slr_coeff");
641 slrCoeffTao_ = glGetUniformLocation(programId_, "slr_coeff_tao");
642 return true;
643 }
644
645 if (!Build()) {
646 IMAGE_LOGE("slr_gpu SLRShader::LoadProgram Build failed");
647 return false;
648 }
649
650 if (!saveShaderToFile(shaderBinary_, binaryFormat_, binarySize_,
651 g_SlrFilePath.c_str(), programId_)) {
652 IMAGE_LOGE("slr_gpu SLRShader saveShaderToFile failed");
653 return false;
654 }
655
656 GLenum err = glGetError();
657 if (err != GL_NO_ERROR) {
658 IMAGE_LOGE("slr_gpu SLRShader %{public}s failed gl error: %{public}x", __func__, err);
659 return false;
660 }
661 return true;
662 }
663
SetParams(GPUTransformData transformData)664 bool SLRShader::SetParams(GPUTransformData transformData)
665 {
666 if (texture_[0] == 0U) {
667 glGenTextures(NUM_2, texture_);
668 }
669 return Shader::SetParams(transformData);
670 }
671
Use()672 bool SLRShader::Use()
673 {
674 ImageTrace imageTrace("SLRShader::Use");
675 if (!Shader::BuildWriteTexture()) {
676 return false;
677 }
678 glUseProgram(programId_);
679 glBindFramebuffer(GL_FRAMEBUFFER, writeFbo_);
680 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, writeTexId_, 0);
681 glClearColor(0, 1, 0, 0);
682 glClear(GL_COLOR_BUFFER_BIT);
683 int texture_index = 0;
684 if (eglImage_ != EGL_NO_IMAGE) {
685 glActiveTexture(GL_TEXTURE0);
686 glBindTexture(GL_TEXTURE_EXTERNAL_OES, readTexId_);
687 } else {
688 glBindTexture(GL_TEXTURE_2D, 0);
689 glActiveTexture(GL_TEXTURE1);
690 glBindTexture(GL_TEXTURE_2D, readTexId_);
691 texture_index = 1;
692 }
693 float coeff_w = ((float)targetSize_.width) / sourceSize_.width;
694 float coeff_h = ((float)targetSize_.height) / sourceSize_.height;
695 float tao_w = 1.0f / coeff_w;
696 int a_w = std::clamp(int(std::floor(tao_w)), 2, MAX_SLR_WIN_SIZE / 2);
697 float tao_h = 1.0f / coeff_h;
698 int a_h = std::clamp(int(std::floor(tao_h)), 2, MAX_SLR_WIN_SIZE / 2);
699 auto h_x2 = getWeights(coeff_w, targetSize_.width);
700 glActiveTexture(GL_TEXTURE2);
701 glBindTexture(GL_TEXTURE_2D, texture_[0]);
702 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, MAX_SLR_WIN_SIZE, targetSize_.width, 0, GL_RED, GL_FLOAT, h_x2.get());
703 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
704 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
705 auto h_y2 = getWeights(coeff_h, targetSize_.height);
706 glActiveTexture(GL_TEXTURE3);
707 glBindTexture(GL_TEXTURE_2D, texture_[1]);
708 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, MAX_SLR_WIN_SIZE, targetSize_.height, 0, GL_RED, GL_FLOAT, h_y2.get());
709 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
710 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
711 glUniform2i(slrA_, a_w, a_h);
712 glUniform2i(slrAMax_, a_w * NUM_2, a_h * NUM_2);
713 glUniform2f(slrCoeff_, coeff_w, coeff_h);
714 glUniform2f(slrCoeffTao_, tao_w, tao_h);
715 glViewport(0, 0, targetSize_.width, targetSize_.height);
716 glDrawArrays(GL_TRIANGLES, 0, NUM_6);
717 glFlush();
718 GLenum err = glGetError();
719 if (err != GL_NO_ERROR) {
720 IMAGE_LOGE("slr_gpu SLRShader %{public}s failed gl error: %{public}x", __func__, err);
721 return false;
722 }
723 return true;
724 }
725
LapShader()726 LapShader::LapShader()
727 {
728 type_ = SHADER_LAP;
729 }
730
~LapShader()731 LapShader::~LapShader()
732 {
733 }
734
Clear()735 bool LapShader::Clear()
736 {
737 return Shader::Clear();
738 }
739
Build()740 bool LapShader::Build()
741 {
742 ImageTrace imageTrace("LapShader::Build");
743 static const char vShaderStr[] =
744 "#version 320 es\n"
745 "layout (location = 0) in vec3 position;\n"
746 "layout (location = 1) in vec2 texCoords;\n"
747 "out vec2 vTexCoords;\n"
748 "void main()\n"
749 "{\n"
750 " gl_Position = vec4(position.x, position.y, position.z, 1.0f);\n"
751 " vTexCoords = texCoords;\n"
752 "}\n";
753
754 static const char fShaderStr[] = R"(#version 320 es
755 precision mediump float;
756 in vec2 vTexCoords;
757 uniform sampler2D utexture;
758 uniform float alpha;
759 out vec4 FragColor;
760 void main()
761 {
762 vec2 screenSize = vec2(textureSize(utexture, 0));
763 vec2 uv = gl_FragCoord.xy / screenSize.xy, ps = 1. / screenSize.xy; // pixel size
764 vec4 c = texture(utexture, uv);
765 vec4 top = texture(utexture, uv + vec2(0.0, ps.y));
766 vec4 bottom = texture(utexture, uv - vec2(0.0, ps.y));
767 vec4 left = texture(utexture, uv - vec2(ps.x, 0.0));
768 vec4 right = texture(utexture, uv + vec2(ps.x, 0.0));
769 FragColor = c + alpha* (4.0 * c - top - bottom - left - right);
770 }
771 )";
772
773 vShader_ = loadShader(GL_VERTEX_SHADER, vShaderStr);
774 fShader_ = loadShader(GL_FRAGMENT_SHADER, fShaderStr);
775 if (vShader_ == 0 || fShader_ == 0) {
776 IMAGE_LOGE("slr_gpu LapShader LoadShader failed");
777 return false;
778 }
779 if (!buildFromSource()) {
780 IMAGE_LOGE("slr_gpu LapShader LoadShader failed");
781 return false;
782 }
783 utexture_ = glGetUniformLocation(programId_, "utexture");
784 alpha_ = glGetUniformLocation(programId_, "alpha");
785 GLenum err = glGetError();
786 if (err != GL_NO_ERROR) {
787 IMAGE_LOGE("slr_gpu LapShader %{public}s failed gl error: %{public}x", __func__, err);
788 return false;
789 }
790 return true;
791 }
792
LoadProgram()793 bool LapShader::LoadProgram()
794 {
795 ImageTrace imageTrace("LapShader::LoadProgram");
796 if (programId_ == 0) {
797 programId_ = glCreateProgram();
798 }
799 if (loadShaderFromFile(shaderBinary_, binaryFormat_, binarySize_, g_LapFilePath.c_str(), g_shaderVersion) &&
800 buildFromBinary(shaderBinary_, binaryFormat_, binarySize_)) {
801 utexture_ = glGetUniformLocation(programId_, "utexture");
802 alpha_ = glGetUniformLocation(programId_, "alpha");
803 return true;
804 }
805 if (!Build()) {
806 IMAGE_LOGE("slr_gpu LapShader::LoadProgram Build failed");
807 return false;
808 }
809 if (!saveShaderToFile(shaderBinary_, binaryFormat_, binarySize_,
810 g_LapFilePath.c_str(), programId_)) {
811 IMAGE_LOGE("slr_gpu LapShader saveShaderToFile failed");
812 return false;
813 }
814 GLenum err = glGetError();
815 if (err != GL_NO_ERROR) {
816 IMAGE_LOGE("slr_gpu LapShader %{public}s failed gl error: %{public}x", __func__, err);
817 return false;
818 }
819 return true;
820 }
821
SetParams(GPUTransformData transformData)822 bool LapShader::SetParams(GPUTransformData transformData)
823 {
824 float coeff = ((float)targetSize_.width) / sourceSize_.width;
825 if (coeff > 0.8f) {
826 param_ = 0;
827 } else if (coeff > 0.6f) {
828 param_ = 0.06f;
829 } else if (coeff > 0.5f) {
830 param_ = 0.1f;
831 } else {
832 param_ = 0.15f;
833 }
834 return Shader::SetParams(transformData);
835 }
836
Use()837 bool LapShader::Use()
838 {
839 ImageTrace imageTrace("LapShader::Use");
840 if (!Shader::BuildWriteTexture()) {
841 return false;
842 }
843 glUseProgram(programId_);
844 glBindFramebuffer(GL_FRAMEBUFFER, writeFbo_);
845 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, writeTexId_, 0);
846 glClearColor(0, 0, 0, 0);
847 glClear(GL_COLOR_BUFFER_BIT);
848
849 glActiveTexture(GL_TEXTURE0);
850 glBindTexture(GL_TEXTURE_2D, readTexId_);
851 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
852 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
853 glUniform1f(alpha_, param_);
854 glViewport(0, 0, targetSize_.width, targetSize_.height);
855 glDrawArrays(GL_TRIANGLES, 0, NUM_6);
856 glFlush();
857 GLenum err = glGetError();
858 if (err != GL_NO_ERROR) {
859 IMAGE_LOGE("slr_gpu LapShader %{public}s failed gl error: %{public}x", __func__, err);
860 return false;
861 }
862 return true;
863 }
864 }
865 } // namespace Media
866 } // namespace OHOS
867