• 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 <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