• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "shader.h"
17 
18 #include <EGL/egl.h>
19 #include <GLES2/gl2.h>
20 #include <gslogger.h>
21 
22 namespace {
23 DEFINE_HILOG_LABEL("Shader");
24 } // namespace
25 
Shader(const std::string & vertexSource,const std::string & fragmentSource)26 Shader::Shader(const std::string& vertexSource, const std::string& fragmentSource)
27 {
28     rendererID_ = CreateShader(vertexSource, fragmentSource);
29 }
30 
~Shader()31 Shader::~Shader()
32 {
33     if (rendererID_ != 0) {
34         glDeleteProgram(rendererID_);
35     }
36 }
37 
Available()38 bool Shader::Available()
39 {
40     return rendererID_ != 0;
41 }
42 
Bind() const43 void Shader::Bind() const
44 {
45     glUseProgram(rendererID_);
46 }
47 
Unbind() const48 void Shader::Unbind() const
49 {
50     glUseProgram(0);
51 }
52 
SetUniform1i(const std::string & name,int32_t v)53 void Shader::SetUniform1i(const std::string& name, int32_t v)
54 {
55     glUniform1i(GetUniformLocation(name), v);
56 }
57 
SetUniform1f(const std::string & name,float v)58 void Shader::SetUniform1f(const std::string& name, float v)
59 {
60     glUniform1f(GetUniformLocation(name), v);
61 }
62 
SetUniform4f(const std::string & name,float v0,float v1,float v2,float v3)63 void Shader::SetUniform4f(const std::string& name, float v0, float v1, float v2, float v3)
64 {
65     glUniform4f(GetUniformLocation(name), v0, v1, v2, v3);
66 }
67 
SetUniformMat4f(const std::string & name,const Matrix<float> & matrix)68 void Shader::SetUniformMat4f(const std::string& name, const Matrix<float>& matrix)
69 {
70     glUniformMatrix4fv(GetUniformLocation(name), 1, GL_FALSE, matrix);
71 }
72 
GetAttribLocation(const std::string & name)73 int32_t Shader::GetAttribLocation(const std::string& name)
74 {
75     return glGetAttribLocation(rendererID_, name.c_str());
76 }
77 
GetUniformLocation(const std::string & name)78 int32_t Shader::GetUniformLocation(const std::string& name)
79 {
80     if (uniformLocationCache_.find(name) != uniformLocationCache_.end()) {
81         return uniformLocationCache_[name];
82     }
83     auto location = glGetUniformLocation(rendererID_, name.c_str());
84     if (location == -1) {
85         GSLOG2HI(WARN) << "Warning: uniform '" << name << "' doesn't exist!" << std::endl;
86     }
87 
88     uniformLocationCache_[name] = location;
89     return location;
90 }
91 
CompileShader(uint32_t type,const std::string & source)92 uint32_t Shader::CompileShader(uint32_t type, const std::string& source)
93 {
94     auto id = glCreateShader(type);
95     auto src = source.c_str();
96     glShaderSource(id, 1, &src, nullptr);
97     glCompileShader(id);
98 
99     auto result = GL_FALSE;
100     glGetShaderiv(id, GL_COMPILE_STATUS, &result);
101     if (result == GL_FALSE) {
102         int32_t length = 0;
103         glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
104         if (length < 0) {
105             GSLOG2HI(ERROR) << "CompileShader Failed length is not right";
106             return 0;
107         }
108         char* message = static_cast<char*>(malloc(length));
109         if (message == nullptr) {
110             GSLOG2HI(ERROR) << "CompileShader Failed malloc failed";
111             return 0;
112         }
113         glGetShaderInfoLog(id, length, &length, message);
114         GSLOG2HI(ERROR) << "CompileShader[" << type << "] Failed: " << message;
115         glDeleteShader(id);
116         free(message);
117         message = nullptr;
118         return 0;
119     }
120 
121     return id;
122 }
123 
CreateShader(const std::string & vertexShader,const std::string & fragmentShader)124 uint32_t Shader::CreateShader(const std::string& vertexShader, const std::string& fragmentShader)
125 {
126     auto program = glCreateProgram();
127     auto vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
128     auto fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
129 
130     glAttachShader(program, vs);
131     glAttachShader(program, fs);
132     glLinkProgram(program);
133     glDeleteShader(vs);
134     glDeleteShader(fs);
135 
136     auto result = GL_FALSE;
137     glGetProgramiv(program, GL_LINK_STATUS, &result);
138     if (result == GL_FALSE) {
139         int32_t length = 0;
140         glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
141         if (length < 0) {
142             GSLOG2HI(ERROR) << "CreateShader Failed length is not right";
143             return 0;
144         }
145         char* message = static_cast<char*>(malloc(length));
146         if (message == nullptr) {
147             GSLOG2HI(ERROR) << "CreateShader Failed malloc failed";
148             return 0;
149         }
150         glGetProgramInfoLog(program, length, nullptr, message);
151         GSLOG2HI(ERROR) << "program error[" << glGetError() << "]: " << message;
152         free(message);
153         message = nullptr;
154         return 0;
155     }
156 
157     GSLOG2HI(INFO) << "Shader create success " << program;
158     return program;
159 }
160