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