1#include "opengl_sl_program.h"
2
3#include "opengl_sl.h"
4
5#include <base/detect.h>
6#include <base/log.h>
7
8#include <string>
9
10#if defined(BACKEND_AS_OPENGL_ES) || !defined(CONF_BACKEND_OPENGL_ES)
11
12#ifndef BACKEND_AS_OPENGL_ES
13#include <GL/glew.h>
14#else
15#include <GLES3/gl3.h>
16#endif
17
18void CGLSLProgram::CreateProgram()
19{
20 m_ProgramId = glCreateProgram();
21}
22
23void CGLSLProgram::DeleteProgram()
24{
25 if(!m_IsLinked)
26 return;
27 m_IsLinked = false;
28 glDeleteProgram(m_ProgramId);
29}
30
31bool CGLSLProgram::AddShader(CGLSL *pShader) const
32{
33 if(pShader->IsLoaded())
34 {
35 glAttachShader(m_ProgramId, pShader->GetShaderId());
36 return true;
37 }
38 return false;
39}
40
41void CGLSLProgram::DetachShader(CGLSL *pShader) const
42{
43 if(pShader->IsLoaded())
44 {
45 DetachShaderById(ShaderId: pShader->GetShaderId());
46 }
47}
48
49void CGLSLProgram::DetachShaderById(TWGLuint ShaderId) const
50{
51 glDetachShader(m_ProgramId, ShaderId);
52}
53
54bool CGLSLProgram::LinkProgram()
55{
56 glLinkProgram(m_ProgramId);
57 TWGLint LinkStatus;
58 glGetProgramiv(m_ProgramId, GL_LINK_STATUS, &LinkStatus);
59 m_IsLinked = LinkStatus == GL_TRUE;
60 if(!m_IsLinked)
61 {
62 TWGLint LogLength = 0;
63 glGetProgramiv(m_ProgramId, GL_INFO_LOG_LENGTH, &LogLength);
64 if(LogLength > 0)
65 {
66 std::string Log(LogLength, '\0');
67 glGetProgramInfoLog(m_ProgramId, Log.size(), nullptr, &Log.front());
68 if(Log[Log.size() - 2] == '\n')
69 {
70 Log[Log.size() - 2] = '\0';
71 }
72 log_error("gfx/opengl/shader", "Failed to link shader program '%d'. The linker returned:\n%s", m_ProgramId, Log.c_str());
73 }
74 else
75 {
76 log_error("gfx/opengl/shader", "Failed to link shader program '%d'. The linker did not return an error.", m_ProgramId);
77 }
78 }
79
80 DetachAllShaders();
81 return m_IsLinked;
82}
83
84void CGLSLProgram::DetachAllShaders() const
85{
86 TWGLuint aShaders[100];
87 GLsizei ReturnedCount = 0;
88 while(true)
89 {
90 glGetAttachedShaders(m_ProgramId, 100, &ReturnedCount, aShaders);
91
92 if(ReturnedCount > 0)
93 {
94 for(GLsizei i = 0; i < ReturnedCount; ++i)
95 {
96 DetachShaderById(ShaderId: aShaders[i]);
97 }
98 }
99
100 if(ReturnedCount < 100)
101 break;
102 }
103}
104
105void CGLSLProgram::SetUniformVec4(int Loc, int Count, const float *pValues)
106{
107 glUniform4fv(Loc, Count, pValues);
108}
109
110void CGLSLProgram::SetUniformVec2(int Loc, int Count, const float *pValues)
111{
112 glUniform2fv(Loc, Count, pValues);
113}
114
115void CGLSLProgram::SetUniform(int Loc, int Count, const float *pValues)
116{
117 glUniform1fv(Loc, Count, pValues);
118}
119
120void CGLSLProgram::SetUniform(int Loc, const int Value)
121{
122 glUniform1i(Loc, Value);
123}
124
125void CGLSLProgram::SetUniform(int Loc, const float Value)
126{
127 glUniform1f(Loc, Value);
128}
129
130void CGLSLProgram::SetUniform(int Loc, const bool Value)
131{
132 glUniform1i(Loc, (int)Value);
133}
134
135int CGLSLProgram::GetUniformLoc(const char *pName) const
136{
137 return glGetUniformLocation(m_ProgramId, pName);
138}
139
140void CGLSLProgram::UseProgram() const
141{
142 if(m_IsLinked)
143 glUseProgram(m_ProgramId);
144}
145
146TWGLuint CGLSLProgram::GetProgramId() const
147{
148 return m_ProgramId;
149}
150
151CGLSLProgram::CGLSLProgram()
152{
153 m_IsLinked = false;
154}
155
156CGLSLProgram::~CGLSLProgram()
157{
158 DeleteProgram();
159}
160
161#endif
162