summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/kodi-dev-kit/include/kodi/gui/gl/Shader.h
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2020-10-19 00:52:24 +0200
committermanuel <manuel@mausz.at>2020-10-19 00:52:24 +0200
commitbe933ef2241d79558f91796cc5b3a161f72ebf9c (patch)
treefe3ab2f130e20c99001f2d7a81d610c78c96a3f4 /xbmc/addons/kodi-dev-kit/include/kodi/gui/gl/Shader.h
parent5f8335c1e49ce108ef3481863833c98efa00411b (diff)
downloadkodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.tar.gz
kodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.tar.bz2
kodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.zip
sync with upstream
Diffstat (limited to 'xbmc/addons/kodi-dev-kit/include/kodi/gui/gl/Shader.h')
-rw-r--r--xbmc/addons/kodi-dev-kit/include/kodi/gui/gl/Shader.h571
1 files changed, 571 insertions, 0 deletions
diff --git a/xbmc/addons/kodi-dev-kit/include/kodi/gui/gl/Shader.h b/xbmc/addons/kodi-dev-kit/include/kodi/gui/gl/Shader.h
new file mode 100644
index 0000000..bf6d48c
--- /dev/null
+++ b/xbmc/addons/kodi-dev-kit/include/kodi/gui/gl/Shader.h
@@ -0,0 +1,571 @@
1/*
2 * Copyright (C) 2005-2019 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9#pragma once
10
11#include "GL.h"
12
13#ifdef __cplusplus
14
15#include <stdio.h>
16#include <string>
17#include <vector>
18
19#include <kodi/AddonBase.h>
20#include <kodi/Filesystem.h>
21
22#define LOG_SIZE 1024
23#define GLchar char
24
25namespace kodi
26{
27namespace gui
28{
29namespace gl
30{
31
32//========================================================================
33/// CShader - base class
34class ATTRIBUTE_HIDDEN CShader
35{
36public:
37 CShader() = default;
38 virtual ~CShader() = default;
39 virtual bool Compile(const std::string& extraBegin = "", const std::string& extraEnd = "") = 0;
40 virtual void Free() = 0;
41 virtual GLuint Handle() = 0;
42
43 bool LoadSource(const std::string& file)
44 {
45 char buffer[16384];
46
47 kodi::vfs::CFile source;
48 if (!source.OpenFile(file))
49 {
50 kodi::Log(ADDON_LOG_ERROR, "CShader::%s: Failed to open file '%s'", __FUNCTION__,
51 file.c_str());
52 return false;
53 }
54 size_t len = source.Read(buffer, sizeof(buffer));
55 m_source.assign(buffer);
56 m_source[len] = 0;
57 source.Close();
58 return true;
59 }
60
61 bool OK() const { return m_compiled; }
62
63protected:
64 std::string m_source;
65 std::string m_lastLog;
66 bool m_compiled = false;
67};
68//------------------------------------------------------------------------
69
70//========================================================================
71/// CVertexShader
72class ATTRIBUTE_HIDDEN CVertexShader : public CShader
73{
74public:
75 CVertexShader() = default;
76 ~CVertexShader() override { Free(); }
77
78 void Free() override
79 {
80 if (m_vertexShader)
81 glDeleteShader(m_vertexShader);
82 m_vertexShader = 0;
83 }
84
85 bool Compile(const std::string& extraBegin = "", const std::string& extraEnd = "") override
86 {
87 GLint params[4];
88
89 Free();
90
91 m_vertexShader = glCreateShader(GL_VERTEX_SHADER);
92
93 GLsizei count = 0;
94 const char* sources[3];
95 if (!extraBegin.empty())
96 sources[count++] = extraBegin.c_str();
97 if (!m_source.empty())
98 sources[count++] = m_source.c_str();
99 if (!extraEnd.empty())
100 sources[count++] = extraEnd.c_str();
101
102 glShaderSource(m_vertexShader, count, sources, nullptr);
103 glCompileShader(m_vertexShader);
104 glGetShaderiv(m_vertexShader, GL_COMPILE_STATUS, params);
105 if (params[0] != GL_TRUE)
106 {
107 GLchar log[LOG_SIZE];
108 glGetShaderInfoLog(m_vertexShader, LOG_SIZE, nullptr, log);
109 kodi::Log(ADDON_LOG_ERROR, "CVertexShader::%s: %s", __FUNCTION__, log);
110 fprintf(stderr, "CVertexShader::%s: %s\n", __FUNCTION__, log);
111 m_lastLog = log;
112 m_compiled = false;
113 }
114 else
115 {
116 GLchar log[LOG_SIZE];
117 glGetShaderInfoLog(m_vertexShader, LOG_SIZE, nullptr, log);
118 m_lastLog = log;
119 m_compiled = true;
120 }
121 return m_compiled;
122 }
123
124 GLuint Handle() override { return m_vertexShader; }
125
126protected:
127 GLuint m_vertexShader = 0;
128};
129//------------------------------------------------------------------------
130
131//========================================================================
132/// CPixelShader
133class ATTRIBUTE_HIDDEN CPixelShader : public CShader
134{
135public:
136 CPixelShader() = default;
137 ~CPixelShader() { Free(); }
138 void Free() override
139 {
140 if (m_pixelShader)
141 glDeleteShader(m_pixelShader);
142 m_pixelShader = 0;
143 }
144
145 bool Compile(const std::string& extraBegin = "", const std::string& extraEnd = "") override
146 {
147 GLint params[4];
148
149 Free();
150
151 m_pixelShader = glCreateShader(GL_FRAGMENT_SHADER);
152
153 GLsizei count = 0;
154 const char* sources[3];
155 if (!extraBegin.empty())
156 sources[count++] = extraBegin.c_str();
157 if (!m_source.empty())
158 sources[count++] = m_source.c_str();
159 if (!extraEnd.empty())
160 sources[count++] = extraEnd.c_str();
161
162 glShaderSource(m_pixelShader, count, sources, 0);
163 glCompileShader(m_pixelShader);
164 glGetShaderiv(m_pixelShader, GL_COMPILE_STATUS, params);
165 if (params[0] != GL_TRUE)
166 {
167 GLchar log[LOG_SIZE];
168 glGetShaderInfoLog(m_pixelShader, LOG_SIZE, nullptr, log);
169 kodi::Log(ADDON_LOG_ERROR, "CPixelShader::%s: %s", __FUNCTION__, log);
170 fprintf(stderr, "CPixelShader::%s: %s\n", __FUNCTION__, log);
171 m_lastLog = log;
172 m_compiled = false;
173 }
174 else
175 {
176 GLchar log[LOG_SIZE];
177 glGetShaderInfoLog(m_pixelShader, LOG_SIZE, nullptr, log);
178 m_lastLog = log;
179 m_compiled = true;
180 }
181 return m_compiled;
182 }
183
184 GLuint Handle() override { return m_pixelShader; }
185
186protected:
187 GLuint m_pixelShader = 0;
188};
189//------------------------------------------------------------------------
190
191//============================================================================
192/// @defgroup cpp_kodi_gui_helpers_gl_CShaderProgram GL Shader Program
193/// @ingroup cpp_kodi_gui_helpers_gl
194/// @brief @cpp_class{ kodi::gui::gl::CShaderProgram }
195/// **Class to manage an OpenGL shader program**\n
196/// With this class the used GL shader code can be defined on the GPU and
197/// its variables can be managed between CPU and GPU.
198///
199/// It has the header @ref Shader.h "#include <kodi/gui/gl/Shader.h>"
200/// be included to enjoy it.
201///
202/// ----------------------------------------------------------------------------
203///
204/// <b>Example:</b>
205///
206/// ~~~~~~~~~~~~~{.cpp}
207///
208/// #include <kodi/gui/gl/Shader.h>
209/// ...
210///
211/// class ATTRIBUTE_HIDDEN CExample
212/// : ...,
213/// public kodi::gui::gl::CShaderProgram
214/// {
215/// public:
216/// CExample() = default;
217///
218/// bool Start();
219/// void Render();
220///
221/// // override functions for kodi::gui::gl::CShaderProgram
222/// void OnCompiledAndLinked() override;
223/// bool OnEnabled() override;
224///
225/// private:
226/// ...
227/// GLint m_aPosition = -1;
228/// GLint m_aColor = -1;
229/// };
230///
231/// bool CExample::Start()
232/// {
233/// // Define shaders and load
234/// std::string fraqShader = kodi::GetAddonPath("resources/shaders/" GL_TYPE_STRING "/glsl.frag");
235/// std::string vertShader = kodi::GetAddonPath("resources/shaders/" GL_TYPE_STRING "/glsl.vert");
236/// if (!LoadShaderFiles(vertShader, fraqShader) || !CompileAndLink())
237/// return false;
238///
239/// ...
240/// return true;
241/// }
242///
243/// ...
244///
245/// void CExample::Render()
246/// {
247/// ...
248///
249/// EnableShader();
250/// ...
251/// DO WORK
252/// ...
253/// DisableShader();
254/// }
255///
256/// void CExample::OnCompiledAndLinked()
257/// {
258/// ...
259/// DO YOUR WORK HERE FOR WHAT IS ONE TIME REQUIRED DURING COMPILE OF SHADER, E.G.:
260///
261/// m_aPosition = glGetAttribLocation(ProgramHandle(), "a_position");
262/// m_aColor = glGetAttribLocation(ProgramHandle(), "a_color");
263/// }
264///
265/// bool OnEnabled() override
266/// {
267/// ...
268/// DO YOUR WORK HERE FOR WHAT REQUIRED DURING ENABLE OF SHADER
269/// ...
270/// return true;
271/// }
272///
273/// ADDONCREATOR(CExample);
274/// ~~~~~~~~~~~~~
275///
276class ATTRIBUTE_HIDDEN CShaderProgram
277{
278public:
279 //==========================================================================
280 /// @ingroup cpp_kodi_gui_helpers_gl_CShaderProgram
281 /// @brief Construct a new shader.
282 ///
283 /// Load must be done later with @ref LoadShaderFiles.
284 ///
285 CShaderProgram() = default;
286 //--------------------------------------------------------------------------
287
288 //==========================================================================
289 /// @ingroup cpp_kodi_gui_helpers_gl_CShaderProgram
290 /// @brief Construct a new shader and load defined shader files.
291 ///
292 /// @param[in] vert Path to used GL vertext shader
293 /// @param[in] frag Path to used GL fragment shader
294 ///
295 CShaderProgram(const std::string& vert, const std::string& frag) { LoadShaderFiles(vert, frag); }
296 //--------------------------------------------------------------------------
297
298 //==========================================================================
299 /// @ingroup cpp_kodi_gui_helpers_gl_CShaderProgram
300 /// @brief Destructor.
301 ///
302 virtual ~CShaderProgram() { ShaderFree(); }
303 //--------------------------------------------------------------------------
304
305 //==========================================================================
306 /// @ingroup cpp_kodi_gui_helpers_gl_CShaderProgram
307 /// @brief To load manually the needed shader files.
308 ///
309 /// @param[in] vert Path to used GL vertext shader
310 /// @param[in] frag Path to used GL fragment shader
311 ///
312 ///
313 /// @note The use of the files is optional, but it must either be passed over
314 /// here or via @ref CompileAndLink, or both of the source code.
315 ///
316 bool LoadShaderFiles(const std::string& vert, const std::string& frag)
317 {
318 if (!kodi::vfs::FileExists(vert) || !m_pVP.LoadSource(vert))
319 {
320 kodi::Log(ADDON_LOG_ERROR, "%s: Failed to load '%s'", __func__, vert.c_str());
321 return false;
322 }
323
324 if (!kodi::vfs::FileExists(frag) || !m_pFP.LoadSource(frag))
325 {
326 kodi::Log(ADDON_LOG_ERROR, "%s: Failed to load '%s'", __func__, frag.c_str());
327 return false;
328 }
329
330 return true;
331 }
332 //--------------------------------------------------------------------------
333
334 //==========================================================================
335 /// @ingroup cpp_kodi_gui_helpers_gl_CShaderProgram
336 /// @brief To compile and link the shader to the GL interface.
337 ///
338 /// Optionally, additional source code can be transferred here, or it can be
339 /// used independently without any files
340 ///
341 /// @param[in] vertexExtraBegin [opt] To additionally add vextex source
342 /// code to the beginning of the loaded file
343 /// source code
344 /// @param[in] vertexExtraEnd [opt] To additionally add vextex source
345 /// code to the end of the loaded file
346 /// source code
347 /// @param[in] fragmentExtraBegin [opt] To additionally add fragment source
348 /// code to the beginning of the loaded file
349 /// source code
350 /// @param[in] fragmentExtraEnd [opt] To additionally add fragment source
351 /// code to the end of the loaded file
352 /// source code
353 /// @return true if compile was successed
354 ///
355 ///
356 /// @note In the case of a compile error, it will be written once into the Kodi
357 /// log and in addition to the console output to quickly detect the errors when
358 /// writing the damage.
359 ///
360 ///
361 bool CompileAndLink(const std::string& vertexExtraBegin = "",
362 const std::string& vertexExtraEnd = "",
363 const std::string& fragmentExtraBegin = "",
364 const std::string& fragmentExtraEnd = "")
365 {
366 GLint params[4];
367
368 // free resources
369 ShaderFree();
370 m_ok = false;
371
372 // compiled vertex shader
373 if (!m_pVP.Compile(vertexExtraBegin, vertexExtraEnd))
374 {
375 kodi::Log(ADDON_LOG_ERROR, "GL: Error compiling vertex shader");
376 return false;
377 }
378
379 // compile pixel shader
380 if (!m_pFP.Compile(fragmentExtraBegin, fragmentExtraEnd))
381 {
382 m_pVP.Free();
383 kodi::Log(ADDON_LOG_ERROR, "GL: Error compiling fragment shader");
384 return false;
385 }
386
387 // create program object
388 m_shaderProgram = glCreateProgram();
389 if (!m_shaderProgram)
390 {
391 kodi::Log(ADDON_LOG_ERROR, "CShaderProgram::%s: Failed to create GL program", __FUNCTION__);
392 ShaderFree();
393 return false;
394 }
395
396 // attach the vertex shader
397 glAttachShader(m_shaderProgram, m_pVP.Handle());
398 glAttachShader(m_shaderProgram, m_pFP.Handle());
399
400 // link the program
401 glLinkProgram(m_shaderProgram);
402 glGetProgramiv(m_shaderProgram, GL_LINK_STATUS, params);
403 if (params[0] != GL_TRUE)
404 {
405 GLchar log[LOG_SIZE];
406 glGetProgramInfoLog(m_shaderProgram, LOG_SIZE, nullptr, log);
407 kodi::Log(ADDON_LOG_ERROR, "CShaderProgram::%s: %s", __FUNCTION__, log);
408 fprintf(stderr, "CShaderProgram::%s: %s@n", __FUNCTION__, log);
409 ShaderFree();
410 return false;
411 }
412
413 m_validated = false;
414 m_ok = true;
415 OnCompiledAndLinked();
416 return true;
417 }
418 //--------------------------------------------------------------------------
419
420 //==========================================================================
421 /// @ingroup cpp_kodi_gui_helpers_gl_CShaderProgram
422 /// @brief To activate the shader and use it on the GPU.
423 ///
424 /// @return true if enable was successfull done
425 ///
426 ///
427 /// @note During this call, the @ref OnEnabled stored in the child is also
428 /// called
429 ///
430 bool EnableShader()
431 {
432 if (ShaderOK())
433 {
434 glUseProgram(m_shaderProgram);
435 if (OnEnabled())
436 {
437 if (!m_validated)
438 {
439 // validate the program
440 GLint params[4];
441 glValidateProgram(m_shaderProgram);
442 glGetProgramiv(m_shaderProgram, GL_VALIDATE_STATUS, params);
443 if (params[0] != GL_TRUE)
444 {
445 GLchar log[LOG_SIZE];
446 glGetProgramInfoLog(m_shaderProgram, LOG_SIZE, nullptr, log);
447 kodi::Log(ADDON_LOG_ERROR, "CShaderProgram::%s: %s", __FUNCTION__, log);
448 fprintf(stderr, "CShaderProgram::%s: %s\n", __FUNCTION__, log);
449 }
450 m_validated = true;
451 }
452 return true;
453 }
454 else
455 {
456 glUseProgram(0);
457 return false;
458 }
459 return true;
460 }
461 return false;
462 }
463 //--------------------------------------------------------------------------
464
465 //==========================================================================
466 /// @ingroup cpp_kodi_gui_helpers_gl_CShaderProgram
467 /// @brief To deactivate the shader use on the GPU.
468 ///
469 void DisableShader()
470 {
471 if (ShaderOK())
472 {
473 glUseProgram(0);
474 OnDisabled();
475 }
476 }
477 //--------------------------------------------------------------------------
478
479 //==========================================================================
480 /// @ingroup cpp_kodi_gui_helpers_gl_CShaderProgram
481 /// @brief Used to check if shader has been loaded before.
482 ///
483 /// @return true if enable was successfull done
484 ///
485 /// @note The CompileAndLink call sets these values
486 ///
487 ATTRIBUTE_FORCEINLINE bool ShaderOK() const { return m_ok; }
488 //--------------------------------------------------------------------------
489
490 //==========================================================================
491 /// @ingroup cpp_kodi_gui_helpers_gl_CShaderProgram
492 /// @brief To get the vertex shader class used by Kodi at the addon.
493 ///
494 /// @return pointer to vertex shader class
495 ///
496 ATTRIBUTE_FORCEINLINE CVertexShader& VertexShader() { return m_pVP; }
497 //--------------------------------------------------------------------------
498
499 //==========================================================================
500 /// @ingroup cpp_kodi_gui_helpers_gl_CShaderProgram
501 /// @brief To get the fragment shader class used by Kodi at the addon.
502 ///
503 /// @return pointer to fragment shader class
504 ///
505 ATTRIBUTE_FORCEINLINE CPixelShader& PixelShader() { return m_pFP; }
506 //--------------------------------------------------------------------------
507
508 //==========================================================================
509 /// @ingroup cpp_kodi_gui_helpers_gl_CShaderProgram
510 /// @brief Used to get the definition created in the OpenGL itself.
511 ///
512 /// @return GLuint of GL shader program handler
513 ///
514 ATTRIBUTE_FORCEINLINE GLuint ProgramHandle() { return m_shaderProgram; }
515 //--------------------------------------------------------------------------
516
517 //==========================================================================
518 /// @defgroup cpp_kodi_gui_helpers_gl_CShaderProgram_child Child Functions
519 /// @ingroup cpp_kodi_gui_helpers_gl_CShaderProgram
520 /// @brief @cpp_class{ kodi::gui::gl::CShaderProgram child functions }
521 ///
522 /// Functions that are added by parent in the child
523 /// @{
524 //==========================================================================
525 ///
526 /// @ingroup cpp_kodi_gui_helpers_gl_CShaderProgram_child
527 /// @brief Mandatory child function to set the necessary CPU to GPU data
528 ///
529 virtual void OnCompiledAndLinked(){};
530 //--------------------------------------------------------------------------
531
532 //==========================================================================
533 /// @ingroup cpp_kodi_gui_helpers_gl_CShaderProgram_child
534 /// @brief Optional function to exchange data between CPU and GPU while
535 /// activating the shader
536 ///
537 /// @return true if enable was successfull done
538 ///
539 virtual bool OnEnabled() { return true; };
540 //--------------------------------------------------------------------------
541
542 //==========================================================================
543 /// @ingroup cpp_kodi_gui_helpers_gl_CShaderProgram_child
544 /// @brief Optional child function that may have to be performed when
545 /// switching off the shader
546 virtual void OnDisabled(){};
547 //--------------------------------------------------------------------------
548 /// @}
549
550private:
551 void ShaderFree()
552 {
553 if (m_shaderProgram)
554 glDeleteProgram(m_shaderProgram);
555 m_shaderProgram = 0;
556 m_ok = false;
557 }
558
559 CVertexShader m_pVP;
560 CPixelShader m_pFP;
561 GLuint m_shaderProgram = 0;
562 bool m_ok = false;
563 bool m_validated = false;
564};
565//------------------------------------------------------------------------
566
567} /* namespace gl */
568} /* namespace gui */
569} /* namespace kodi */
570
571#endif /* __cplusplus */