2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
11 #include "ServiceBroker.h"
12 #include "filesystem/File.h"
13 #include "rendering/RenderSystem.h"
14 #include "utils/GLUtils.h"
15 #include "utils/StringUtils.h"
16 #include "utils/log.h"
24 using namespace Shaders
;
25 using namespace XFILE
;
27 //////////////////////////////////////////////////////////////////////
29 //////////////////////////////////////////////////////////////////////
30 bool CShader::LoadSource(const std::string
& filename
, const std::string
& prefix
)
37 std::string path
= "special://xbmc/system/shaders/";
38 path
+= CServiceBroker::GetRenderSystem()->GetShaderPath(filename
);
42 CLog::Log(LOGERROR
, "CYUVShaderGLSL::CYUVShaderGLSL - failed to open file {}", filename
);
45 getline(file
, m_source
, '\0');
48 size_t versionPos
= m_source
.find("#version");
49 if (versionPos
!= std::string::npos
)
51 versionPos
= m_source
.find('\n', versionPos
);
52 if (versionPos
!= std::string::npos
)
55 m_source
.insert(pos
, prefix
);
57 m_filenames
= filename
;
62 bool CShader::AppendSource(const std::string
& filename
)
70 std::string path
= "special://xbmc/system/shaders/";
71 path
+= CServiceBroker::GetRenderSystem()->GetShaderPath(filename
);
75 CLog::Log(LOGERROR
, "CShader::AppendSource - failed to open file {}", filename
);
78 getline(file
, temp
, '\0');
79 m_source
.append(temp
);
81 m_filenames
.append(" " + filename
);
86 bool CShader::InsertSource(const std::string
& filename
, const std::string
& loc
)
94 std::string path
= "special://xbmc/system/shaders/";
95 path
+= CServiceBroker::GetRenderSystem()->GetShaderPath(filename
);
99 CLog::Log(LOGERROR
, "CShader::InsertSource - failed to open file {}", filename
);
102 getline(file
, temp
, '\0');
104 size_t locPos
= m_source
.find(loc
);
105 if (locPos
== std::string::npos
)
107 CLog::Log(LOGERROR
, "CShader::InsertSource - could not find location {}", loc
);
111 m_source
.insert(locPos
, temp
);
113 m_filenames
.append(" " + filename
);
118 std::string
CShader::GetSourceWithLineNumbers() const
121 auto lines
= StringUtils::Split(m_source
, "\n");
122 for (auto& line
: lines
)
124 line
.insert(0, StringUtils::Format("{:3}: ", i
));
128 auto output
= StringUtils::Join(lines
, "\n");
134 //////////////////////////////////////////////////////////////////////
136 //////////////////////////////////////////////////////////////////////
138 bool CGLSLVertexShader::Compile()
144 m_vertexShader
= glCreateShader(GL_VERTEX_SHADER
);
145 const char *ptr
= m_source
.c_str();
146 glShaderSource(m_vertexShader
, 1, &ptr
, 0);
147 glCompileShader(m_vertexShader
);
148 glGetShaderiv(m_vertexShader
, GL_COMPILE_STATUS
, params
);
150 if (params
[0] != GL_TRUE
)
152 GLchar log
[LOG_SIZE
];
153 CLog::Log(LOGERROR
, "GL: Error compiling vertex shader");
154 glGetShaderInfoLog(m_vertexShader
, LOG_SIZE
, NULL
, log
);
155 CLog::Log(LOGERROR
, "{}", log
);
161 GLchar log
[LOG_SIZE
];
163 glGetShaderInfoLog(m_vertexShader
, LOG_SIZE
, &length
, log
);
166 CLog::Log(LOGDEBUG
, "GL: Vertex Shader compilation log:");
167 CLog::Log(LOGDEBUG
, "{}", log
);
175 void CGLSLVertexShader::Free()
178 glDeleteShader(m_vertexShader
);
182 //////////////////////////////////////////////////////////////////////
184 //////////////////////////////////////////////////////////////////////
185 bool CGLSLPixelShader::Compile()
191 // Pixel shaders are not mandatory.
192 if (m_source
.length()==0)
194 CLog::Log(LOGINFO
, "GL: No pixel shader, fixed pipeline in use");
198 m_pixelShader
= glCreateShader(GL_FRAGMENT_SHADER
);
199 const char *ptr
= m_source
.c_str();
200 glShaderSource(m_pixelShader
, 1, &ptr
, 0);
201 glCompileShader(m_pixelShader
);
202 glGetShaderiv(m_pixelShader
, GL_COMPILE_STATUS
, params
);
203 if (params
[0] != GL_TRUE
)
205 GLchar log
[LOG_SIZE
];
206 CLog::Log(LOGERROR
, "GL: Error compiling pixel shader");
207 glGetShaderInfoLog(m_pixelShader
, LOG_SIZE
, NULL
, log
);
208 CLog::Log(LOGERROR
, "{}", log
);
214 GLchar log
[LOG_SIZE
];
216 glGetShaderInfoLog(m_pixelShader
, LOG_SIZE
, &length
, log
);
219 CLog::Log(LOGDEBUG
, "GL: Pixel Shader compilation log:");
220 CLog::Log(LOGDEBUG
, "{}", log
);
228 void CGLSLPixelShader::Free()
231 glDeleteShader(m_pixelShader
);
235 //////////////////////////////////////////////////////////////////////
236 // CGLSLShaderProgram
237 //////////////////////////////////////////////////////////////////////
238 CGLSLShaderProgram::CGLSLShaderProgram()
240 m_pFP
= new CGLSLPixelShader();
241 m_pVP
= new CGLSLVertexShader();
244 CGLSLShaderProgram::CGLSLShaderProgram(const std::string
& vert
,
245 const std::string
& frag
)
247 m_pFP
= new CGLSLPixelShader();
248 m_pFP
->LoadSource(frag
);
249 m_pVP
= new CGLSLVertexShader();
250 m_pVP
->LoadSource(vert
);
253 CGLSLShaderProgram::~CGLSLShaderProgram()
258 void CGLSLShaderProgram::Free()
266 glDeleteProgram(m_shaderProgram
);
273 bool CGLSLShaderProgram::CompileAndLink()
280 // compiled vertex shader
281 if (!m_pVP
->Compile())
283 CLog::Log(LOGERROR
, "GL: Error compiling vertex shader: {}", m_pVP
->GetName());
284 CLog::Log(LOGDEBUG
, "GL: vertex shader source:\n{}", m_pVP
->GetSourceWithLineNumbers());
288 // compile pixel shader
289 if (!m_pFP
->Compile())
292 CLog::Log(LOGERROR
, "GL: Error compiling fragment shader: {}", m_pFP
->GetName());
293 CLog::Log(LOGDEBUG
, "GL: fragment shader source:\n{}", m_pFP
->GetSourceWithLineNumbers());
297 // create program object
298 if (!(m_shaderProgram
= glCreateProgram()))
300 CLog::Log(LOGERROR
, "GL: Error creating shader program handle");
304 // attach the vertex shader
305 glAttachShader(m_shaderProgram
, m_pVP
->Handle());
308 // if we have a pixel shader, attach it. If not, fixed pipeline
312 glAttachShader(m_shaderProgram
, m_pFP
->Handle());
317 glLinkProgram(m_shaderProgram
);
318 glGetProgramiv(m_shaderProgram
, GL_LINK_STATUS
, params
);
319 if (params
[0]!=GL_TRUE
)
321 GLchar log
[LOG_SIZE
];
322 CLog::Log(LOGERROR
, "GL: Error linking shader");
323 glGetProgramInfoLog(m_shaderProgram
, LOG_SIZE
, NULL
, log
);
324 CLog::Log(LOGERROR
, "{}", log
);
331 OnCompiledAndLinked();
341 bool CGLSLShaderProgram::Enable()
345 glUseProgram(m_shaderProgram
);
350 // validate the program
352 glValidateProgram(m_shaderProgram
);
353 glGetProgramiv(m_shaderProgram
, GL_VALIDATE_STATUS
, params
);
354 if (params
[0]!=GL_TRUE
)
356 GLchar log
[LOG_SIZE
];
357 CLog::Log(LOGERROR
, "GL: Error validating shader");
358 glGetProgramInfoLog(m_shaderProgram
, LOG_SIZE
, NULL
, log
);
359 CLog::Log(LOGERROR
, "{}", log
);
376 void CGLSLShaderProgram::Disable()