Merge pull request #26117 from notspiff/infoscanner_inforet_enum_class
[xbmc.git] / xbmc / rendering / gl / GLShader.cpp
bloba67601e77ce3593563fbabd100f365247bb5a7d1
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 "GLShader.h"
11 #include "ServiceBroker.h"
12 #include "rendering/MatrixGL.h"
13 #include "rendering/RenderSystem.h"
14 #include "utils/log.h"
15 #include "windowing/GraphicContext.h"
17 using namespace Shaders;
19 CGLShader::CGLShader(const char* shader, const std::string& prefix)
21 m_proj = nullptr;
22 m_model = nullptr;
23 m_clipPossible = false;
25 VertexShader()->LoadSource("gl_shader_vert.glsl");
26 PixelShader()->LoadSource(shader, prefix);
29 CGLShader::CGLShader(const char* vshader, const char* fshader, const std::string& prefix)
31 m_proj = nullptr;
32 m_model = nullptr;
33 m_clipPossible = false;
35 VertexShader()->LoadSource(vshader, prefix);
36 PixelShader()->LoadSource(fshader, prefix);
39 void CGLShader::OnCompiledAndLinked()
41 // This is called after CompileAndLink()
43 // Variables passed directly to the Fragment shader
44 m_hTex0 = glGetUniformLocation(ProgramHandle(), "m_samp0");
45 m_hTex1 = glGetUniformLocation(ProgramHandle(), "m_samp1");
46 m_hUniCol = glGetUniformLocation(ProgramHandle(), "m_unicol");
48 // Variables passed directly to the Vertex shader
49 m_hProj = glGetUniformLocation(ProgramHandle(), "m_proj");
50 m_hModel = glGetUniformLocation(ProgramHandle(), "m_model");
51 m_hMatrix = glGetUniformLocation(ProgramHandle(), "m_matrix");
52 m_hShaderClip = glGetUniformLocation(ProgramHandle(), "m_shaderClip");
53 m_hCoordStep = glGetUniformLocation(ProgramHandle(), "m_cordStep");
54 m_hDepth = glGetUniformLocation(ProgramHandle(), "m_depth");
56 // Vertex attributes
57 m_hPos = glGetAttribLocation(ProgramHandle(), "m_attrpos");
58 m_hCol = glGetAttribLocation(ProgramHandle(), "m_attrcol");
59 m_hCord0 = glGetAttribLocation(ProgramHandle(), "m_attrcord0");
60 m_hCord1 = glGetAttribLocation(ProgramHandle(), "m_attrcord1");
62 // It's okay to do this only one time. Textures units never change.
63 glUseProgram(ProgramHandle());
64 glUniform1i(m_hTex0, 0);
65 glUniform1i(m_hTex1, 1);
66 glUniform4f(m_hUniCol, 1.0, 1.0, 1.0, 1.0);
68 glUseProgram(0);
71 bool CGLShader::OnEnabled()
73 // This is called after glUseProgram()
75 const GLfloat *projMatrix = glMatrixProject.Get();
76 const GLfloat *modelMatrix = glMatrixModview.Get();
77 glUniformMatrix4fv(m_hProj, 1, GL_FALSE, projMatrix);
78 glUniformMatrix4fv(m_hModel, 1, GL_FALSE, modelMatrix);
80 const TransformMatrix &guiMatrix = CServiceBroker::GetWinSystem()->GetGfxContext().GetGUIMatrix();
81 CRect viewPort; // absolute positions of corners
82 CServiceBroker::GetRenderSystem()->GetViewPort(viewPort);
84 /* glScissor operates in window coordinates. In order that we can use it to
85 * perform clipping, we must ensure that there is an independent linear
86 * transformation from the coordinate system used by CGraphicContext::ClipRect
87 * to window coordinates, separately for X and Y (in other words, no
88 * rotation or shear is introduced at any stage). To do, this, we need to
89 * check that zeros are present in the following locations:
91 * GUI matrix:
92 * / * 0 * * \
93 * | 0 * * * |
94 * \ 0 0 * * /
95 * ^ TransformMatrix::TransformX/Y/ZCoord are only ever called with
96 * input z = 0, so this column doesn't matter
97 * Model-view matrix:
98 * / * 0 0 * \
99 * | 0 * 0 * |
100 * | 0 0 * * |
101 * \ * * * * / <- eye w has no influence on window x/y (last column below
102 * is either 0 or ignored)
103 * Projection matrix:
104 * / * 0 0 0 \
105 * | 0 * 0 0 |
106 * | * * * * | <- normalised device coordinate z has no influence on window x/y
107 * \ 0 0 * 0 /
109 * Some of these zeros are not strictly required to ensure this, but they tend
110 * to be zeroed in the common case, so by checking for zeros here, we simplify
111 * the calculation of the window x/y coordinates further down the line.
113 * (Minor detail: we don't quite deal in window coordinates as defined by
114 * OpenGL, because CRenderSystemGLES::SetScissors flips the Y axis. But all
115 * that's needed to handle that is an effective negation at the stage where
116 * Y is in normalised device coordinates.)
118 m_clipPossible = guiMatrix.m[0][1] == 0 &&
119 guiMatrix.m[1][0] == 0 &&
120 guiMatrix.m[2][0] == 0 &&
121 guiMatrix.m[2][1] == 0 &&
122 modelMatrix[0+1*4] == 0 &&
123 modelMatrix[0+2*4] == 0 &&
124 modelMatrix[1+0*4] == 0 &&
125 modelMatrix[1+2*4] == 0 &&
126 modelMatrix[2+0*4] == 0 &&
127 modelMatrix[2+1*4] == 0 &&
128 projMatrix[0+1*4] == 0 &&
129 projMatrix[0+2*4] == 0 &&
130 projMatrix[0+3*4] == 0 &&
131 projMatrix[1+0*4] == 0 &&
132 projMatrix[1+2*4] == 0 &&
133 projMatrix[1+3*4] == 0 &&
134 projMatrix[3+0*4] == 0 &&
135 projMatrix[3+1*4] == 0 &&
136 projMatrix[3+3*4] == 0;
138 m_clipXFactor = 0.0;
139 m_clipXOffset = 0.0;
140 m_clipYFactor = 0.0;
141 m_clipYOffset = 0.0;
143 if (m_clipPossible)
145 m_clipXFactor = guiMatrix.m[0][0] * modelMatrix[0+0*4] * projMatrix[0+0*4];
146 m_clipXOffset = (guiMatrix.m[0][3] * modelMatrix[0+0*4] + modelMatrix[0+3*4]) * projMatrix[0+0*4];
147 m_clipYFactor = guiMatrix.m[1][1] * modelMatrix[1+1*4] * projMatrix[1+1*4];
148 m_clipYOffset = (guiMatrix.m[1][3] * modelMatrix[1+1*4] + modelMatrix[1+3*4]) * projMatrix[1+1*4];
149 float clipW = (guiMatrix.m[2][3] * modelMatrix[2+2*4] + modelMatrix[2+3*4]) * projMatrix[3+2*4];
150 float xMult = (viewPort.x2 - viewPort.x1) / (2 * clipW);
151 float yMult = (viewPort.y1 - viewPort.y2) / (2 * clipW); // correct for inverted window coordinate scheme
152 m_clipXFactor = m_clipXFactor * xMult;
153 m_clipXOffset = m_clipXOffset * xMult + (viewPort.x2 + viewPort.x1) / 2;
154 m_clipYFactor = m_clipYFactor * yMult;
155 m_clipYOffset = m_clipYOffset * yMult + (viewPort.y2 + viewPort.y1) / 2;
158 return true;
161 void CGLShader::Free()
163 // Do Cleanup here
164 CGLSLShaderProgram::Free();