Merge pull request #24470 from fuzzard/release_20.3
[xbmc.git] / xbmc / rendering / gles / GLESShader.cpp
blob3964f4ba47e916de54dd7c09b88d953d12761be2
1 /*
2 * Copyright (C) 2005-2018 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 "GLESShader.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 CGLESShader::CGLESShader(const char* shader, const std::string& prefix)
21 m_proj = nullptr;
22 m_model = nullptr;
23 m_clipPossible = false;
25 VertexShader()->LoadSource("gles_shader.vert");
26 PixelShader()->LoadSource(shader, prefix);
29 CGLESShader::CGLESShader(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 CGLESShader::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");
47 m_hField = glGetUniformLocation(ProgramHandle(), "m_field");
48 m_hStep = glGetUniformLocation(ProgramHandle(), "m_step");
49 m_hContrast = glGetUniformLocation(ProgramHandle(), "m_contrast");
50 m_hBrightness = glGetUniformLocation(ProgramHandle(), "m_brightness");
52 // Variables passed directly to the Vertex shader
53 m_hProj = glGetUniformLocation(ProgramHandle(), "m_proj");
54 m_hModel = glGetUniformLocation(ProgramHandle(), "m_model");
55 m_hCoord0Matrix = glGetUniformLocation(ProgramHandle(), "m_coord0Matrix");
57 // Vertex attributes
58 m_hPos = glGetAttribLocation(ProgramHandle(), "m_attrpos");
59 m_hCol = glGetAttribLocation(ProgramHandle(), "m_attrcol");
60 m_hCord0 = glGetAttribLocation(ProgramHandle(), "m_attrcord0");
61 m_hCord1 = glGetAttribLocation(ProgramHandle(), "m_attrcord1");
63 // It's okay to do this only one time. Textures units never change.
64 glUseProgram( ProgramHandle() );
65 glUniform1i(m_hTex0, 0);
66 glUniform1i(m_hTex1, 1);
67 glUniform4f(m_hUniCol, 1.0, 1.0, 1.0, 1.0);
69 const float identity[16] = {
70 1.0f, 0.0f, 0.0f, 0.0f,
71 0.0f, 1.0f, 0.0f, 0.0f,
72 0.0f, 0.0f, 1.0f, 0.0f,
73 0.0f, 0.0f, 0.0f, 1.0f
75 glUniformMatrix4fv(m_hCoord0Matrix, 1, GL_FALSE, identity);
77 glUseProgram( 0 );
80 bool CGLESShader::OnEnabled()
82 // This is called after glUseProgram()
84 const GLfloat *projMatrix = glMatrixProject.Get();
85 const GLfloat *modelMatrix = glMatrixModview.Get();
86 glUniformMatrix4fv(m_hProj, 1, GL_FALSE, projMatrix);
87 glUniformMatrix4fv(m_hModel, 1, GL_FALSE, modelMatrix);
89 const TransformMatrix &guiMatrix = CServiceBroker::GetWinSystem()->GetGfxContext().GetGUIMatrix();
90 CRect viewPort; // absolute positions of corners
91 CServiceBroker::GetRenderSystem()->GetViewPort(viewPort);
93 /* glScissor operates in window coordinates. In order that we can use it to
94 * perform clipping, we must ensure that there is an independent linear
95 * transformation from the coordinate system used by CGraphicContext::ClipRect
96 * to window coordinates, separately for X and Y (in other words, no
97 * rotation or shear is introduced at any stage). To do, this, we need to
98 * check that zeros are present in the following locations:
100 * GUI matrix:
101 * / * 0 * * \
102 * | 0 * * * |
103 * \ 0 0 * * /
104 * ^ TransformMatrix::TransformX/Y/ZCoord are only ever called with
105 * input z = 0, so this column doesn't matter
106 * Model-view matrix:
107 * / * 0 0 * \
108 * | 0 * 0 * |
109 * | 0 0 * * |
110 * \ * * * * / <- eye w has no influence on window x/y (last column below
111 * is either 0 or ignored)
112 * Projection matrix:
113 * / * 0 0 0 \
114 * | 0 * 0 0 |
115 * | * * * * | <- normalised device coordinate z has no influence on window x/y
116 * \ 0 0 * 0 /
118 * Some of these zeros are not strictly required to ensure this, but they tend
119 * to be zeroed in the common case, so by checking for zeros here, we simplify
120 * the calculation of the window x/y coordinates further down the line.
122 * (Minor detail: we don't quite deal in window coordinates as defined by
123 * OpenGL, because CRenderSystemGLES::SetScissors flips the Y axis. But all
124 * that's needed to handle that is an effective negation at the stage where
125 * Y is in normalised device coordinates.)
127 m_clipPossible = guiMatrix.m[0][1] == 0 &&
128 guiMatrix.m[1][0] == 0 &&
129 guiMatrix.m[2][0] == 0 &&
130 guiMatrix.m[2][1] == 0 &&
131 modelMatrix[0+1*4] == 0 &&
132 modelMatrix[0+2*4] == 0 &&
133 modelMatrix[1+0*4] == 0 &&
134 modelMatrix[1+2*4] == 0 &&
135 modelMatrix[2+0*4] == 0 &&
136 modelMatrix[2+1*4] == 0 &&
137 projMatrix[0+1*4] == 0 &&
138 projMatrix[0+2*4] == 0 &&
139 projMatrix[0+3*4] == 0 &&
140 projMatrix[1+0*4] == 0 &&
141 projMatrix[1+2*4] == 0 &&
142 projMatrix[1+3*4] == 0 &&
143 projMatrix[3+0*4] == 0 &&
144 projMatrix[3+1*4] == 0 &&
145 projMatrix[3+3*4] == 0;
147 m_clipXFactor = 0.0;
148 m_clipXOffset = 0.0;
149 m_clipYFactor = 0.0;
150 m_clipYOffset = 0.0;
152 if (m_clipPossible)
154 m_clipXFactor = guiMatrix.m[0][0] * modelMatrix[0+0*4] * projMatrix[0+0*4];
155 m_clipXOffset = (guiMatrix.m[0][3] * modelMatrix[0+0*4] + modelMatrix[0+3*4]) * projMatrix[0+0*4];
156 m_clipYFactor = guiMatrix.m[1][1] * modelMatrix[1+1*4] * projMatrix[1+1*4];
157 m_clipYOffset = (guiMatrix.m[1][3] * modelMatrix[1+1*4] + modelMatrix[1+3*4]) * projMatrix[1+1*4];
158 float clipW = (guiMatrix.m[2][3] * modelMatrix[2+2*4] + modelMatrix[2+3*4]) * projMatrix[3+2*4];
159 float xMult = (viewPort.x2 - viewPort.x1) / (2 * clipW);
160 float yMult = (viewPort.y1 - viewPort.y2) / (2 * clipW); // correct for inverted window coordinate scheme
161 m_clipXFactor = m_clipXFactor * xMult;
162 m_clipXOffset = m_clipXOffset * xMult + (viewPort.x2 + viewPort.x1) / 2;
163 m_clipYFactor = m_clipYFactor * yMult;
164 m_clipYOffset = m_clipYOffset * yMult + (viewPort.y2 + viewPort.y1) / 2;
167 glUniform1f(m_hBrightness, 0.0f);
168 glUniform1f(m_hContrast, 1.0f);
170 return true;
173 void CGLESShader::Free()
175 // Do Cleanup here
176 CGLSLShaderProgram::Free();