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