summaryrefslogtreecommitdiff
path: root/vcl/opengl/program.cxx
diff options
context:
space:
mode:
authorLouis-Francis Ratté-Boulianne <lfrb@collabora.com>2014-11-28 14:56:08 -0500
committerJan Holesovsky <kendy@collabora.com>2014-12-02 11:58:45 +0100
commit99ade27b04d3d492648eadb620cda8ea9909bf45 (patch)
tree45a9221e508acc90e73db3ad998eeaa819099686 /vcl/opengl/program.cxx
parent0d4233ef90a4350d63da0c9d1b98ced64b773ce0 (diff)
vcl: Only load OpenGL shaders once for each context
Change-Id: Idbf9026c5e64ef41d4c913153dfddf36923ff7de
Diffstat (limited to 'vcl/opengl/program.cxx')
-rw-r--r--vcl/opengl/program.cxx238
1 files changed, 238 insertions, 0 deletions
diff --git a/vcl/opengl/program.cxx b/vcl/opengl/program.cxx
new file mode 100644
index 000000000000..c9542c726c75
--- /dev/null
+++ b/vcl/opengl/program.cxx
@@ -0,0 +1,238 @@
+/* -*- 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 <vcl/opengl/OpenGLHelper.hxx>
+
+#include <glm/glm.hpp>
+#include <glm/gtc/type_ptr.hpp>
+
+OpenGLProgram::OpenGLProgram() :
+ mnId( 0 ),
+ mnEnabledAttribs( 0 ),
+ mnAttribIndex( 0 ),
+ mnPositionAttrib( SAL_MAX_UINT32 ),
+ mnTexCoordAttrib( SAL_MAX_UINT32 ),
+ mnAlphaCoordAttrib( SAL_MAX_UINT32 ),
+ mbBlending( false )
+{
+}
+
+OpenGLProgram::~OpenGLProgram()
+{
+ maUniformLocations.clear();
+ if( mnId != 0 )
+ glDeleteProgram( mnId );
+}
+
+bool OpenGLProgram::Load( const OUString& rVertexShader, const OUString& rFragmentShader )
+{
+ mnId = OpenGLHelper::LoadShaders( rVertexShader, rFragmentShader );
+ return ( mnId != 0 );
+}
+
+bool OpenGLProgram::Use()
+{
+ if( !mnId )
+ return false;
+
+ glUseProgram( mnId );
+ return true;
+}
+
+bool OpenGLProgram::Clean()
+{
+ // unbind all textures
+ if( !maTextures.empty() )
+ {
+ int nIndex( maTextures.size() - 1 );
+ TextureList::reverse_iterator it( maTextures.rbegin() );
+ while( it != maTextures.rend() )
+ {
+ glActiveTexture( GL_TEXTURE0 + nIndex-- );
+ it->Unbind();
+ it++;
+ }
+ maTextures.clear();
+ }
+
+ // disable any enabled vertex attrib array
+ if( mnEnabledAttribs )
+ {
+ for( int i = 0; i < 32; i++ )
+ {
+ if( mnEnabledAttribs & ( 1 << i ) )
+ glDisableVertexAttribArray( i );
+ }
+ mnEnabledAttribs = 0;
+ }
+
+ // disable blending if enabled
+ if( mbBlending )
+ {
+ mbBlending = false;
+ glDisable( GL_BLEND );
+ }
+
+ CHECK_GL_ERROR();
+ return true;
+}
+
+void OpenGLProgram::SetVertexAttrib( GLuint& rAttrib, const OString& rName, const GLvoid* pData )
+{
+ if( rAttrib == SAL_MAX_UINT32 )
+ rAttrib = glGetAttribLocation( mnId, (char*) rName.getStr() );
+ if( (mnEnabledAttribs & ( 1 << rAttrib )) == 0 )
+ {
+ glEnableVertexAttribArray( rAttrib );
+ mnEnabledAttribs |= ( 1 << rAttrib );
+ }
+ glVertexAttribPointer( rAttrib, 2, GL_FLOAT, GL_FALSE, 0, pData );
+}
+
+void OpenGLProgram::SetVertices( const GLvoid* pData )
+{
+ SetVertexAttrib( mnPositionAttrib, "position", pData );
+}
+
+void OpenGLProgram::SetTextureCoord( const GLvoid* pData )
+{
+ SetVertexAttrib( mnTexCoordAttrib, "tex_coord_in", pData );
+}
+
+void OpenGLProgram::SetAlphaCoord( const GLvoid* pData )
+{
+ SetVertexAttrib( mnAlphaCoordAttrib, "alpha_coord_in", pData );
+}
+
+GLuint OpenGLProgram::GetUniformLocation( const OString& rName )
+{
+ boost::unordered_map<OString, GLuint>::iterator it;
+
+ it = maUniformLocations.find( rName );
+ if( it == maUniformLocations.end() )
+ {
+ GLuint nLocation = glGetUniformLocation( mnId, (char*) rName.getStr() );
+ maUniformLocations[rName] = nLocation;
+ return nLocation;
+ }
+
+ return it->second;
+}
+
+void OpenGLProgram::SetUniform2f( const OString& rName, GLfloat v1, GLfloat v2 )
+{
+ GLuint nUniform = GetUniformLocation( rName );
+ glUniform2f( nUniform, v1, v2 );
+}
+
+void OpenGLProgram::SetUniform1fv( const OString& rName, GLsizei nCount, GLfloat* aValues )
+{
+ GLuint nUniform = GetUniformLocation( rName );
+ glUniform1fv( nUniform, nCount, aValues );
+}
+
+void OpenGLProgram::SetUniform2fv( const OString& rName, GLsizei nCount, GLfloat* aValues )
+{
+ GLuint nUniform = GetUniformLocation( rName );
+ glUniform2fv( nUniform, nCount, aValues );
+}
+
+void OpenGLProgram::SetColor( const OString& rName, SalColor nColor, sal_uInt8 nTransparency )
+{
+ GLuint nUniform = GetUniformLocation( rName );
+ glUniform4f( nUniform,
+ ((float) SALCOLOR_RED( nColor )) / 255,
+ ((float) SALCOLOR_GREEN( nColor )) / 255,
+ ((float) SALCOLOR_BLUE( nColor )) / 255,
+ (100 - nTransparency) * (1.0 / 100) );
+
+ if( nTransparency > 0 )
+ SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+}
+
+void OpenGLProgram::SetColorf( const OString& rName, SalColor nColor, double fTransparency )
+{
+ GLuint nUniform = GetUniformLocation( rName );
+ glUniform4f( nUniform,
+ ((float) SALCOLOR_RED( nColor )) / 255,
+ ((float) SALCOLOR_GREEN( nColor )) / 255,
+ ((float) SALCOLOR_BLUE( nColor )) / 255,
+ (1.0f - fTransparency) );
+
+ if( fTransparency > 0.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,
+ ((float) rColor.GetRed()) * nFactor / 25500.0,
+ ((float) rColor.GetGreen()) * nFactor / 25500.0,
+ ((float) rColor.GetBlue()) * nFactor / 25500.0,
+ 1.0f );
+}
+
+void OpenGLProgram::SetTexture( const OString& rName, OpenGLTexture& rTexture )
+{
+ GLuint nUniform = GetUniformLocation( rName );
+ int nIndex = maTextures.size();
+
+ glUniform1i( nUniform, nIndex );
+ glActiveTexture( GL_TEXTURE0 + 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 )
+{
+ GLuint nUniform = GetUniformLocation( rName );
+ const basegfx::B2DVector aXRel = rX - rNull;
+ const basegfx::B2DVector aYRel = rY - rNull;
+ const float aValues[] = {
+ (float) aXRel.getX()/rTexture.GetWidth(), (float) aXRel.getY()/rTexture.GetWidth(), 0, 0,
+ (float) aYRel.getX()/rTexture.GetHeight(), (float) aYRel.getY()/rTexture.GetHeight(), 0, 0,
+ 0, 0, 1, 0,
+ (float) rNull.getX(), (float) rNull.getY(), 0, 1 };
+ glm::mat4 mMatrix = glm::make_mat4( aValues );
+ glUniformMatrix4fv( nUniform, 1, GL_FALSE, glm::value_ptr( mMatrix ) );
+}
+
+void OpenGLProgram::SetBlendMode( GLenum nSFactor, GLenum nDFactor )
+{
+ glEnable( GL_BLEND );
+ glBlendFunc( nSFactor, nDFactor );
+ mbBlending = true;
+}
+
+bool OpenGLProgram::DrawTexture( OpenGLTexture& rTexture )
+{
+ GLfloat aPosition[8] = { -1, -1, -1, 1, 1, 1, 1, -1 };
+ GLfloat aTexCoord[8];
+
+ if( !rTexture )
+ return false;
+
+ rTexture.GetWholeCoord( aTexCoord );
+ SetVertices( aPosition );
+ SetTextureCoord( aTexCoord );
+ glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
+ CHECK_GL_ERROR();
+
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */