1 /*
2  *  Copyright (C) 2005-2018 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 #include "RenderSystemGL.h"
10 
11 #include "filesystem/File.h"
12 #include "rendering/MatrixGL.h"
13 #include "settings/AdvancedSettings.h"
14 #include "settings/DisplaySettings.h"
15 #include "utils/GLUtils.h"
16 #include "utils/MathUtils.h"
17 #include "utils/StringUtils.h"
18 #include "utils/SystemInfo.h"
19 #include "utils/TimeUtils.h"
20 #include "utils/XTimeUtils.h"
21 #include "utils/log.h"
22 #include "windowing/GraphicContext.h"
23 
CRenderSystemGL()24 CRenderSystemGL::CRenderSystemGL() : CRenderSystemBase()
25 {
26 }
27 
28 CRenderSystemGL::~CRenderSystemGL() = default;
29 
InitRenderSystem()30 bool CRenderSystemGL::InitRenderSystem()
31 {
32   m_bVSync = false;
33   m_bVsyncInit = false;
34   m_maxTextureSize = 2048;
35 
36   // Get the GL version number
37   m_RenderVersionMajor = 0;
38   m_RenderVersionMinor = 0;
39   const char* ver = (const char*)glGetString(GL_VERSION);
40   if (ver != 0)
41   {
42     sscanf(ver, "%d.%d", &m_RenderVersionMajor, &m_RenderVersionMinor);
43     m_RenderVersion = ver;
44   }
45 
46   CLog::Log(LOGINFO, "CRenderSystemGL::%s - Version: %s, Major: %d, Minor: %d", __FUNCTION__, ver,
47             m_RenderVersionMajor, m_RenderVersionMinor);
48 
49   m_RenderExtensions  = " ";
50   if (m_RenderVersionMajor > 3 ||
51       (m_RenderVersionMajor == 3 && m_RenderVersionMinor >= 2))
52   {
53     GLint n = 0;
54     glGetIntegerv(GL_NUM_EXTENSIONS, &n);
55     if (n > 0)
56     {
57       GLint i;
58       for (i = 0; i < n; i++)
59       {
60         m_RenderExtensions += (const char*) glGetStringi(GL_EXTENSIONS, i);
61         m_RenderExtensions += " ";
62       }
63     }
64   }
65   else
66   {
67     auto extensions = (const char*) glGetString(GL_EXTENSIONS);
68     if (extensions)
69     {
70       m_RenderExtensions += extensions;
71     }
72   }
73   m_RenderExtensions += " ";
74 
75   ver = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
76   if (ver)
77   {
78     sscanf(ver, "%d.%d", &m_glslMajor, &m_glslMinor);
79   }
80   else
81   {
82     m_glslMajor = 1;
83     m_glslMinor = 0;
84   }
85 
86   LogGraphicsInfo();
87 
88   // Get our driver vendor and renderer
89   const char* tmpVendor = (const char*) glGetString(GL_VENDOR);
90   m_RenderVendor.clear();
91   if (tmpVendor != NULL)
92     m_RenderVendor = tmpVendor;
93 
94   const char* tmpRenderer = (const char*) glGetString(GL_RENDERER);
95   m_RenderRenderer.clear();
96   if (tmpRenderer != NULL)
97     m_RenderRenderer = tmpRenderer;
98 
99   m_bRenderCreated = true;
100 
101   if (m_RenderVersionMajor > 3 ||
102       (m_RenderVersionMajor == 3 && m_RenderVersionMinor >= 2))
103   {
104     glGenVertexArrays(1, &m_vertexArray);
105     glBindVertexArray(m_vertexArray);
106   }
107 
108   InitialiseShaders();
109 
110   return true;
111 }
112 
ResetRenderSystem(int width,int height)113 bool CRenderSystemGL::ResetRenderSystem(int width, int height)
114 {
115   if (!m_bRenderCreated)
116     return false;
117 
118   m_width = width;
119   m_height = height;
120 
121   if (m_RenderVersionMajor > 3 ||
122       (m_RenderVersionMajor == 3 && m_RenderVersionMinor >= 2))
123   {
124     glBindVertexArray(0);
125     glDeleteVertexArrays(1, &m_vertexArray);
126     glGenVertexArrays(1, &m_vertexArray);
127     glBindVertexArray(m_vertexArray);
128   }
129 
130   ReleaseShaders();
131   InitialiseShaders();
132 
133   glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
134 
135   CalculateMaxTexturesize();
136 
137   CRect rect( 0, 0, width, height );
138   SetViewPort( rect );
139 
140   glEnable(GL_SCISSOR_TEST);
141 
142   glMatrixProject.Clear();
143   glMatrixProject->LoadIdentity();
144   glMatrixProject->Ortho(0.0f, width-1, height-1, 0.0f, -1.0f, 1.0f);
145   glMatrixProject.Load();
146 
147   glMatrixModview.Clear();
148   glMatrixModview->LoadIdentity();
149   glMatrixModview.Load();
150 
151   glMatrixTexture.Clear();
152   glMatrixTexture->LoadIdentity();
153   glMatrixTexture.Load();
154 
155   if (IsExtSupported("GL_ARB_multitexture"))
156   {
157     //clear error flags
158     ResetGLErrors();
159 
160     GLint maxtex;
161     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxtex);
162 
163     //some sanity checks
164     GLenum error = glGetError();
165     if (error != GL_NO_ERROR)
166     {
167       CLog::Log(LOGERROR, "ResetRenderSystem() GL_MAX_TEXTURE_IMAGE_UNITS returned error %i", (int)error);
168       maxtex = 3;
169     }
170     else if (maxtex < 1 || maxtex > 32)
171     {
172       CLog::Log(LOGERROR, "ResetRenderSystem() GL_MAX_TEXTURE_IMAGE_UNITS returned invalid value %i", (int)maxtex);
173       maxtex = 3;
174     }
175 
176     //reset texture matrix for all textures
177     for (GLint i = 0; i < maxtex; i++)
178     {
179       glActiveTexture(GL_TEXTURE0 + i);
180       glMatrixTexture.Load();
181     }
182     glActiveTexture(GL_TEXTURE0);
183   }
184 
185   glBlendFunc(GL_SRC_ALPHA, GL_ONE);
186   glEnable(GL_BLEND);          // Turn Blending On
187   glDisable(GL_DEPTH_TEST);
188 
189   return true;
190 }
191 
DestroyRenderSystem()192 bool CRenderSystemGL::DestroyRenderSystem()
193 {
194   if (m_vertexArray != GL_NONE)
195   {
196     glDeleteVertexArrays(1, &m_vertexArray);
197   }
198 
199   ReleaseShaders();
200   m_bRenderCreated = false;
201 
202   return true;
203 }
204 
BeginRender()205 bool CRenderSystemGL::BeginRender()
206 {
207   if (!m_bRenderCreated)
208     return false;
209 
210   bool useLimited = CServiceBroker::GetWinSystem()->UseLimitedColor();
211 
212   if (m_limitedColorRange != useLimited)
213   {
214     ReleaseShaders();
215     InitialiseShaders();
216   }
217 
218   m_limitedColorRange = useLimited;
219   return true;
220 }
221 
EndRender()222 bool CRenderSystemGL::EndRender()
223 {
224   if (!m_bRenderCreated)
225     return false;
226 
227   return true;
228 }
229 
ClearBuffers(UTILS::Color color)230 bool CRenderSystemGL::ClearBuffers(UTILS::Color color)
231 {
232   if (!m_bRenderCreated)
233     return false;
234 
235   /* clear is not affected by stipple pattern, so we can only clear on first frame */
236   if(m_stereoMode == RENDER_STEREO_MODE_INTERLACED && m_stereoView == RENDER_STEREO_VIEW_RIGHT)
237     return true;
238 
239   float r = GET_R(color) / 255.0f;
240   float g = GET_G(color) / 255.0f;
241   float b = GET_B(color) / 255.0f;
242   float a = GET_A(color) / 255.0f;
243 
244   glClearColor(r, g, b, a);
245 
246   GLbitfield flags = GL_COLOR_BUFFER_BIT;
247   glClear(flags);
248 
249   return true;
250 }
251 
IsExtSupported(const char * extension) const252 bool CRenderSystemGL::IsExtSupported(const char* extension) const
253 {
254   if (m_RenderVersionMajor > 3 ||
255       (m_RenderVersionMajor == 3 && m_RenderVersionMinor >= 2))
256   {
257     if (strcmp( extension, "GL_EXT_framebuffer_object") == 0)
258     {
259       return true;
260     }
261     if (strcmp( extension, "GL_ARB_texture_non_power_of_two") == 0)
262     {
263       return true;
264     }
265   }
266 
267   std::string name;
268   name  = " ";
269   name += extension;
270   name += " ";
271 
272   return m_RenderExtensions.find(name) != std::string::npos;
273 }
274 
SupportsNPOT(bool dxt) const275 bool CRenderSystemGL::SupportsNPOT(bool dxt) const
276 {
277   return true;
278 }
279 
PresentRender(bool rendered,bool videoLayer)280 void CRenderSystemGL::PresentRender(bool rendered, bool videoLayer)
281 {
282   SetVSync(true);
283 
284   if (!m_bRenderCreated)
285     return;
286 
287   PresentRenderImpl(rendered);
288 
289   if (!rendered)
290     KODI::TIME::Sleep(40);
291 }
292 
SetVSync(bool enable)293 void CRenderSystemGL::SetVSync(bool enable)
294 {
295   if (m_bVSync == enable && m_bVsyncInit == true)
296     return;
297 
298   if (!m_bRenderCreated)
299     return;
300 
301   if (enable)
302     CLog::Log(LOGINFO, "GL: Enabling VSYNC");
303   else
304     CLog::Log(LOGINFO, "GL: Disabling VSYNC");
305 
306   m_bVSync = enable;
307   m_bVsyncInit = true;
308 
309   SetVSyncImpl(enable);
310 }
311 
CaptureStateBlock()312 void CRenderSystemGL::CaptureStateBlock()
313 {
314   if (!m_bRenderCreated)
315     return;
316 
317   glMatrixProject.Push();
318   glMatrixModview.Push();
319   glMatrixTexture.Push();
320 
321   glDisable(GL_SCISSOR_TEST); // fixes FBO corruption on Macs
322   glActiveTexture(GL_TEXTURE0);
323 }
324 
ApplyStateBlock()325 void CRenderSystemGL::ApplyStateBlock()
326 {
327   if (!m_bRenderCreated)
328     return;
329 
330   glBindVertexArray(m_vertexArray);
331 
332   glViewport(m_viewPort[0], m_viewPort[1], m_viewPort[2], m_viewPort[3]);
333 
334   glMatrixProject.PopLoad();
335   glMatrixModview.PopLoad();
336   glMatrixTexture.PopLoad();
337 
338   glActiveTexture(GL_TEXTURE0);
339   glEnable(GL_BLEND);
340   glEnable(GL_SCISSOR_TEST);
341 }
342 
SetCameraPosition(const CPoint & camera,int screenWidth,int screenHeight,float stereoFactor)343 void CRenderSystemGL::SetCameraPosition(const CPoint &camera, int screenWidth, int screenHeight, float stereoFactor)
344 {
345   if (!m_bRenderCreated)
346     return;
347 
348   CPoint offset = camera - CPoint(screenWidth*0.5f, screenHeight*0.5f);
349 
350 
351   float w = (float)m_viewPort[2]*0.5f;
352   float h = (float)m_viewPort[3]*0.5f;
353 
354   glMatrixModview->LoadIdentity();
355   glMatrixModview->Translatef(-(w + offset.x - stereoFactor), +(h + offset.y), 0);
356   glMatrixModview->LookAt(0.0, 0.0, -2.0*h, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0);
357   glMatrixModview.Load();
358 
359   glMatrixProject->LoadIdentity();
360   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);
361   glMatrixProject.Load();
362 }
363 
Project(float & x,float & y,float & z)364 void CRenderSystemGL::Project(float &x, float &y, float &z)
365 {
366   GLfloat coordX, coordY, coordZ;
367   if (CMatrixGL::Project(x, y, z, glMatrixModview.Get(), glMatrixProject.Get(), m_viewPort, &coordX, &coordY, &coordZ))
368   {
369     x = coordX;
370     y = (float)(m_viewPort[1] + m_viewPort[3] - coordY);
371     z = 0;
372   }
373 }
374 
CalculateMaxTexturesize()375 void CRenderSystemGL::CalculateMaxTexturesize()
376 {
377   GLint width = 256;
378 
379   // reset any previous GL errors
380   ResetGLErrors();
381 
382   // max out at 2^(8+8)
383   for (int i = 0 ; i<8 ; i++)
384   {
385     glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, width, width, 0, GL_BGRA,
386                  GL_UNSIGNED_BYTE, NULL);
387     glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
388                              &width);
389 
390     // GMA950 on OS X sets error instead
391     if (width == 0 || (glGetError() != GL_NO_ERROR) )
392       break;
393 
394     m_maxTextureSize = width;
395     width *= 2;
396     if (width > 65536) // have an upper limit in case driver acts stupid
397     {
398       CLog::Log(LOGERROR, "GL: Could not determine maximum texture width, falling back to 2048");
399       m_maxTextureSize = 2048;
400       break;
401     }
402   }
403 
404   CLog::Log(LOGINFO, "GL: Maximum texture width: %u", m_maxTextureSize);
405 }
406 
GetViewPort(CRect & viewPort)407 void CRenderSystemGL::GetViewPort(CRect& viewPort)
408 {
409   if (!m_bRenderCreated)
410     return;
411 
412   viewPort.x1 = m_viewPort[0];
413   viewPort.y1 = m_height - m_viewPort[1] - m_viewPort[3];
414   viewPort.x2 = m_viewPort[0] + m_viewPort[2];
415   viewPort.y2 = viewPort.y1 + m_viewPort[3];
416 }
417 
SetViewPort(const CRect & viewPort)418 void CRenderSystemGL::SetViewPort(const CRect& viewPort)
419 {
420   if (!m_bRenderCreated)
421     return;
422 
423   glScissor((GLint) viewPort.x1, (GLint) (m_height - viewPort.y1 - viewPort.Height()), (GLsizei) viewPort.Width(), (GLsizei) viewPort.Height());
424   glViewport((GLint) viewPort.x1, (GLint) (m_height - viewPort.y1 - viewPort.Height()), (GLsizei) viewPort.Width(), (GLsizei) viewPort.Height());
425   m_viewPort[0] = viewPort.x1;
426   m_viewPort[1] = m_height - viewPort.y1 - viewPort.Height();
427   m_viewPort[2] = viewPort.Width();
428   m_viewPort[3] = viewPort.Height();
429 }
430 
ScissorsCanEffectClipping()431 bool CRenderSystemGL::ScissorsCanEffectClipping()
432 {
433   if (m_pShader[m_method])
434     return m_pShader[m_method]->HardwareClipIsPossible();
435 
436   return false;
437 }
438 
ClipRectToScissorRect(const CRect & rect)439 CRect CRenderSystemGL::ClipRectToScissorRect(const CRect &rect)
440 {
441   if (!m_pShader[m_method])
442     return CRect();
443   float xFactor = m_pShader[m_method]->GetClipXFactor();
444   float xOffset = m_pShader[m_method]->GetClipXOffset();
445   float yFactor = m_pShader[m_method]->GetClipYFactor();
446   float yOffset = m_pShader[m_method]->GetClipYOffset();
447   return CRect(rect.x1 * xFactor + xOffset,
448                rect.y1 * yFactor + yOffset,
449                rect.x2 * xFactor + xOffset,
450                rect.y2 * yFactor + yOffset);
451 }
452 
SetScissors(const CRect & rect)453 void CRenderSystemGL::SetScissors(const CRect &rect)
454 {
455   if (!m_bRenderCreated)
456     return;
457   GLint x1 = MathUtils::round_int(rect.x1);
458   GLint y1 = MathUtils::round_int(rect.y1);
459   GLint x2 = MathUtils::round_int(rect.x2);
460   GLint y2 = MathUtils::round_int(rect.y2);
461   glScissor(x1, m_height - y2, x2-x1, y2-y1);
462 }
463 
ResetScissors()464 void CRenderSystemGL::ResetScissors()
465 {
466   SetScissors(CRect(0, 0, (float)m_width, (float)m_height));
467 }
468 
GetGLSLVersion(int & major,int & minor)469 void CRenderSystemGL::GetGLSLVersion(int& major, int& minor)
470 {
471   major = m_glslMajor;
472   minor = m_glslMinor;
473 }
474 
ResetGLErrors()475 void CRenderSystemGL::ResetGLErrors()
476 {
477   int count = 0;
478   while (glGetError() != GL_NO_ERROR)
479   {
480     count++;
481     if (count >= 100)
482     {
483       CLog::Log(LOGWARNING, "CRenderSystemGL::ResetGLErrors glGetError didn't return GL_NO_ERROR after %i iterations", count);
484       break;
485     }
486   }
487 }
488 static const GLubyte stipple_3d[] = {
489   0x00, 0x00, 0x00, 0x00,
490   0xFF, 0xFF, 0xFF, 0xFF,
491   0x00, 0x00, 0x00, 0x00,
492   0xFF, 0xFF, 0xFF, 0xFF,
493   0x00, 0x00, 0x00, 0x00,
494   0xFF, 0xFF, 0xFF, 0xFF,
495   0x00, 0x00, 0x00, 0x00,
496   0xFF, 0xFF, 0xFF, 0xFF,
497   0x00, 0x00, 0x00, 0x00,
498   0xFF, 0xFF, 0xFF, 0xFF,
499   0x00, 0x00, 0x00, 0x00,
500   0xFF, 0xFF, 0xFF, 0xFF,
501   0x00, 0x00, 0x00, 0x00,
502   0xFF, 0xFF, 0xFF, 0xFF,
503   0x00, 0x00, 0x00, 0x00,
504   0xFF, 0xFF, 0xFF, 0xFF,
505   0x00, 0x00, 0x00, 0x00,
506   0xFF, 0xFF, 0xFF, 0xFF,
507   0x00, 0x00, 0x00, 0x00,
508   0xFF, 0xFF, 0xFF, 0xFF,
509   0x00, 0x00, 0x00, 0x00,
510   0xFF, 0xFF, 0xFF, 0xFF,
511   0x00, 0x00, 0x00, 0x00,
512   0xFF, 0xFF, 0xFF, 0xFF,
513   0x00, 0x00, 0x00, 0x00,
514   0xFF, 0xFF, 0xFF, 0xFF,
515   0x00, 0x00, 0x00, 0x00,
516   0xFF, 0xFF, 0xFF, 0xFF,
517   0x00, 0x00, 0x00, 0x00,
518   0xFF, 0xFF, 0xFF, 0xFF,
519   0x00, 0x00, 0x00, 0x00,
520   0xFF, 0xFF, 0xFF, 0xFF,
521   0x00, 0x00, 0x00, 0x00,
522 };
523 
SetStereoMode(RENDER_STEREO_MODE mode,RENDER_STEREO_VIEW view)524 void CRenderSystemGL::SetStereoMode(RENDER_STEREO_MODE mode, RENDER_STEREO_VIEW view)
525 {
526   CRenderSystemBase::SetStereoMode(mode, view);
527 
528   glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
529   glDrawBuffer(GL_BACK);
530 
531   if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN)
532   {
533     if(m_stereoView == RENDER_STEREO_VIEW_LEFT)
534       glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
535     else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT)
536       glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
537   }
538   if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA)
539   {
540     if(m_stereoView == RENDER_STEREO_VIEW_LEFT)
541       glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
542     else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT)
543       glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_TRUE);
544   }
545   if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE)
546   {
547     if(m_stereoView == RENDER_STEREO_VIEW_LEFT)
548       glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE);
549     else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT)
550       glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
551   }
552 
553   if(m_stereoMode == RENDER_STEREO_MODE_INTERLACED)
554   {
555     glEnable(GL_POLYGON_STIPPLE);
556     if(m_stereoView == RENDER_STEREO_VIEW_LEFT)
557       glPolygonStipple(stipple_3d);
558     else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT)
559       glPolygonStipple(stipple_3d+4);
560   }
561 
562   if(m_stereoMode == RENDER_STEREO_MODE_HARDWAREBASED)
563   {
564     if(m_stereoView == RENDER_STEREO_VIEW_LEFT)
565       glDrawBuffer(GL_BACK_LEFT);
566     else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT)
567       glDrawBuffer(GL_BACK_RIGHT);
568   }
569 
570 }
571 
SupportsStereo(RENDER_STEREO_MODE mode) const572 bool CRenderSystemGL::SupportsStereo(RENDER_STEREO_MODE mode) const
573 {
574   switch(mode)
575   {
576     case RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN:
577     case RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA:
578     case RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE:
579     case RENDER_STEREO_MODE_INTERLACED:
580       return true;
581     case RENDER_STEREO_MODE_HARDWAREBASED: {
582       //This is called by setting init, at which point GL is not inited
583       //luckily if GL doesn't support this, it will just behave as if
584       //it was not in effect.
585       //GLboolean stereo = GL_FALSE;
586       //glGetBooleanv(GL_STEREO, &stereo);
587       //return stereo == GL_TRUE ? true : false;
588       return true;
589     }
590     default:
591       return CRenderSystemBase::SupportsStereo(mode);
592   }
593 }
594 
595 // -----------------------------------------------------------------------------
596 // shaders
597 // -----------------------------------------------------------------------------
InitialiseShaders()598 void CRenderSystemGL::InitialiseShaders()
599 {
600   std::string defines;
601   m_limitedColorRange = CServiceBroker::GetWinSystem()->UseLimitedColor();
602   if (m_limitedColorRange)
603   {
604     defines += "#define KODI_LIMITED_RANGE 1\n";
605   }
606 
607   m_pShader[SM_DEFAULT].reset(new CGLShader("gl_shader_vert_default.glsl", "gl_shader_frag_default.glsl", defines));
608   if (!m_pShader[SM_DEFAULT]->CompileAndLink())
609   {
610     m_pShader[SM_DEFAULT]->Free();
611     m_pShader[SM_DEFAULT].reset();
612     CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_default.glsl - compile and link failed");
613   }
614 
615   m_pShader[SM_TEXTURE].reset(new CGLShader("gl_shader_frag_texture.glsl", defines));
616   if (!m_pShader[SM_TEXTURE]->CompileAndLink())
617   {
618     m_pShader[SM_TEXTURE]->Free();
619     m_pShader[SM_TEXTURE].reset();
620     CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_texture.glsl - compile and link failed");
621   }
622 
623   m_pShader[SM_TEXTURE_LIM].reset(new CGLShader("gl_shader_frag_texture_lim.glsl", defines));
624   if (!m_pShader[SM_TEXTURE_LIM]->CompileAndLink())
625   {
626     m_pShader[SM_TEXTURE_LIM]->Free();
627     m_pShader[SM_TEXTURE_LIM].reset();
628     CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_texture_lim.glsl - compile and link failed");
629   }
630 
631   m_pShader[SM_MULTI].reset(new CGLShader("gl_shader_frag_multi.glsl", defines));
632   if (!m_pShader[SM_MULTI]->CompileAndLink())
633   {
634     m_pShader[SM_MULTI]->Free();
635     m_pShader[SM_MULTI].reset();
636     CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_multi.glsl - compile and link failed");
637   }
638 
639   m_pShader[SM_FONTS].reset(new CGLShader("gl_shader_frag_fonts.glsl", defines));
640   if (!m_pShader[SM_FONTS]->CompileAndLink())
641   {
642     m_pShader[SM_FONTS]->Free();
643     m_pShader[SM_FONTS].reset();
644     CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_fonts.glsl - compile and link failed");
645   }
646 
647   m_pShader[SM_TEXTURE_NOBLEND].reset(new CGLShader("gl_shader_frag_texture_noblend.glsl", defines));
648   if (!m_pShader[SM_TEXTURE_NOBLEND]->CompileAndLink())
649   {
650     m_pShader[SM_TEXTURE_NOBLEND]->Free();
651     m_pShader[SM_TEXTURE_NOBLEND].reset();
652     CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_texture_noblend.glsl - compile and link failed");
653   }
654 
655   m_pShader[SM_MULTI_BLENDCOLOR].reset(new CGLShader("gl_shader_frag_multi_blendcolor.glsl", defines));
656   if (!m_pShader[SM_MULTI_BLENDCOLOR]->CompileAndLink())
657   {
658     m_pShader[SM_MULTI_BLENDCOLOR]->Free();
659     m_pShader[SM_MULTI_BLENDCOLOR].reset();
660     CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_multi_blendcolor.glsl - compile and link failed");
661   }
662 }
663 
ReleaseShaders()664 void CRenderSystemGL::ReleaseShaders()
665 {
666   if (m_pShader[SM_DEFAULT])
667     m_pShader[SM_DEFAULT]->Free();
668   m_pShader[SM_DEFAULT].reset();
669 
670   if (m_pShader[SM_TEXTURE])
671     m_pShader[SM_TEXTURE]->Free();
672   m_pShader[SM_TEXTURE].reset();
673 
674   if (m_pShader[SM_TEXTURE_LIM])
675     m_pShader[SM_TEXTURE_LIM]->Free();
676   m_pShader[SM_TEXTURE_LIM].reset();
677 
678   if (m_pShader[SM_MULTI])
679     m_pShader[SM_MULTI]->Free();
680   m_pShader[SM_MULTI].reset();
681 
682   if (m_pShader[SM_FONTS])
683     m_pShader[SM_FONTS]->Free();
684   m_pShader[SM_FONTS].reset();
685 
686   if (m_pShader[SM_TEXTURE_NOBLEND])
687     m_pShader[SM_TEXTURE_NOBLEND]->Free();
688   m_pShader[SM_TEXTURE_NOBLEND].reset();
689 
690   if (m_pShader[SM_MULTI_BLENDCOLOR])
691     m_pShader[SM_MULTI_BLENDCOLOR]->Free();
692   m_pShader[SM_MULTI_BLENDCOLOR].reset();
693 }
694 
EnableShader(ESHADERMETHOD method)695 void CRenderSystemGL::EnableShader(ESHADERMETHOD method)
696 {
697   m_method = method;
698   if (m_pShader[m_method])
699   {
700     m_pShader[m_method]->Enable();
701   }
702   else
703   {
704     CLog::Log(LOGERROR, "Invalid GUI Shader selected %d", method);
705   }
706 }
707 
DisableShader()708 void CRenderSystemGL::DisableShader()
709 {
710   if (m_pShader[m_method])
711   {
712     m_pShader[m_method]->Disable();
713   }
714   m_method = SM_DEFAULT;
715 }
716 
ShaderGetPos()717 GLint CRenderSystemGL::ShaderGetPos()
718 {
719   if (m_pShader[m_method])
720     return m_pShader[m_method]->GetPosLoc();
721 
722   return -1;
723 }
724 
ShaderGetCol()725 GLint CRenderSystemGL::ShaderGetCol()
726 {
727   if (m_pShader[m_method])
728     return m_pShader[m_method]->GetColLoc();
729 
730   return -1;
731 }
732 
ShaderGetCoord0()733 GLint CRenderSystemGL::ShaderGetCoord0()
734 {
735   if (m_pShader[m_method])
736     return m_pShader[m_method]->GetCord0Loc();
737 
738   return -1;
739 }
740 
ShaderGetCoord1()741 GLint CRenderSystemGL::ShaderGetCoord1()
742 {
743   if (m_pShader[m_method])
744     return m_pShader[m_method]->GetCord1Loc();
745 
746   return -1;
747 }
748 
ShaderGetUniCol()749 GLint CRenderSystemGL::ShaderGetUniCol()
750 {
751   if (m_pShader[m_method])
752     return m_pShader[m_method]->GetUniColLoc();
753 
754   return -1;
755 }
756 
ShaderGetModel()757 GLint CRenderSystemGL::ShaderGetModel()
758 {
759   if (m_pShader[m_method])
760     return m_pShader[m_method]->GetModelLoc();
761 
762   return -1;
763 }
764 
GetShaderPath(const std::string & filename)765 std::string CRenderSystemGL::GetShaderPath(const std::string &filename)
766 {
767   std::string path = "GL/1.2/";
768 
769   if (m_glslMajor >= 4)
770   {
771     std::string file = "special://xbmc/system/shaders/GL/4.0/" + filename;
772     const CURL pathToUrl(file);
773     if (XFILE::CFile::Exists(pathToUrl))
774       return "GL/4.0/";
775   }
776   if (m_glslMajor >= 2 || (m_glslMajor == 1 && m_glslMinor >= 50))
777     path = "GL/1.5/";
778 
779   return path;
780 }
781