Merge pull request #26117 from notspiff/infoscanner_inforet_enum_class
[xbmc.git] / xbmc / rendering / gl / RenderSystemGL.cpp
blob94a71dae48e807d10ee2496638c76b4f5fca48d2
1 /*
2 * Copyright (C) 2005-2024 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.
7 */
9 #include "RenderSystemGL.h"
11 #include "ServiceBroker.h"
12 #include "URL.h"
13 #include "guilib/GUITextureGL.h"
14 #include "platform/MessagePrinter.h"
15 #include "rendering/MatrixGL.h"
16 #include "settings/AdvancedSettings.h"
17 #include "settings/SettingsComponent.h"
18 #include "utils/FileUtils.h"
19 #include "utils/GLUtils.h"
20 #include "utils/MathUtils.h"
21 #include "utils/XTimeUtils.h"
22 #include "utils/log.h"
23 #include "windowing/WinSystem.h"
25 #include <exception>
27 #if defined(TARGET_LINUX)
28 #include "utils/EGLUtils.h"
29 #endif
31 using namespace std::chrono_literals;
33 CRenderSystemGL::CRenderSystemGL() : CRenderSystemBase()
37 CRenderSystemGL::~CRenderSystemGL() = default;
39 bool CRenderSystemGL::InitRenderSystem()
41 m_bVSync = false;
42 m_bVsyncInit = false;
43 m_maxTextureSize = 2048;
45 // Get the GL version number
46 m_RenderVersionMajor = 0;
47 m_RenderVersionMinor = 0;
48 m_RenderVersion = "<none>";
49 const char* ver = reinterpret_cast<const char*>(glGetString(GL_VERSION));
50 if (ver)
52 sscanf(ver, "%d.%d", &m_RenderVersionMajor, &m_RenderVersionMinor);
53 m_RenderVersion = ver;
56 CLog::Log(LOGINFO, "CRenderSystemGL::{} - Version: {}, Major: {}, Minor: {}", __FUNCTION__,
57 m_RenderVersion, m_RenderVersionMajor, m_RenderVersionMinor);
59 m_RenderExtensions = "";
60 if (m_RenderVersionMajor > 3 ||
61 (m_RenderVersionMajor == 3 && m_RenderVersionMinor >= 2))
63 GLint n = 0;
64 glGetIntegerv(GL_NUM_EXTENSIONS, &n);
65 if (n > 0)
67 GLint i;
68 for (i = 0; i < n; i++)
70 const char* extension = reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i));
71 if (extension)
73 m_RenderExtensions += extension;
74 m_RenderExtensions += " ";
79 else
81 const char* extensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
82 if (extensions)
84 m_RenderExtensions += extensions;
85 m_RenderExtensions += " ";
89 ver = reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
90 if (ver)
92 sscanf(ver, "%d.%d", &m_glslMajor, &m_glslMinor);
94 else
96 m_glslMajor = 1;
97 m_glslMinor = 0;
100 #if defined(GL_KHR_debug) && defined(TARGET_LINUX)
101 if (CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_openGlDebugging)
103 if (IsExtSupported("GL_KHR_debug"))
105 auto glDebugMessageCallback =
106 CEGLUtils::GetRequiredProcAddress<PFNGLDEBUGMESSAGECALLBACKPROC>(
107 "glDebugMessageCallback");
108 auto glDebugMessageControl =
109 CEGLUtils::GetRequiredProcAddress<PFNGLDEBUGMESSAGECONTROLPROC>("glDebugMessageControl");
111 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
112 glDebugMessageCallback(KODI::UTILS::GL::GlErrorCallback, nullptr);
114 // ignore shader compilation information
115 glDebugMessageControl(GL_DEBUG_SOURCE_SHADER_COMPILER, GL_DEBUG_TYPE_OTHER, GL_DONT_CARE, 0,
116 nullptr, GL_FALSE);
118 CLog::Log(LOGDEBUG, "OpenGL: debugging enabled");
120 else
122 CLog::Log(LOGDEBUG, "OpenGL: debugging requested but the required extension isn't "
123 "available (GL_KHR_debug)");
126 #endif
128 // Shut down gracefully if OpenGL context could not be allocated
129 if (m_RenderVersionMajor == 0)
131 CLog::Log(LOGFATAL, "Can not initialize OpenGL context. Exiting");
132 CMessagePrinter::DisplayError("ERROR: Can not initialize OpenGL context. Exiting");
133 return false;
136 LogGraphicsInfo();
138 // Get our driver vendor and renderer
139 const char* tmpVendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
140 m_RenderVendor.clear();
141 if (tmpVendor)
142 m_RenderVendor = tmpVendor;
144 const char* tmpRenderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
145 m_RenderRenderer.clear();
146 if (tmpRenderer)
147 m_RenderRenderer = tmpRenderer;
149 m_bRenderCreated = true;
151 if (m_RenderVersionMajor > 3 ||
152 (m_RenderVersionMajor == 3 && m_RenderVersionMinor >= 2))
154 glGenVertexArrays(1, &m_vertexArray);
155 glBindVertexArray(m_vertexArray);
158 InitialiseShaders();
160 CGUITextureGL::Register();
162 return true;
165 bool CRenderSystemGL::ResetRenderSystem(int width, int height)
167 if (!m_bRenderCreated)
168 return false;
170 m_width = width;
171 m_height = height;
173 if (m_RenderVersionMajor > 3 ||
174 (m_RenderVersionMajor == 3 && m_RenderVersionMinor >= 2))
176 glBindVertexArray(0);
177 glDeleteVertexArrays(1, &m_vertexArray);
178 glGenVertexArrays(1, &m_vertexArray);
179 glBindVertexArray(m_vertexArray);
182 ReleaseShaders();
183 InitialiseShaders();
185 glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
187 CalculateMaxTexturesize();
189 CRect rect( 0, 0, width, height );
190 SetViewPort( rect );
192 glEnable(GL_SCISSOR_TEST);
194 glMatrixProject.Clear();
195 glMatrixProject->LoadIdentity();
196 glMatrixProject->Ortho(0.0f, width-1, height-1, 0.0f, -1.0f, 1.0f);
197 glMatrixProject.Load();
199 glMatrixModview.Clear();
200 glMatrixModview->LoadIdentity();
201 glMatrixModview.Load();
203 glMatrixTexture.Clear();
204 glMatrixTexture->LoadIdentity();
205 glMatrixTexture.Load();
207 if (IsExtSupported("GL_ARB_multitexture"))
209 //clear error flags
210 ResetGLErrors();
212 GLint maxtex;
213 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxtex);
215 //some sanity checks
216 GLenum error = glGetError();
217 if (error != GL_NO_ERROR)
219 CLog::Log(LOGERROR, "ResetRenderSystem() GL_MAX_TEXTURE_IMAGE_UNITS returned error {}",
220 (int)error);
221 maxtex = 3;
223 else if (maxtex < 1 || maxtex > 32)
225 CLog::Log(LOGERROR,
226 "ResetRenderSystem() GL_MAX_TEXTURE_IMAGE_UNITS returned invalid value {}",
227 (int)maxtex);
228 maxtex = 3;
231 //reset texture matrix for all textures
232 for (GLint i = 0; i < maxtex; i++)
234 glActiveTexture(GL_TEXTURE0 + i);
235 glMatrixTexture.Load();
237 glActiveTexture(GL_TEXTURE0);
240 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
241 glEnable(GL_BLEND); // Turn Blending On
243 return true;
246 bool CRenderSystemGL::DestroyRenderSystem()
248 if (m_vertexArray != GL_NONE)
250 glDeleteVertexArrays(1, &m_vertexArray);
253 ReleaseShaders();
254 m_bRenderCreated = false;
256 return true;
259 bool CRenderSystemGL::BeginRender()
261 if (!m_bRenderCreated)
262 return false;
264 bool useLimited = CServiceBroker::GetWinSystem()->UseLimitedColor();
266 if (m_limitedColorRange != useLimited)
268 ReleaseShaders();
269 InitialiseShaders();
272 m_limitedColorRange = useLimited;
273 return true;
276 bool CRenderSystemGL::EndRender()
278 if (!m_bRenderCreated)
279 return false;
281 return true;
284 void CRenderSystemGL::InvalidateColorBuffer()
286 if (!m_bRenderCreated)
287 return;
289 /* clear is not affected by stipple pattern, so we can only clear on first frame */
290 if (m_stereoMode == RENDER_STEREO_MODE_INTERLACED && m_stereoView == RENDER_STEREO_VIEW_RIGHT)
291 return;
293 // some platforms prefer a clear, instead of rendering over
294 if (!CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_guiGeometryClear)
296 ClearBuffers(0);
297 return;
300 if (!CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_guiFrontToBackRendering)
301 return;
303 glClearDepthf(0);
304 glDepthMask(GL_TRUE);
305 glClear(GL_DEPTH_BUFFER_BIT);
308 bool CRenderSystemGL::ClearBuffers(KODI::UTILS::COLOR::Color color)
310 if (!m_bRenderCreated)
311 return false;
313 /* clear is not affected by stipple pattern, so we can only clear on first frame */
314 if(m_stereoMode == RENDER_STEREO_MODE_INTERLACED && m_stereoView == RENDER_STEREO_VIEW_RIGHT)
315 return true;
317 float r = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::R, color) / 255.0f;
318 float g = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::G, color) / 255.0f;
319 float b = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::B, color) / 255.0f;
320 float a = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::A, color) / 255.0f;
322 glClearColor(r, g, b, a);
324 GLbitfield flags = GL_COLOR_BUFFER_BIT;
326 if (CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_guiFrontToBackRendering)
328 glClearDepthf(0);
329 glDepthMask(GL_TRUE);
330 flags |= GL_DEPTH_BUFFER_BIT;
333 glClear(flags);
335 return true;
338 bool CRenderSystemGL::IsExtSupported(const char* extension) const
340 if (m_RenderVersionMajor > 3 ||
341 (m_RenderVersionMajor == 3 && m_RenderVersionMinor >= 2))
343 if (strcmp( extension, "GL_EXT_framebuffer_object") == 0)
345 return true;
347 if (strcmp( extension, "GL_ARB_texture_non_power_of_two") == 0)
349 return true;
353 std::string name;
354 name = " ";
355 name += extension;
356 name += " ";
358 return m_RenderExtensions.find(name) != std::string::npos;
361 bool CRenderSystemGL::SupportsNPOT(bool dxt) const
363 return true;
366 void CRenderSystemGL::PresentRender(bool rendered, bool videoLayer)
368 SetVSync(true);
370 if (!m_bRenderCreated)
371 return;
373 PresentRenderImpl(rendered);
375 if (!rendered)
376 KODI::TIME::Sleep(40ms);
379 void CRenderSystemGL::SetVSync(bool enable)
381 if (m_bVSync == enable && m_bVsyncInit == true)
382 return;
384 if (!m_bRenderCreated)
385 return;
387 if (enable)
388 CLog::Log(LOGINFO, "GL: Enabling VSYNC");
389 else
390 CLog::Log(LOGINFO, "GL: Disabling VSYNC");
392 m_bVSync = enable;
393 m_bVsyncInit = true;
395 SetVSyncImpl(enable);
398 void CRenderSystemGL::CaptureStateBlock()
400 if (!m_bRenderCreated)
401 return;
403 glMatrixProject.Push();
404 glMatrixModview.Push();
405 glMatrixTexture.Push();
407 glDisable(GL_SCISSOR_TEST); // fixes FBO corruption on Macs
408 glActiveTexture(GL_TEXTURE0);
411 void CRenderSystemGL::ApplyStateBlock()
413 if (!m_bRenderCreated)
414 return;
416 glBindVertexArray(m_vertexArray);
418 glViewport(m_viewPort[0], m_viewPort[1], m_viewPort[2], m_viewPort[3]);
420 glMatrixProject.PopLoad();
421 glMatrixModview.PopLoad();
422 glMatrixTexture.PopLoad();
424 glActiveTexture(GL_TEXTURE0);
425 glEnable(GL_BLEND);
426 glEnable(GL_SCISSOR_TEST);
429 void CRenderSystemGL::SetCameraPosition(const CPoint &camera, int screenWidth, int screenHeight, float stereoFactor)
431 if (!m_bRenderCreated)
432 return;
434 CPoint offset = camera - CPoint(screenWidth*0.5f, screenHeight*0.5f);
437 float w = (float)m_viewPort[2]*0.5f;
438 float h = (float)m_viewPort[3]*0.5f;
440 glMatrixModview->LoadIdentity();
441 glMatrixModview->Translatef(-(w + offset.x - stereoFactor), +(h + offset.y), 0);
442 glMatrixModview->LookAt(0.0f, 0.0f, -2.0f * h, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f);
443 glMatrixModview.Load();
445 glMatrixProject->LoadIdentity();
446 glMatrixProject->Frustum( (-w - offset.x)*0.5f, (w - offset.x)*0.5f, (-h + offset.y)*0.5f, (h + offset.y)*0.5f, h, 100*h);
447 glMatrixProject.Load();
450 void CRenderSystemGL::Project(float &x, float &y, float &z)
452 GLfloat coordX, coordY, coordZ;
453 if (CMatrixGL::Project(x, y, z, glMatrixModview.Get(), glMatrixProject.Get(), m_viewPort, &coordX, &coordY, &coordZ))
455 x = coordX;
456 y = (float)(m_viewPort[1] + m_viewPort[3] - coordY);
457 z = 0;
461 void CRenderSystemGL::CalculateMaxTexturesize()
463 GLint width = 256;
465 // reset any previous GL errors
466 ResetGLErrors();
468 // max out at 2^(8+8)
469 for (int i = 0 ; i<8 ; i++)
471 glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, width, width, 0, GL_BGRA,
472 GL_UNSIGNED_BYTE, NULL);
473 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
474 &width);
476 // GMA950 on OS X sets error instead
477 if (width == 0 || (glGetError() != GL_NO_ERROR) )
478 break;
480 m_maxTextureSize = width;
481 width *= 2;
482 if (width > 65536) // have an upper limit in case driver acts stupid
484 CLog::Log(LOGERROR, "GL: Could not determine maximum texture width, falling back to 2048");
485 m_maxTextureSize = 2048;
486 break;
490 CLog::Log(LOGINFO, "GL: Maximum texture width: {}", m_maxTextureSize);
493 void CRenderSystemGL::GetViewPort(CRect& viewPort)
495 if (!m_bRenderCreated)
496 return;
498 viewPort.x1 = m_viewPort[0];
499 viewPort.y1 = m_height - m_viewPort[1] - m_viewPort[3];
500 viewPort.x2 = m_viewPort[0] + m_viewPort[2];
501 viewPort.y2 = viewPort.y1 + m_viewPort[3];
504 void CRenderSystemGL::SetViewPort(const CRect& viewPort)
506 if (!m_bRenderCreated)
507 return;
509 glScissor((GLint) viewPort.x1, (GLint) (m_height - viewPort.y1 - viewPort.Height()), (GLsizei) viewPort.Width(), (GLsizei) viewPort.Height());
510 glViewport((GLint) viewPort.x1, (GLint) (m_height - viewPort.y1 - viewPort.Height()), (GLsizei) viewPort.Width(), (GLsizei) viewPort.Height());
511 m_viewPort[0] = viewPort.x1;
512 m_viewPort[1] = m_height - viewPort.y1 - viewPort.Height();
513 m_viewPort[2] = viewPort.Width();
514 m_viewPort[3] = viewPort.Height();
517 bool CRenderSystemGL::ScissorsCanEffectClipping()
519 if (m_pShader[m_method])
520 return m_pShader[m_method]->HardwareClipIsPossible();
522 return false;
525 CRect CRenderSystemGL::ClipRectToScissorRect(const CRect &rect)
527 if (!m_pShader[m_method])
528 return CRect();
529 float xFactor = m_pShader[m_method]->GetClipXFactor();
530 float xOffset = m_pShader[m_method]->GetClipXOffset();
531 float yFactor = m_pShader[m_method]->GetClipYFactor();
532 float yOffset = m_pShader[m_method]->GetClipYOffset();
533 return CRect(rect.x1 * xFactor + xOffset,
534 rect.y1 * yFactor + yOffset,
535 rect.x2 * xFactor + xOffset,
536 rect.y2 * yFactor + yOffset);
539 void CRenderSystemGL::SetScissors(const CRect &rect)
541 if (!m_bRenderCreated)
542 return;
543 GLint x1 = MathUtils::round_int(static_cast<double>(rect.x1));
544 GLint y1 = MathUtils::round_int(static_cast<double>(rect.y1));
545 GLint x2 = MathUtils::round_int(static_cast<double>(rect.x2));
546 GLint y2 = MathUtils::round_int(static_cast<double>(rect.y2));
547 glScissor(x1, m_height - y2, x2-x1, y2-y1);
550 void CRenderSystemGL::ResetScissors()
552 SetScissors(CRect(0, 0, (float)m_width, (float)m_height));
555 void CRenderSystemGL::SetDepthCulling(DEPTH_CULLING culling)
557 if (culling == DEPTH_CULLING_OFF)
559 glDisable(GL_DEPTH_TEST);
560 glDepthMask(GL_FALSE);
562 else if (culling == DEPTH_CULLING_BACK_TO_FRONT)
564 glEnable(GL_DEPTH_TEST);
565 glDepthMask(GL_FALSE);
566 glDepthFunc(GL_GEQUAL);
568 else if (culling == DEPTH_CULLING_FRONT_TO_BACK)
570 glEnable(GL_DEPTH_TEST);
571 glDepthMask(GL_TRUE);
572 glDepthFunc(GL_GREATER);
576 void CRenderSystemGL::GetGLSLVersion(int& major, int& minor)
578 major = m_glslMajor;
579 minor = m_glslMinor;
582 void CRenderSystemGL::ResetGLErrors()
584 int count = 0;
585 while (glGetError() != GL_NO_ERROR)
587 count++;
588 if (count >= 100)
590 CLog::Log(
591 LOGWARNING,
592 "CRenderSystemGL::ResetGLErrors glGetError didn't return GL_NO_ERROR after {} iterations",
593 count);
594 break;
598 static const GLubyte stipple_3d[] = {
599 0x00, 0x00, 0x00, 0x00,
600 0xFF, 0xFF, 0xFF, 0xFF,
601 0x00, 0x00, 0x00, 0x00,
602 0xFF, 0xFF, 0xFF, 0xFF,
603 0x00, 0x00, 0x00, 0x00,
604 0xFF, 0xFF, 0xFF, 0xFF,
605 0x00, 0x00, 0x00, 0x00,
606 0xFF, 0xFF, 0xFF, 0xFF,
607 0x00, 0x00, 0x00, 0x00,
608 0xFF, 0xFF, 0xFF, 0xFF,
609 0x00, 0x00, 0x00, 0x00,
610 0xFF, 0xFF, 0xFF, 0xFF,
611 0x00, 0x00, 0x00, 0x00,
612 0xFF, 0xFF, 0xFF, 0xFF,
613 0x00, 0x00, 0x00, 0x00,
614 0xFF, 0xFF, 0xFF, 0xFF,
615 0x00, 0x00, 0x00, 0x00,
616 0xFF, 0xFF, 0xFF, 0xFF,
617 0x00, 0x00, 0x00, 0x00,
618 0xFF, 0xFF, 0xFF, 0xFF,
619 0x00, 0x00, 0x00, 0x00,
620 0xFF, 0xFF, 0xFF, 0xFF,
621 0x00, 0x00, 0x00, 0x00,
622 0xFF, 0xFF, 0xFF, 0xFF,
623 0x00, 0x00, 0x00, 0x00,
624 0xFF, 0xFF, 0xFF, 0xFF,
625 0x00, 0x00, 0x00, 0x00,
626 0xFF, 0xFF, 0xFF, 0xFF,
627 0x00, 0x00, 0x00, 0x00,
628 0xFF, 0xFF, 0xFF, 0xFF,
629 0x00, 0x00, 0x00, 0x00,
630 0xFF, 0xFF, 0xFF, 0xFF,
631 0x00, 0x00, 0x00, 0x00,
634 void CRenderSystemGL::SetStereoMode(RENDER_STEREO_MODE mode, RENDER_STEREO_VIEW view)
636 CRenderSystemBase::SetStereoMode(mode, view);
638 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
639 glDrawBuffer(GL_BACK);
641 if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN)
643 if(m_stereoView == RENDER_STEREO_VIEW_LEFT)
644 glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
645 else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT)
646 glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
648 if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA)
650 if(m_stereoView == RENDER_STEREO_VIEW_LEFT)
651 glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
652 else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT)
653 glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_TRUE);
655 if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE)
657 if(m_stereoView == RENDER_STEREO_VIEW_LEFT)
658 glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE);
659 else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT)
660 glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
663 if(m_stereoMode == RENDER_STEREO_MODE_INTERLACED)
665 glEnable(GL_POLYGON_STIPPLE);
666 if(m_stereoView == RENDER_STEREO_VIEW_LEFT)
667 glPolygonStipple(stipple_3d);
668 else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT)
669 glPolygonStipple(stipple_3d+4);
672 if(m_stereoMode == RENDER_STEREO_MODE_HARDWAREBASED)
674 if(m_stereoView == RENDER_STEREO_VIEW_LEFT)
675 glDrawBuffer(GL_BACK_LEFT);
676 else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT)
677 glDrawBuffer(GL_BACK_RIGHT);
682 bool CRenderSystemGL::SupportsStereo(RENDER_STEREO_MODE mode) const
684 switch(mode)
686 case RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN:
687 case RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA:
688 case RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE:
689 case RENDER_STEREO_MODE_INTERLACED:
690 return true;
691 case RENDER_STEREO_MODE_HARDWAREBASED: {
692 //This is called by setting init, at which point GL is not inited
693 //luckily if GL doesn't support this, it will just behave as if
694 //it was not in effect.
695 //GLboolean stereo = GL_FALSE;
696 //glGetBooleanv(GL_STEREO, &stereo);
697 //return stereo == GL_TRUE ? true : false;
698 return true;
700 default:
701 return CRenderSystemBase::SupportsStereo(mode);
705 // -----------------------------------------------------------------------------
706 // shaders
707 // -----------------------------------------------------------------------------
708 void CRenderSystemGL::InitialiseShaders()
710 std::string defines;
711 m_limitedColorRange = CServiceBroker::GetWinSystem()->UseLimitedColor();
712 if (m_limitedColorRange)
714 defines += "#define KODI_LIMITED_RANGE 1\n";
717 m_pShader[ShaderMethodGL::SM_DEFAULT] = std::make_unique<CGLShader>(
718 "gl_shader_vert_default.glsl", "gl_shader_frag_default.glsl", defines);
719 if (!m_pShader[ShaderMethodGL::SM_DEFAULT]->CompileAndLink())
721 m_pShader[ShaderMethodGL::SM_DEFAULT]->Free();
722 m_pShader[ShaderMethodGL::SM_DEFAULT].reset();
723 CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_default.glsl - compile and link failed");
726 m_pShader[ShaderMethodGL::SM_TEXTURE] =
727 std::make_unique<CGLShader>("gl_shader_frag_texture.glsl", defines);
728 if (!m_pShader[ShaderMethodGL::SM_TEXTURE]->CompileAndLink())
730 m_pShader[ShaderMethodGL::SM_TEXTURE]->Free();
731 m_pShader[ShaderMethodGL::SM_TEXTURE].reset();
732 CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_texture.glsl - compile and link failed");
735 m_pShader[ShaderMethodGL::SM_TEXTURE_LIM] =
736 std::make_unique<CGLShader>("gl_shader_frag_texture_lim.glsl", defines);
737 if (!m_pShader[ShaderMethodGL::SM_TEXTURE_LIM]->CompileAndLink())
739 m_pShader[ShaderMethodGL::SM_TEXTURE_LIM]->Free();
740 m_pShader[ShaderMethodGL::SM_TEXTURE_LIM].reset();
741 CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_texture_lim.glsl - compile and link failed");
744 m_pShader[ShaderMethodGL::SM_MULTI] =
745 std::make_unique<CGLShader>("gl_shader_frag_multi.glsl", defines);
746 if (!m_pShader[ShaderMethodGL::SM_MULTI]->CompileAndLink())
748 m_pShader[ShaderMethodGL::SM_MULTI]->Free();
749 m_pShader[ShaderMethodGL::SM_MULTI].reset();
750 CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_multi.glsl - compile and link failed");
753 m_pShader[ShaderMethodGL::SM_FONTS] = std::make_unique<CGLShader>(
754 "gl_shader_vert_simple.glsl", "gl_shader_frag_fonts.glsl", defines);
755 if (!m_pShader[ShaderMethodGL::SM_FONTS]->CompileAndLink())
757 m_pShader[ShaderMethodGL::SM_FONTS]->Free();
758 m_pShader[ShaderMethodGL::SM_FONTS].reset();
759 CLog::Log(LOGERROR, "GUI Shader gl_shader_vert_simple.glsl + gl_shader_frag_fonts.glsl - "
760 "compile and link failed");
763 m_pShader[ShaderMethodGL::SM_FONTS_SHADER_CLIP] =
764 std::make_unique<CGLShader>("gl_shader_vert_clip.glsl", "gl_shader_frag_fonts.glsl", defines);
765 if (!m_pShader[ShaderMethodGL::SM_FONTS_SHADER_CLIP]->CompileAndLink())
767 m_pShader[ShaderMethodGL::SM_FONTS_SHADER_CLIP]->Free();
768 m_pShader[ShaderMethodGL::SM_FONTS_SHADER_CLIP].reset();
769 CLog::Log(LOGERROR, "GUI Shader gl_shader_vert_clip.glsl + gl_shader_frag_fonts.glsl - compile "
770 "and link failed");
773 m_pShader[ShaderMethodGL::SM_TEXTURE_NOBLEND] =
774 std::make_unique<CGLShader>("gl_shader_frag_texture_noblend.glsl", defines);
775 if (!m_pShader[ShaderMethodGL::SM_TEXTURE_NOBLEND]->CompileAndLink())
777 m_pShader[ShaderMethodGL::SM_TEXTURE_NOBLEND]->Free();
778 m_pShader[ShaderMethodGL::SM_TEXTURE_NOBLEND].reset();
779 CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_texture_noblend.glsl - compile and link failed");
782 m_pShader[ShaderMethodGL::SM_MULTI_BLENDCOLOR] =
783 std::make_unique<CGLShader>("gl_shader_frag_multi_blendcolor.glsl", defines);
784 if (!m_pShader[ShaderMethodGL::SM_MULTI_BLENDCOLOR]->CompileAndLink())
786 m_pShader[ShaderMethodGL::SM_MULTI_BLENDCOLOR]->Free();
787 m_pShader[ShaderMethodGL::SM_MULTI_BLENDCOLOR].reset();
788 CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_multi_blendcolor.glsl - compile and link failed");
792 void CRenderSystemGL::ReleaseShaders()
794 if (m_pShader[ShaderMethodGL::SM_DEFAULT])
795 m_pShader[ShaderMethodGL::SM_DEFAULT]->Free();
796 m_pShader[ShaderMethodGL::SM_DEFAULT].reset();
798 if (m_pShader[ShaderMethodGL::SM_TEXTURE])
799 m_pShader[ShaderMethodGL::SM_TEXTURE]->Free();
800 m_pShader[ShaderMethodGL::SM_TEXTURE].reset();
802 if (m_pShader[ShaderMethodGL::SM_TEXTURE_LIM])
803 m_pShader[ShaderMethodGL::SM_TEXTURE_LIM]->Free();
804 m_pShader[ShaderMethodGL::SM_TEXTURE_LIM].reset();
806 if (m_pShader[ShaderMethodGL::SM_MULTI])
807 m_pShader[ShaderMethodGL::SM_MULTI]->Free();
808 m_pShader[ShaderMethodGL::SM_MULTI].reset();
810 if (m_pShader[ShaderMethodGL::SM_FONTS])
811 m_pShader[ShaderMethodGL::SM_FONTS]->Free();
812 m_pShader[ShaderMethodGL::SM_FONTS].reset();
814 if (m_pShader[ShaderMethodGL::SM_FONTS_SHADER_CLIP])
815 m_pShader[ShaderMethodGL::SM_FONTS_SHADER_CLIP]->Free();
816 m_pShader[ShaderMethodGL::SM_FONTS_SHADER_CLIP].reset();
818 if (m_pShader[ShaderMethodGL::SM_TEXTURE_NOBLEND])
819 m_pShader[ShaderMethodGL::SM_TEXTURE_NOBLEND]->Free();
820 m_pShader[ShaderMethodGL::SM_TEXTURE_NOBLEND].reset();
822 if (m_pShader[ShaderMethodGL::SM_MULTI_BLENDCOLOR])
823 m_pShader[ShaderMethodGL::SM_MULTI_BLENDCOLOR]->Free();
824 m_pShader[ShaderMethodGL::SM_MULTI_BLENDCOLOR].reset();
827 void CRenderSystemGL::EnableShader(ShaderMethodGL method)
829 m_method = method;
830 if (m_pShader[m_method])
832 m_pShader[m_method]->Enable();
834 else
836 CLog::Log(LOGERROR, "Invalid GUI Shader selected {}", method);
840 void CRenderSystemGL::DisableShader()
842 if (m_pShader[m_method])
844 m_pShader[m_method]->Disable();
846 m_method = ShaderMethodGL::SM_DEFAULT;
849 GLint CRenderSystemGL::ShaderGetPos()
851 if (m_pShader[m_method])
852 return m_pShader[m_method]->GetPosLoc();
854 return -1;
857 GLint CRenderSystemGL::ShaderGetCol()
859 if (m_pShader[m_method])
860 return m_pShader[m_method]->GetColLoc();
862 return -1;
865 GLint CRenderSystemGL::ShaderGetCoord0()
867 if (m_pShader[m_method])
868 return m_pShader[m_method]->GetCord0Loc();
870 return -1;
873 GLint CRenderSystemGL::ShaderGetCoord1()
875 if (m_pShader[m_method])
876 return m_pShader[m_method]->GetCord1Loc();
878 return -1;
881 GLint CRenderSystemGL::ShaderGetDepth()
883 if (m_pShader[m_method])
884 return m_pShader[m_method]->GetDepthLoc();
886 return -1;
889 GLint CRenderSystemGL::ShaderGetUniCol()
891 if (m_pShader[m_method])
892 return m_pShader[m_method]->GetUniColLoc();
894 return -1;
897 GLint CRenderSystemGL::ShaderGetModel()
899 if (m_pShader[m_method])
900 return m_pShader[m_method]->GetModelLoc();
902 return -1;
905 GLint CRenderSystemGL::ShaderGetMatrix()
907 if (m_pShader[m_method])
908 return m_pShader[m_method]->GetMatrixLoc();
910 return -1;
913 GLint CRenderSystemGL::ShaderGetClip()
915 if (m_pShader[m_method])
916 return m_pShader[m_method]->GetShaderClipLoc();
918 return -1;
921 GLint CRenderSystemGL::ShaderGetCoordStep()
923 if (m_pShader[m_method])
924 return m_pShader[m_method]->GetShaderCoordStepLoc();
926 return -1;
929 std::string CRenderSystemGL::GetShaderPath(const std::string &filename)
931 std::string path = "GL/1.2/";
933 if (m_glslMajor >= 4)
935 std::string file = "special://xbmc/system/shaders/GL/4.0/" + filename;
936 const CURL pathToUrl(file);
937 if (CFileUtils::Exists(pathToUrl.Get()))
938 return "GL/4.0/";
940 if (m_glslMajor >= 2 || (m_glslMajor == 1 && m_glslMinor >= 50))
941 path = "GL/1.5/";
943 return path;