diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /vcl/opengl/program.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vcl/opengl/program.cxx')
-rw-r--r-- | vcl/opengl/program.cxx | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/vcl/opengl/program.cxx b/vcl/opengl/program.cxx new file mode 100644 index 000000000..6557eccf8 --- /dev/null +++ b/vcl/opengl/program.cxx @@ -0,0 +1,390 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <opengl/program.hxx> +#include <opengl/RenderState.hxx> + +#include <vcl/opengl/OpenGLHelper.hxx> +#include <vcl/opengl/OpenGLContext.hxx> + +#include <glm/glm.hpp> +#include <glm/gtc/type_ptr.hpp> +#include <glm/gtc/matrix_transform.hpp> + +OpenGLProgram::OpenGLProgram() : + mnId( 0 ), + mnEnabledAttribs( 0 ), + mnPositionAttrib( SAL_MAX_UINT32 ), + mnTexCoordAttrib( SAL_MAX_UINT32 ), + mnAlphaCoordAttrib( SAL_MAX_UINT32 ), + mnMaskCoordAttrib( SAL_MAX_UINT32 ), + mnExtrusionVectorsAttrib( SAL_MAX_UINT32 ), + mnVertexColorsAttrib( SAL_MAX_UINT32 ), + mbBlending(false), + mfLastWidth(0.0), + mfLastHeight(0.0), + mfLastPixelOffset(0.0) +{ +} + +OpenGLProgram::~OpenGLProgram() +{ + maUniformLocations.clear(); + if( mnId != 0 ) + { + glDeleteProgram( mnId ); + CHECK_GL_ERROR(); + } +} + +bool OpenGLProgram::Load( const OUString& rVertexShader, + const OUString& rFragmentShader, + const OString& preamble, + const OString& rDigest ) +{ + mnId = OpenGLHelper::LoadShaders( rVertexShader, rFragmentShader, preamble, rDigest ); + return ( mnId != 0 ); +} + +void OpenGLProgram::Reuse() +{ + mbBlending = false; +} + +void OpenGLProgram::Use() +{ + if (!mnId) + return; + + glUseProgram(mnId); + CHECK_GL_ERROR(); + Reuse(); +} + +void OpenGLProgram::Clean() +{ + // unbind all textures + for (OpenGLTexture& rTexture : maTextures) + { + rTexture.Unbind(); + } + maTextures.clear(); + + // disable any enabled vertex attrib array + if( mnEnabledAttribs ) + { + for( int i = 0; i < 32; i++ ) + { + if( mnEnabledAttribs & ( 1 << i ) ) + { + glDisableVertexAttribArray( i ); + CHECK_GL_ERROR(); + } + } + mnEnabledAttribs = 0; + } +} + +bool OpenGLProgram::EnableVertexAttrib(GLuint& rAttrib, const OString& rName) +{ + if( rAttrib == SAL_MAX_UINT32 ) + { + GLint aLocation = glGetAttribLocation(mnId, rName.getStr()); + CHECK_GL_ERROR(); + if (aLocation < 0) + return false; + rAttrib = GLuint(aLocation); + } + if( (mnEnabledAttribs & ( 1 << rAttrib )) == 0 ) + { + glEnableVertexAttribArray( rAttrib ); + CHECK_GL_ERROR(); + mnEnabledAttribs |= ( 1 << rAttrib ); + } + return true; +} + +void OpenGLProgram::SetVertexAttrib(GLuint& rAttrib, const OString& rName, GLint nSize, + GLenum eType, GLboolean bNormalized, GLsizei aStride, + const GLvoid* pPointer) +{ + if (EnableVertexAttrib(rAttrib, rName)) + { + glVertexAttribPointer(rAttrib, nSize, eType, bNormalized, aStride, pPointer); + CHECK_GL_ERROR(); + } + else + { + VCL_GL_INFO("Vertex attribute '" << rName << "' doesn't exist in this program (" << mnId << ")"); + } +} + +void OpenGLProgram::SetVertices( const GLvoid* pData ) +{ + SetVertexAttrib(mnPositionAttrib, "position", 2, GL_FLOAT, GL_FALSE, 0, pData); +} + +void OpenGLProgram::SetTextureCoord( const GLvoid* pData ) +{ + SetVertexAttrib(mnTexCoordAttrib, "tex_coord_in", 2, GL_FLOAT, GL_FALSE, 0, pData); +} + +void OpenGLProgram::SetAlphaCoord( const GLvoid* pData ) +{ + SetVertexAttrib(mnAlphaCoordAttrib, "alpha_coord_in", 2, GL_FLOAT, GL_FALSE, 0, pData); +} + +void OpenGLProgram::SetMaskCoord(const GLvoid* pData) +{ + SetVertexAttrib(mnMaskCoordAttrib, "mask_coord_in", 2, GL_FLOAT, GL_FALSE, 0, pData); +} + +void OpenGLProgram::SetExtrusionVectors(const GLvoid* pData) +{ + SetVertexAttrib(mnExtrusionVectorsAttrib, "extrusion_vectors", 3, GL_FLOAT, GL_FALSE, 0, pData); +} + +void OpenGLProgram::SetVertexColors(std::vector<GLubyte>& rColorVector) +{ + SetVertexAttrib(mnVertexColorsAttrib, "vertex_color_in", 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, rColorVector.data()); +} + +void OpenGLProgram::SetShaderType(TextureShaderType eTextureShaderType) +{ + SetUniform1i("type", GLint(eTextureShaderType)); +} + +void OpenGLProgram::SetShaderType(DrawShaderType eDrawShaderType) +{ + SetUniform1i("type", GLint(eDrawShaderType)); +} + +GLuint OpenGLProgram::GetUniformLocation( const OString& rName ) +{ + auto it = maUniformLocations.find( rName ); + if( it == maUniformLocations.end() ) + { + GLuint nLocation = glGetUniformLocation( mnId, rName.getStr() ); + CHECK_GL_ERROR(); + maUniformLocations[rName] = nLocation; + return nLocation; + } + + return it->second; +} + +void OpenGLProgram::DrawArrays(GLenum aMode, std::vector<GLfloat>& aVertices) +{ + if (!mbBlending) + OpenGLContext::getVCLContext()->state().blend().disable(); + + SetVertices(aVertices.data()); + glDrawArrays(aMode, 0, aVertices.size() / 2); +} + +void OpenGLProgram::DrawElements(GLenum aMode, GLuint nNumberOfVertices) +{ + if (!mbBlending) + OpenGLContext::getVCLContext()->state().blend().disable(); + + glDrawElements(aMode, nNumberOfVertices, GL_UNSIGNED_INT, nullptr); +} + +void OpenGLProgram::SetUniform1f( const OString& rName, GLfloat v1 ) +{ + GLuint nUniform = GetUniformLocation( rName ); + glUniform1f( nUniform, v1 ); + CHECK_GL_ERROR(); +} + +void OpenGLProgram::SetUniform2f( const OString& rName, GLfloat v1, GLfloat v2 ) +{ + GLuint nUniform = GetUniformLocation( rName ); + glUniform2f( nUniform, v1, v2 ); + CHECK_GL_ERROR(); +} + +void OpenGLProgram::SetUniform1fv( const OString& rName, GLsizei nCount, GLfloat const * aValues ) +{ + GLuint nUniform = GetUniformLocation( rName ); + glUniform1fv( nUniform, nCount, aValues ); + CHECK_GL_ERROR(); +} + +void OpenGLProgram::SetUniform2fv( const OString& rName, GLsizei nCount, GLfloat const * aValues ) +{ + GLuint nUniform = GetUniformLocation( rName ); + glUniform2fv( nUniform, nCount, aValues ); + CHECK_GL_ERROR(); +} + +void OpenGLProgram::SetUniform1i( const OString& rName, GLint v1 ) +{ + GLuint nUniform = GetUniformLocation( rName ); + glUniform1i( nUniform, v1 ); + CHECK_GL_ERROR(); +} + +void OpenGLProgram::SetColor( const OString& rName, Color nColor, sal_uInt8 nTransparency ) +{ + GLuint nUniform = GetUniformLocation( rName ); + glUniform4f( nUniform, + nColor.GetRed() / 255.0f, + nColor.GetGreen() / 255.0f, + nColor.GetBlue() / 255.0f, + (100 - nTransparency) * (1.0 / 100) ); + CHECK_GL_ERROR(); + + if( nTransparency > 0 ) + SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); +} + +void OpenGLProgram::SetColorf( const OString& rName, Color nColor, double fTransparency ) +{ + GLuint nUniform = GetUniformLocation( rName ); + glUniform4f( nUniform, + nColor.GetRed() / 255.0f, + nColor.GetGreen() / 255.0f, + nColor.GetBlue() / 255.0f, + (1.0f - fTransparency) ); + CHECK_GL_ERROR(); + + if( fTransparency > 0.0 ) + SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); +} + +void OpenGLProgram::SetColor( const OString& rName, const Color& rColor ) +{ + GLuint nUniform = GetUniformLocation( rName ); + glUniform4f( nUniform, + static_cast<float>(rColor.GetRed()) / 255, + static_cast<float>(rColor.GetGreen()) / 255, + static_cast<float>(rColor.GetBlue()) / 255, + 1.0f - static_cast<float>(rColor.GetTransparency()) / 255 ); + CHECK_GL_ERROR(); + + if( rColor.GetTransparency() > 0 ) + SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); +} + +void OpenGLProgram::SetColorWithIntensity( const OString& rName, const Color& rColor, long nFactor ) +{ + GLuint nUniform = GetUniformLocation( rName ); + glUniform4f( nUniform, + static_cast<float>(rColor.GetRed()) * nFactor / 25500.0, + static_cast<float>(rColor.GetGreen()) * nFactor / 25500.0, + static_cast<float>(rColor.GetBlue()) * nFactor / 25500.0, + 1.0f ); + CHECK_GL_ERROR(); +} + +void OpenGLProgram::SetTexture( const OString& rName, OpenGLTexture& rTexture ) +{ + GLuint nUniform = GetUniformLocation( rName ); + int nIndex = maTextures.size(); + + glUniform1i( nUniform, nIndex ); + CHECK_GL_ERROR(); + + OpenGLContext::getVCLContext()->state().texture().active(nIndex); + + rTexture.Bind(); + maTextures.push_back(rTexture); +} + +void OpenGLProgram::SetTransform( + const OString& rName, + const OpenGLTexture& rTexture, + const basegfx::B2DPoint& rNull, + const basegfx::B2DPoint& rX, + const basegfx::B2DPoint& rY ) +{ + auto nTexWidth = rTexture.GetWidth(); + auto nTexHeight = rTexture.GetHeight(); + if (nTexWidth == 0 || nTexHeight == 0) + return; + + GLuint nUniform = GetUniformLocation( rName ); + const basegfx::B2DVector aXRel = rX - rNull; + const basegfx::B2DVector aYRel = rY - rNull; + const float aValues[] = { + static_cast<float>(aXRel.getX())/nTexWidth, static_cast<float>(aXRel.getY())/nTexWidth, 0, 0, + static_cast<float>(aYRel.getX())/nTexHeight, static_cast<float>(aYRel.getY())/nTexHeight, 0, 0, + 0, 0, 1, 0, + static_cast<float>(rNull.getX()), static_cast<float>(rNull.getY()), 0, 1 }; + glm::mat4 aMatrix = glm::make_mat4( aValues ); + glUniformMatrix4fv( nUniform, 1, GL_FALSE, glm::value_ptr( aMatrix ) ); + CHECK_GL_ERROR(); +} + +void OpenGLProgram::SetIdentityTransform(const OString& rName) +{ + GLuint nUniform = GetUniformLocation(rName); + glm::mat4 aMatrix {}; + glUniformMatrix4fv(nUniform, 1, GL_FALSE, glm::value_ptr( aMatrix ) ); + CHECK_GL_ERROR(); +} + +void OpenGLProgram::ApplyMatrix(float fWidth, float fHeight, float fPixelOffset) +{ + + if (mfLastWidth == fWidth && mfLastHeight == fHeight && mfLastPixelOffset == fPixelOffset) + return; + + mfLastWidth = fWidth; + mfLastHeight = fHeight; + mfLastPixelOffset = fPixelOffset; + + GLuint nUniform = GetUniformLocation("mvp"); + + glm::mat4 aMVP = glm::ortho(0.0f, fWidth, fHeight, 0.0f, 0.0f, 1.0f); + + if (fPixelOffset != 0.0f) + aMVP = glm::translate(aMVP, glm::vec3(fPixelOffset, fPixelOffset, 0.0f)); + + glUniformMatrix4fv(nUniform, 1, GL_FALSE, glm::value_ptr(aMVP)); + CHECK_GL_ERROR(); +} + +void OpenGLProgram::SetBlendMode(GLenum nSFactor, GLenum nDFactor) +{ + OpenGLContext::getVCLContext()->state().blend().enable(); + OpenGLContext::getVCLContext()->state().blend().func(nSFactor, nDFactor); + mbBlending = true; +} + +void OpenGLProgram::DrawTexture( const OpenGLTexture& rTexture ) +{ + if (!rTexture) + return; + + float fWidth = rTexture.GetWidth(); + float fHeight = rTexture.GetHeight(); + + float fMinX = 0.0f; + float fMaxX = fWidth; + float fMinY = 0.0f; + float fMaxY = fHeight; + + std::vector<GLfloat> aPosition { + fMinX, fMaxY, + fMinX, fMinY, + fMaxX, fMinY, + fMaxX, fMaxY + }; + GLfloat aTexCoord[8]; + + rTexture.GetWholeCoord( aTexCoord ); + SetTextureCoord( aTexCoord ); + ApplyMatrix(fWidth, fHeight); + DrawArrays(GL_TRIANGLE_FAN, aPosition); + CHECK_GL_ERROR(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |