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