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