Kodi Development 22.0
for Binary and Script based Add-Ons
 
Loading...
Searching...
No Matches
Shader.h
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//========================================================================
34class ATTR_DLL_LOCAL 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//========================================================================
72class ATTR_DLL_LOCAL 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//========================================================================
133class ATTR_DLL_LOCAL 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//============================================================================
276class ATTR_DLL_LOCAL CShaderProgram
277{
278public:
279 //==========================================================================
285 CShaderProgram() = default;
286 //--------------------------------------------------------------------------
287
288 //==========================================================================
295 CShaderProgram(const std::string& vert, const std::string& frag) { LoadShaderFiles(vert, frag); }
296 //--------------------------------------------------------------------------
297
298 //==========================================================================
302 virtual ~CShaderProgram() { ShaderFree(); }
303 //--------------------------------------------------------------------------
304
305 //==========================================================================
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 //==========================================================================
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 //==========================================================================
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 //==========================================================================
470 {
471 if (ShaderOK())
472 {
473 glUseProgram(0);
474 OnDisabled();
475 }
476 }
477 //--------------------------------------------------------------------------
478
479 //==========================================================================
487 ATTR_FORCEINLINE bool ShaderOK() const { return m_ok; }
488 //--------------------------------------------------------------------------
489
490 //==========================================================================
496 ATTR_FORCEINLINE CVertexShader& VertexShader() { return m_pVP; }
497 //--------------------------------------------------------------------------
498
499 //==========================================================================
505 ATTR_FORCEINLINE CPixelShader& PixelShader() { return m_pFP; }
506 //--------------------------------------------------------------------------
507
508 //==========================================================================
514 ATTR_FORCEINLINE GLuint ProgramHandle() { return m_shaderProgram; }
515 //--------------------------------------------------------------------------
516
517 //==========================================================================
524 //==========================================================================
529 virtual void OnCompiledAndLinked() {}
530 //--------------------------------------------------------------------------
531
532 //==========================================================================
539 virtual bool OnEnabled() { return true; }
540 //--------------------------------------------------------------------------
541
542 //==========================================================================
546 virtual void OnDisabled() {}
547 //--------------------------------------------------------------------------
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 */
CPixelShader.
Definition Shader.h:134
CShader - base class.
Definition Shader.h:35
Definition Shader.h:277
CVertexShader.
Definition Shader.h:73
Definition Filesystem.h:1835
@ ADDON_LOG_ERROR
3 : To report error messages in the log file.
Definition addon_base.h:193
virtual void OnCompiledAndLinked()
Mandatory child function to set the necessary CPU to GPU data.
Definition Shader.h:529
virtual void OnDisabled()
Optional child function that may have to be performed when switching off the shader.
Definition Shader.h:546
virtual bool OnEnabled()
Optional function to exchange data between CPU and GPU while activating the shader.
Definition Shader.h:539
CShaderProgram(const std::string &vert, const std::string &frag)
Construct a new shader and load defined shader files.
Definition Shader.h:295
bool LoadShaderFiles(const std::string &vert, const std::string &frag)
To load manually the needed shader files.
Definition Shader.h:316
ATTR_FORCEINLINE GLuint ProgramHandle()
Used to get the definition created in the OpenGL itself.
Definition Shader.h:514
CShaderProgram()=default
Construct a new shader.
ATTR_FORCEINLINE bool ShaderOK() const
Used to check if shader has been loaded before.
Definition Shader.h:487
bool EnableShader()
To activate the shader and use it on the GPU.
Definition Shader.h:430
bool CompileAndLink(const std::string &vertexExtraBegin="", const std::string &vertexExtraEnd="", const std::string &fragmentExtraBegin="", const std::string &fragmentExtraEnd="")
To compile and link the shader to the GL interface.
Definition Shader.h:361
ATTR_FORCEINLINE CVertexShader & VertexShader()
To get the vertex shader class used by Kodi at the addon.
Definition Shader.h:496
ATTR_FORCEINLINE CPixelShader & PixelShader()
To get the fragment shader class used by Kodi at the addon.
Definition Shader.h:505
void DisableShader()
To deactivate the shader use on the GPU.
Definition Shader.h:469
virtual ~CShaderProgram()
Destructor.
Definition Shader.h:302
void Close()
Close an open file.
Definition Filesystem.h:1921
bool OpenFile(const std::string &filename, unsigned int flags=0)
Open the file with filename via Kodi's CFile. Needs to be closed by calling Close() when done.
Definition Filesystem.h:1861
ssize_t Read(void *ptr, size_t size)
Read from an open file.
Definition Filesystem.h:2005
bool ATTR_DLL_LOCAL FileExists(const std::string &filename, bool usecache=false)
Check if a file exists.
Definition Filesystem.h:945
void ATTR_DLL_LOCAL Log(const ADDON_LOG loglevel, const char *format,...)
Add a message to Kodi's log.
Definition AddonBase.h:1938
log(...)
<h4><code><span style="font-style: italic;">Function: </span><span style="font-style: bold;"><font co...