diff options
Diffstat (limited to 'xbmc/rendering/gles/GLESShader.cpp')
-rw-r--r-- | xbmc/rendering/gles/GLESShader.cpp | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/xbmc/rendering/gles/GLESShader.cpp b/xbmc/rendering/gles/GLESShader.cpp new file mode 100644 index 0000000..3964f4b --- /dev/null +++ b/xbmc/rendering/gles/GLESShader.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2005-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GLESShader.h" + +#include "ServiceBroker.h" +#include "rendering/MatrixGL.h" +#include "rendering/RenderSystem.h" +#include "utils/log.h" +#include "windowing/GraphicContext.h" + +using namespace Shaders; + +CGLESShader::CGLESShader(const char* shader, const std::string& prefix) +{ + m_proj = nullptr; + m_model = nullptr; + m_clipPossible = false; + + VertexShader()->LoadSource("gles_shader.vert"); + PixelShader()->LoadSource(shader, prefix); +} + +CGLESShader::CGLESShader(const char* vshader, const char* fshader, const std::string& prefix) +{ + m_proj = nullptr; + m_model = nullptr; + m_clipPossible = false; + + VertexShader()->LoadSource(vshader, prefix); + PixelShader()->LoadSource(fshader, prefix); +} + +void CGLESShader::OnCompiledAndLinked() +{ + // This is called after CompileAndLink() + + // Variables passed directly to the Fragment shader + m_hTex0 = glGetUniformLocation(ProgramHandle(), "m_samp0"); + m_hTex1 = glGetUniformLocation(ProgramHandle(), "m_samp1"); + m_hUniCol = glGetUniformLocation(ProgramHandle(), "m_unicol"); + m_hField = glGetUniformLocation(ProgramHandle(), "m_field"); + m_hStep = glGetUniformLocation(ProgramHandle(), "m_step"); + m_hContrast = glGetUniformLocation(ProgramHandle(), "m_contrast"); + m_hBrightness = glGetUniformLocation(ProgramHandle(), "m_brightness"); + + // Variables passed directly to the Vertex shader + m_hProj = glGetUniformLocation(ProgramHandle(), "m_proj"); + m_hModel = glGetUniformLocation(ProgramHandle(), "m_model"); + m_hCoord0Matrix = glGetUniformLocation(ProgramHandle(), "m_coord0Matrix"); + + // Vertex attributes + m_hPos = glGetAttribLocation(ProgramHandle(), "m_attrpos"); + m_hCol = glGetAttribLocation(ProgramHandle(), "m_attrcol"); + m_hCord0 = glGetAttribLocation(ProgramHandle(), "m_attrcord0"); + m_hCord1 = glGetAttribLocation(ProgramHandle(), "m_attrcord1"); + + // It's okay to do this only one time. Textures units never change. + glUseProgram( ProgramHandle() ); + glUniform1i(m_hTex0, 0); + glUniform1i(m_hTex1, 1); + glUniform4f(m_hUniCol, 1.0, 1.0, 1.0, 1.0); + + const float identity[16] = { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + glUniformMatrix4fv(m_hCoord0Matrix, 1, GL_FALSE, identity); + + glUseProgram( 0 ); +} + +bool CGLESShader::OnEnabled() +{ + // This is called after glUseProgram() + + const GLfloat *projMatrix = glMatrixProject.Get(); + const GLfloat *modelMatrix = glMatrixModview.Get(); + glUniformMatrix4fv(m_hProj, 1, GL_FALSE, projMatrix); + glUniformMatrix4fv(m_hModel, 1, GL_FALSE, modelMatrix); + + const TransformMatrix &guiMatrix = CServiceBroker::GetWinSystem()->GetGfxContext().GetGUIMatrix(); + CRect viewPort; // absolute positions of corners + CServiceBroker::GetRenderSystem()->GetViewPort(viewPort); + + /* glScissor operates in window coordinates. In order that we can use it to + * perform clipping, we must ensure that there is an independent linear + * transformation from the coordinate system used by CGraphicContext::ClipRect + * to window coordinates, separately for X and Y (in other words, no + * rotation or shear is introduced at any stage). To do, this, we need to + * check that zeros are present in the following locations: + * + * GUI matrix: + * / * 0 * * \ + * | 0 * * * | + * \ 0 0 * * / + * ^ TransformMatrix::TransformX/Y/ZCoord are only ever called with + * input z = 0, so this column doesn't matter + * Model-view matrix: + * / * 0 0 * \ + * | 0 * 0 * | + * | 0 0 * * | + * \ * * * * / <- eye w has no influence on window x/y (last column below + * is either 0 or ignored) + * Projection matrix: + * / * 0 0 0 \ + * | 0 * 0 0 | + * | * * * * | <- normalised device coordinate z has no influence on window x/y + * \ 0 0 * 0 / + * + * Some of these zeros are not strictly required to ensure this, but they tend + * to be zeroed in the common case, so by checking for zeros here, we simplify + * the calculation of the window x/y coordinates further down the line. + * + * (Minor detail: we don't quite deal in window coordinates as defined by + * OpenGL, because CRenderSystemGLES::SetScissors flips the Y axis. But all + * that's needed to handle that is an effective negation at the stage where + * Y is in normalised device coordinates.) + */ + m_clipPossible = guiMatrix.m[0][1] == 0 && + guiMatrix.m[1][0] == 0 && + guiMatrix.m[2][0] == 0 && + guiMatrix.m[2][1] == 0 && + modelMatrix[0+1*4] == 0 && + modelMatrix[0+2*4] == 0 && + modelMatrix[1+0*4] == 0 && + modelMatrix[1+2*4] == 0 && + modelMatrix[2+0*4] == 0 && + modelMatrix[2+1*4] == 0 && + projMatrix[0+1*4] == 0 && + projMatrix[0+2*4] == 0 && + projMatrix[0+3*4] == 0 && + projMatrix[1+0*4] == 0 && + projMatrix[1+2*4] == 0 && + projMatrix[1+3*4] == 0 && + projMatrix[3+0*4] == 0 && + projMatrix[3+1*4] == 0 && + projMatrix[3+3*4] == 0; + + m_clipXFactor = 0.0; + m_clipXOffset = 0.0; + m_clipYFactor = 0.0; + m_clipYOffset = 0.0; + + if (m_clipPossible) + { + m_clipXFactor = guiMatrix.m[0][0] * modelMatrix[0+0*4] * projMatrix[0+0*4]; + m_clipXOffset = (guiMatrix.m[0][3] * modelMatrix[0+0*4] + modelMatrix[0+3*4]) * projMatrix[0+0*4]; + m_clipYFactor = guiMatrix.m[1][1] * modelMatrix[1+1*4] * projMatrix[1+1*4]; + m_clipYOffset = (guiMatrix.m[1][3] * modelMatrix[1+1*4] + modelMatrix[1+3*4]) * projMatrix[1+1*4]; + float clipW = (guiMatrix.m[2][3] * modelMatrix[2+2*4] + modelMatrix[2+3*4]) * projMatrix[3+2*4]; + float xMult = (viewPort.x2 - viewPort.x1) / (2 * clipW); + float yMult = (viewPort.y1 - viewPort.y2) / (2 * clipW); // correct for inverted window coordinate scheme + m_clipXFactor = m_clipXFactor * xMult; + m_clipXOffset = m_clipXOffset * xMult + (viewPort.x2 + viewPort.x1) / 2; + m_clipYFactor = m_clipYFactor * yMult; + m_clipYOffset = m_clipYOffset * yMult + (viewPort.y2 + viewPort.y1) / 2; + } + + glUniform1f(m_hBrightness, 0.0f); + glUniform1f(m_hContrast, 1.0f); + + return true; +} + +void CGLESShader::Free() +{ + // Do Cleanup here + CGLSLShaderProgram::Free(); +} + |