• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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