include/vcl/opengl/OpenGLContext.hxx | 34 + vcl/Library_vcl.mk | 1 vcl/Package_opengl.mk | 4 vcl/inc/opengl/program.hxx | 72 ++ vcl/inc/opengl/salbmp.hxx | 11 vcl/inc/opengl/texture.hxx | 1 vcl/inc/openglgdiimpl.hxx | 67 -- vcl/opengl/dumbVertexShader.glsl | 16 vcl/opengl/gdiimpl.cxx | 758 +++++------------------------- vcl/opengl/maskVertexShader.glsl | 19 vcl/opengl/maskedTextureVertexShader.glsl | 19 vcl/opengl/program.cxx | 238 +++++++++ vcl/opengl/salbmp.cxx | 7 vcl/opengl/scale.cxx | 96 --- vcl/opengl/solidVertexShader.glsl | 16 vcl/opengl/texture.cxx | 32 - vcl/source/opengl/OpenGLContext.cxx | 35 + 17 files changed, 589 insertions(+), 837 deletions(-)
New commits: commit b2e3367c3c7de2a4ff2ba825df561549b253e5bf Author: Louis-Francis Ratté-Boulianne <l...@collabora.com> Date: Fri Nov 28 14:58:53 2014 -0500 vcl: Fix a coordinate issue when getting a bitmap from a VirtualDevice Change-Id: I06fef2765f2dc9d64a991385a984a4c75a1fd424 diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx index 2f3b96b..7cd4e50 100644 --- a/vcl/opengl/gdiimpl.cxx +++ b/vcl/opengl/gdiimpl.cxx @@ -1128,8 +1128,8 @@ SalBitmap* OpenGLSalGraphicsImpl::getBitmap( long nX, long nY, long nWidth, long OpenGLSalBitmap* pBitmap = new OpenGLSalBitmap; SAL_INFO( "vcl.opengl", "::getBitmap " << nX << "," << nY << " " << nWidth << "x" << nHeight ); + //TODO really needed? PreDraw(); - nY = GetHeight() - nHeight - nY; if( !pBitmap->Create( maOffscreenTex, nX, nY, nWidth, nHeight ) ) { delete pBitmap; @@ -1144,6 +1144,7 @@ SalColor OpenGLSalGraphicsImpl::getPixel( long nX, long nY ) char pixel[3] = { 0, 0, 0 }; PreDraw(); + nY = GetHeight() - nY; glReadPixels( nX, nY, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel); PostDraw(); diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx index 7618c04..0c45d77 100644 --- a/vcl/opengl/texture.cxx +++ b/vcl/opengl/texture.cxx @@ -52,6 +52,9 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight ) mnHeight( nHeight ), mnFilter( GL_NEAREST ) { + // FIXME We need the window height here + // nY = GetHeight() - nHeight - nY; + glGenTextures( 1, &mnTexture ); glBindTexture( GL_TEXTURE_2D, mnTexture ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); commit 766f1238d88cd980825e0613b194b0659fb93ba5 Author: Louis-Francis Ratté-Boulianne <l...@collabora.com> Date: Fri Nov 28 14:56:08 2014 -0500 vcl: Only load OpenGL shaders once for each context Change-Id: Idbf9026c5e64ef41d4c913153dfddf36923ff7de diff --git a/include/vcl/opengl/OpenGLContext.hxx b/include/vcl/opengl/OpenGLContext.hxx index 1b21851..679de09 100644 --- a/include/vcl/opengl/OpenGLContext.hxx +++ b/include/vcl/opengl/OpenGLContext.hxx @@ -51,11 +51,13 @@ class NSOpenGLView; #include <vcl/vclopengl_dllapi.hxx> #include <boost/scoped_ptr.hpp> +#include <boost/unordered_map.hpp> #include <vcl/window.hxx> #include <tools/gen.hxx> #include <vcl/syschild.hxx> class OpenGLFramebuffer; +class OpenGLProgram; class OpenGLTexture; /// Holds the information of our new child window @@ -155,6 +157,31 @@ struct GLWindow ~GLWindow(); }; +struct ProgramKey +{ + OUString maVertexShader; + OUString maFragmentShader; + + ProgramKey( const OUString& rVertexShader, const OUString& rFragmentShader ) + { + maVertexShader = rVertexShader; + maFragmentShader = rFragmentShader; + } +}; + +inline bool operator==( ProgramKey const& k1, ProgramKey const& k2 ) +{ + return k1.maVertexShader == k2.maVertexShader && k1.maFragmentShader == k2.maFragmentShader; +} + +inline std::size_t hash_value( ProgramKey const& rKey ) +{ + std::size_t nSeed = 0x9e3779b9; + nSeed = rKey.maVertexShader.hashCode(); + nSeed = rKey.maFragmentShader.hashCode() + 0x9e3779b9 + (nSeed << 6) + (nSeed >> 2); + return nSeed; +} + class VCLOPENGL_DLLPUBLIC OpenGLContext { public: @@ -187,6 +214,10 @@ public: OpenGLFramebuffer* AcquireFramebuffer( const OpenGLTexture& rTexture ); void ReleaseFramebuffer( OpenGLFramebuffer* pFramebuffer ); + // retrieve a program from the cache or compile/link it + OpenGLProgram* GetProgram( const OUString& rVertexShader, const OUString& rFragmentShader ); + OpenGLProgram* UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader ); + void makeCurrent(); void resetCurrent(); void swapBuffers(); @@ -244,6 +275,9 @@ private: OpenGLFramebuffer* mpFirstFramebuffer; OpenGLFramebuffer* mpLastFramebuffer; + boost::unordered_map<ProgramKey, OpenGLProgram*> maPrograms; + OpenGLProgram* mpCurrentProgram; + public: vcl::Region maClipRegion; int mnPainting; diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index a231dae..d5063627 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -126,6 +126,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/opengl/salbmp \ vcl/opengl/scale \ vcl/opengl/framebuffer \ + vcl/opengl/program \ vcl/opengl/texture \ vcl/source/opengl/OpenGLContext \ vcl/source/opengl/OpenGLHelper \ diff --git a/vcl/Package_opengl.mk b/vcl/Package_opengl.mk index d81c0ec..98ff78b 100644 --- a/vcl/Package_opengl.mk +++ b/vcl/Package_opengl.mk @@ -12,16 +12,14 @@ $(eval $(call gb_Package_Package,vcl_opengl_shader,$(SRCDIR)/vcl/opengl)) $(eval $(call gb_Package_add_files,vcl_opengl_shader,$(LIBO_ETC_FOLDER)/opengl,\ blendedTextureFragmentShader.glsl \ blendedTextureVertexShader.glsl \ + dumbVertexShader.glsl \ diffTextureFragmentShader.glsl \ convolutionFragmentShader.glsl \ linearGradientFragmentShader.glsl \ maskFragmentShader.glsl \ - maskVertexShader.glsl \ maskedTextureFragmentShader.glsl \ - maskedTextureVertexShader.glsl \ radialGradientFragmentShader.glsl \ solidFragmentShader.glsl \ - solidVertexShader.glsl \ textureFragmentShader.glsl \ textureVertexShader.glsl \ transformedTextureVertexShader.glsl \ diff --git a/vcl/inc/opengl/program.hxx b/vcl/inc/opengl/program.hxx new file mode 100644 index 0000000..4b2b26f --- /dev/null +++ b/vcl/inc/opengl/program.hxx @@ -0,0 +1,72 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_VCL_INC_OPENGL_PROGRAM_H +#define INCLUDED_VCL_INC_OPENGL_PROGRAM_H + +#include <GL/glew.h> +#include <vcl/dllapi.h> + +#include <basegfx/point/b2dpoint.hxx> +#include <rtl/ustring.hxx> +#include <tools/color.hxx> +#include <opengl/texture.hxx> + +#include <boost/unordered_map.hpp> + +typedef boost::unordered_map< OString, GLuint, OStringHash > UniformCache; +typedef std::list< OpenGLTexture > TextureList; + +class VCL_PLUGIN_PUBLIC OpenGLProgram +{ +private: + GLuint mnId; + UniformCache maUniformLocations; + sal_uInt32 mnEnabledAttribs; + GLuint mnAttribIndex; + GLuint mnPositionAttrib; + GLuint mnTexCoordAttrib; + GLuint mnAlphaCoordAttrib; + TextureList maTextures; + bool mbBlending; + +public: + OpenGLProgram(); + ~OpenGLProgram(); + + bool Load( const OUString& rVertexShader, const OUString& rFragmentShader ); + bool Use(); + bool Clean(); + + void SetVertices( const GLvoid* pData ); + void SetTextureCoord( const GLvoid* pData ); + void SetAlphaCoord( const GLvoid* pData ); + + void SetUniform2f( const OString& rName, GLfloat v1, GLfloat v2 ); + void SetUniform1fv( const OString& rName, GLsizei nCount, GLfloat* aValues ); + void SetUniform2fv( const OString& rName, GLsizei nCount, GLfloat* aValues ); + void SetColor( const OString& rName, SalColor nColor, sal_uInt8 nTransparency ); + void SetColorf( const OString& rName, SalColor nColor, double fTransparency ); + void SetColorWithIntensity( const OString& rName, const Color& rColor, long nFactor ); + void SetTexture( const OString& rName, OpenGLTexture& rTexture ); + void SetTransform( const OString& rName, const OpenGLTexture& rTexture, + const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX, + const basegfx::B2DPoint& rY ); + void SetBlendMode( GLenum nSFactor, GLenum nDFactor ); + + bool DrawTexture( OpenGLTexture& rTexture ); + +protected: + void SetVertexAttrib( GLuint& rAttrib, const OString& rName, const GLvoid* pData ); + GLuint GetUniformLocation( const OString& rName ); +}; + +#endif // INCLUDED_VCL_INC_OPENGL_PROGRAM_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/opengl/salbmp.hxx b/vcl/inc/opengl/salbmp.hxx index 6a812d0..c25dfa8 100644 --- a/vcl/inc/opengl/salbmp.hxx +++ b/vcl/inc/opengl/salbmp.hxx @@ -100,17 +100,6 @@ private: private: - GLuint ImplGetTextureProgram(); - GLuint mnTexProgram; - GLuint mnTexSamplerUniform; - - GLuint ImplGetConvolutionProgram(); - GLuint mnConvProgram; - GLuint mnConvSamplerUniform; - GLuint mnConvKernelUniform; - GLuint mnConvKernelSizeUniform; - GLuint mnConvOffsetsUniform; - bool ImplScaleFilter( const double& rScaleX, const double& rScaleY, GLenum nFilter ); void ImplCreateKernel( const double& fScale, const Kernel& rKernel, GLfloat*& pWeights, sal_uInt32& aKernelSize ); bool ImplScaleConvolution( const double& rScaleX, const double& rScaleY, const Kernel& aKernel ); diff --git a/vcl/inc/opengl/texture.hxx b/vcl/inc/opengl/texture.hxx index ad4738a..3d99526 100644 --- a/vcl/inc/opengl/texture.hxx +++ b/vcl/inc/opengl/texture.hxx @@ -65,6 +65,7 @@ public: int GetWidth() const; int GetHeight() const; void GetCoord( GLfloat* pCoord, const SalTwoRect& rPosAry, bool bInverted=false ) const; + void GetWholeCoord( GLfloat* pCoord ) const; void Bind(); void Unbind(); diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx index ad13335..42c5520 100644 --- a/vcl/inc/openglgdiimpl.hxx +++ b/vcl/inc/openglgdiimpl.hxx @@ -25,6 +25,7 @@ #include <vcl/dllapi.h> #include "opengl/framebuffer.hxx" +#include "opengl/program.hxx" #include "opengl/texture.hxx" #include "regionband.hxx" @@ -42,6 +43,7 @@ protected: /// Pointer to the SalFrame or SalVirtualDevice SalGeometryProvider* mpParent; OpenGLFramebuffer* mpFramebuffer; + OpenGLProgram* mpProgram; // clipping vcl::Region maClipRegion; @@ -54,72 +56,17 @@ protected: SalColor mnLineColor; SalColor mnFillColor; - GLuint mnSolidProgram; - GLuint mnColorUniform; - - GLuint mnTextureProgram; - GLuint mnSamplerUniform; - - GLuint mnTransformedTextureProgram; - GLuint mnTransformedViewportUniform; - GLuint mnTransformedTransformUniform; - GLuint mnTransformedSamplerUniform; - - GLuint mnTransformedMaskedTextureProgram; - GLuint mnTransformedMaskedViewportUniform; - GLuint mnTransformedMaskedTransformUniform; - GLuint mnTransformedMaskedSamplerUniform; - GLuint mnTransformedMaskedMaskUniform; - - GLuint mnDiffTextureProgram; - GLuint mnDiffTextureUniform; - GLuint mnDiffMaskUniform; - - GLuint mnMaskedTextureProgram; - GLuint mnMaskedSamplerUniform; - GLuint mnMaskSamplerUniform; - - GLuint mnBlendedTextureProgram; - GLuint mnBlendedTextureUniform; - GLuint mnBlendedMaskUniform; - GLuint mnBlendedAlphaUniform; - - GLuint mnMaskProgram; - GLuint mnMaskUniform; - GLuint mnMaskColorUniform; - - GLuint mnLinearGradientProgram; - GLuint mnLinearGradientStartColorUniform; - GLuint mnLinearGradientEndColorUniform; - - GLuint mnRadialGradientProgram; - GLuint mnRadialGradientStartColorUniform; - GLuint mnRadialGradientEndColorUniform; - GLuint mnRadialGradientCenterUniform; - void ImplInitClipRegion(); void ImplSetClipBit( const vcl::Region& rClip, GLuint nMask ); bool CheckOffscreenTexture(); - bool CreateSolidProgram( void ); - bool CreateTextureProgram( void ); - bool CreateTransformedTextureProgram( void ); - bool CreateDiffTextureProgram( void ); - bool CreateMaskedTextureProgram( void ); - bool CreateBlendedTextureProgram( void ); - bool CreateTransformedMaskedTextureProgram( void ); - bool CreateMaskProgram( void ); - bool CreateLinearGradientProgram( void ); - bool CreateRadialGradientProgram( void ); - public: - void BeginSolid( SalColor nColor, sal_uInt8 nTransparency ); - void BeginSolid( SalColor nColor, double fTransparency ); - void BeginSolid( SalColor nColor ); - void EndSolid( void ); - void BeginInvert( void ); - void EndInvert( void ); + bool UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader ); + bool UseSolid( SalColor nColor, sal_uInt8 nTransparency ); + bool UseSolid( SalColor nColor, double fTransparency ); + bool UseSolid( SalColor nColor ); + bool UseInvert(); void DrawPoint( long nX, long nY ); void DrawLine( long nX1, long nY1, long nX2, long nY2 ); diff --git a/vcl/opengl/solidVertexShader.glsl b/vcl/opengl/dumbVertexShader.glsl similarity index 100% rename from vcl/opengl/solidVertexShader.glsl rename to vcl/opengl/dumbVertexShader.glsl diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx index f761ebf..2f3b96b 100644 --- a/vcl/opengl/gdiimpl.cxx +++ b/vcl/opengl/gdiimpl.cxx @@ -34,77 +34,18 @@ #include "svdata.hxx" #include "opengl/salbmp.hxx" -#include <glm/glm.hpp> -#include <glm/gtc/type_ptr.hpp> #include <vector> -#define GL_ATTRIB_POS 0 -#define GL_ATTRIB_TEX 1 -#define GL_ATTRIB_TEX2 2 - -#define glUniformColor(nUniform, nColor, nTransparency) \ - glUniform4f( nUniform, \ - ((float) SALCOLOR_RED( nColor )) / 255, \ - ((float) SALCOLOR_GREEN( nColor )) / 255, \ - ((float) SALCOLOR_BLUE( nColor )) / 255, \ - (100 - nTransparency) * (1.0 / 100) ) - -#define glUniformColorf(nUniform, nColor, fTransparency) \ - glUniform4f( nUniform, \ - ((float) SALCOLOR_RED( nColor )) / 255, \ - ((float) SALCOLOR_GREEN( nColor )) / 255, \ - ((float) SALCOLOR_BLUE( nColor )) / 255, \ - (1.0f - fTransparency) ) - -#define glUniformColorIntensity(nUniform, aColor, nFactor) \ - glUniform4f( nUniform, \ - ((float) aColor.GetRed()) * nFactor / 25500.0, \ - ((float) aColor.GetGreen()) * nFactor / 25500.0, \ - ((float) aColor.GetBlue()) * nFactor / 25500.0, \ - 1.0f ) - OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl(SalGeometryProvider* pParent) : mpContext(0) , mpParent(pParent) , mpFramebuffer(NULL) + , mpProgram(NULL) , mbUseScissor(false) , mbUseStencil(false) , mbOffscreen(false) , mnLineColor(SALCOLOR_NONE) , mnFillColor(SALCOLOR_NONE) - , mnSolidProgram(0) - , mnColorUniform(0) - , mnTextureProgram(0) - , mnSamplerUniform(0) - , mnTransformedTextureProgram(0) - , mnTransformedViewportUniform(0) - , mnTransformedTransformUniform(0) - , mnTransformedSamplerUniform(0) - , mnTransformedMaskedTextureProgram(0) - , mnTransformedMaskedViewportUniform(0) - , mnTransformedMaskedTransformUniform(0) - , mnTransformedMaskedSamplerUniform(0) - , mnTransformedMaskedMaskUniform(0) - , mnDiffTextureProgram(0) - , mnDiffTextureUniform(0) - , mnDiffMaskUniform(0) - , mnMaskedTextureProgram(0) - , mnMaskedSamplerUniform(0) - , mnMaskSamplerUniform(0) - , mnBlendedTextureProgram(0) - , mnBlendedTextureUniform(0) - , mnBlendedMaskUniform(0) - , mnBlendedAlphaUniform(0) - , mnMaskProgram(0) - , mnMaskUniform(0) - , mnMaskColorUniform(0) - , mnLinearGradientProgram(0) - , mnLinearGradientStartColorUniform(0) - , mnLinearGradientEndColorUniform(0) - , mnRadialGradientProgram(0) - , mnRadialGradientStartColorUniform(0) - , mnRadialGradientEndColorUniform(0) - , mnRadialGradientCenterUniform(0) { } @@ -204,6 +145,11 @@ void OpenGLSalGraphicsImpl::PostDraw() glDisable( GL_SCISSOR_TEST ); if( mbUseStencil ) glDisable( GL_STENCIL_TEST ); + if( mpProgram ) + { + mpProgram->Clean(); + mpProgram = NULL; + } mpContext->ReleaseFramebuffer( mpFramebuffer ); mpFramebuffer = NULL; @@ -225,12 +171,13 @@ void OpenGLSalGraphicsImpl::ImplSetClipBit( const vcl::Region& rClip, GLuint nMa glStencilOp( GL_REPLACE, GL_KEEP, GL_KEEP ); glClear( GL_STENCIL_BUFFER_BIT ); - BeginSolid( MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF ) ); - if( rClip.getRegionBand() ) - DrawRegionBand( *rClip.getRegionBand() ); - else - DrawPolyPolygon( rClip.GetAsB2DPolyPolygon() ); - EndSolid(); + if( UseSolid( MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF ) ) ) + { + if( rClip.getRegionBand() ) + DrawRegionBand( *rClip.getRegionBand() ); + else + DrawPolyPolygon( rClip.GetAsB2DPolyPolygon() ); + } glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); glStencilMask( 0x00 ); @@ -383,231 +330,45 @@ bool OpenGLSalGraphicsImpl::CheckOffscreenTexture() return true; } -bool OpenGLSalGraphicsImpl::CreateSolidProgram( void ) -{ - SAL_INFO( "vcl.opengl", "::CreateSolidProgram" ); - mnSolidProgram = OpenGLHelper::LoadShaders( "solidVertexShader", "solidFragmentShader" ); - if( mnSolidProgram == 0 ) - return false; - - SAL_INFO( "vcl.opengl", "Solid Program Created" ); - glBindAttribLocation( mnSolidProgram, GL_ATTRIB_POS, "position" ); - mnColorUniform = glGetUniformLocation( mnSolidProgram, "color" ); - - CHECK_GL_ERROR(); - return true; -} - -bool OpenGLSalGraphicsImpl::CreateTextureProgram( void ) -{ - mnTextureProgram = OpenGLHelper::LoadShaders( "textureVertexShader", "textureFragmentShader" ); - if( mnTextureProgram == 0 ) - return false; - - glBindAttribLocation( mnTextureProgram, GL_ATTRIB_POS, "position" ); - glBindAttribLocation( mnTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" ); - mnSamplerUniform = glGetUniformLocation( mnTextureProgram, "sampler" ); - - CHECK_GL_ERROR(); - return true; -} - -bool OpenGLSalGraphicsImpl::CreateTransformedTextureProgram( void ) -{ - mnTransformedTextureProgram = OpenGLHelper::LoadShaders( "transformedTextureVertexShader", "textureFragmentShader" ); - if( mnTransformedTextureProgram == 0 ) - return false; - - glBindAttribLocation( mnTransformedTextureProgram, GL_ATTRIB_POS, "position" ); - glBindAttribLocation( mnTransformedTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" ); - mnTransformedViewportUniform = glGetUniformLocation( mnTransformedTextureProgram, "viewport" ); - mnTransformedTransformUniform = glGetUniformLocation( mnTransformedTextureProgram, "transform" ); - mnTransformedSamplerUniform = glGetUniformLocation( mnTransformedTextureProgram, "sampler" ); - - CHECK_GL_ERROR(); - return true; -} - -bool OpenGLSalGraphicsImpl::CreateDiffTextureProgram( void ) +bool OpenGLSalGraphicsImpl::UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader ) { - mnDiffTextureProgram = OpenGLHelper::LoadShaders( "textureVertexShader", "diffTextureFragmentShader" ); - if( mnDiffTextureProgram == 0 ) - return false; - - glBindAttribLocation( mnDiffTextureProgram, GL_ATTRIB_POS, "position" ); - glBindAttribLocation( mnDiffTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" ); - mnDiffTextureUniform = glGetUniformLocation( mnDiffTextureProgram, "texture" ); - mnDiffMaskUniform = glGetUniformLocation( mnDiffTextureProgram, "mask" ); - - CHECK_GL_ERROR(); - return true; + mpProgram = mpContext->UseProgram( rVertexShader, rFragmentShader ); + return ( mpProgram != NULL ); } -bool OpenGLSalGraphicsImpl::CreateMaskedTextureProgram( void ) +bool OpenGLSalGraphicsImpl::UseSolid( SalColor nColor, sal_uInt8 nTransparency ) { - mnMaskedTextureProgram = OpenGLHelper::LoadShaders( "maskedTextureVertexShader", "maskedTextureFragmentShader" ); - if( mnMaskedTextureProgram == 0 ) + if( nColor == SALCOLOR_NONE ) return false; - - glBindAttribLocation( mnMaskedTextureProgram, GL_ATTRIB_POS, "position" ); - glBindAttribLocation( mnMaskedTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" ); - mnMaskedSamplerUniform = glGetUniformLocation( mnMaskedTextureProgram, "sampler" ); - mnMaskSamplerUniform = glGetUniformLocation( mnMaskedTextureProgram, "mask" ); - - CHECK_GL_ERROR(); - return true; -} - -bool OpenGLSalGraphicsImpl::CreateTransformedMaskedTextureProgram( void ) -{ - mnTransformedMaskedTextureProgram = OpenGLHelper::LoadShaders( "transformedTextureVertexShader", "maskedTextureFragmentShader" ); - if( mnTransformedMaskedTextureProgram == 0 ) + if( !UseProgram( "dumbVertexShader", "solidFragmentShader" ) ) return false; - - glBindAttribLocation( mnTransformedMaskedTextureProgram, GL_ATTRIB_POS, "position" ); - glBindAttribLocation( mnTransformedMaskedTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" ); - mnTransformedMaskedViewportUniform = glGetUniformLocation( mnTransformedMaskedTextureProgram, "viewport" ); - mnTransformedMaskedTransformUniform = glGetUniformLocation( mnTransformedMaskedTextureProgram, "transform" ); - mnTransformedMaskedSamplerUniform = glGetUniformLocation( mnTransformedMaskedTextureProgram, "sampler" ); - mnTransformedMaskedMaskUniform = glGetUniformLocation( mnTransformedMaskedTextureProgram, "mask" ); - - CHECK_GL_ERROR(); + mpProgram->SetColor( "color", nColor, nTransparency ); return true; } -bool OpenGLSalGraphicsImpl::CreateBlendedTextureProgram( void ) +bool OpenGLSalGraphicsImpl::UseSolid( SalColor nColor, double fTransparency ) { - mnBlendedTextureProgram = OpenGLHelper::LoadShaders( "blendedTextureVertexShader", "blendedTextureFragmentShader" ); - if( mnBlendedTextureProgram == 0 ) + if( nColor == SALCOLOR_NONE ) return false; - - glBindAttribLocation( mnBlendedTextureProgram, GL_ATTRIB_POS, "position" ); - glBindAttribLocation( mnBlendedTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" ); - glBindAttribLocation( mnBlendedTextureProgram, GL_ATTRIB_TEX2, "alpha_coord_in" ); - mnBlendedTextureUniform = glGetUniformLocation( mnBlendedTextureProgram, "sampler" ); - mnBlendedMaskUniform = glGetUniformLocation( mnBlendedTextureProgram, "mask" ); - mnBlendedAlphaUniform = glGetUniformLocation( mnBlendedTextureProgram, "alpha" ); - - CHECK_GL_ERROR(); - return true; -} - -bool OpenGLSalGraphicsImpl::CreateMaskProgram( void ) -{ - mnMaskProgram = OpenGLHelper::LoadShaders( "maskVertexShader", "maskFragmentShader" ); - if( mnMaskProgram == 0 ) + if( !UseProgram( "dumbVertexShader", "solidFragmentShader" ) ) return false; - - glBindAttribLocation( mnMaskProgram, GL_ATTRIB_POS, "position" ); - glBindAttribLocation( mnMaskProgram, GL_ATTRIB_TEX, "tex_coord_in" ); - mnMaskUniform = glGetUniformLocation( mnMaskProgram, "sampler" ); - mnMaskColorUniform = glGetUniformLocation( mnMaskProgram, "color" ); - - CHECK_GL_ERROR(); + mpProgram->SetColorf( "color", nColor, fTransparency ); return true; } -bool OpenGLSalGraphicsImpl::CreateLinearGradientProgram( void ) +bool OpenGLSalGraphicsImpl::UseSolid( SalColor nColor ) { - mnLinearGradientProgram = OpenGLHelper::LoadShaders( "textureVertexShader", "linearGradientFragmentShader" ); - if( mnLinearGradientProgram == 0 ) - return false; - - glBindAttribLocation( mnLinearGradientProgram, GL_ATTRIB_POS, "position" ); - glBindAttribLocation( mnLinearGradientProgram, GL_ATTRIB_TEX, "tex_coord_in" ); - mnLinearGradientStartColorUniform = glGetUniformLocation( mnLinearGradientProgram, "start_color" ); - mnLinearGradientEndColorUniform = glGetUniformLocation( mnLinearGradientProgram, "end_color" ); - - CHECK_GL_ERROR(); - return true; + return UseSolid( nColor, 0.0f ); } -bool OpenGLSalGraphicsImpl::CreateRadialGradientProgram( void ) +bool OpenGLSalGraphicsImpl::UseInvert() { - mnRadialGradientProgram = OpenGLHelper::LoadShaders( "textureVertexShader", "radialGradientFragmentShader" ); - if( mnRadialGradientProgram == 0 ) + if( !UseSolid( MAKE_SALCOLOR( 255, 255, 255 ) ) ) return false; - - glBindAttribLocation( mnRadialGradientProgram, GL_ATTRIB_POS, "position" ); - glBindAttribLocation( mnRadialGradientProgram, GL_ATTRIB_TEX, "tex_coord_in" ); - mnRadialGradientStartColorUniform = glGetUniformLocation( mnRadialGradientProgram, "start_color" ); - mnRadialGradientEndColorUniform = glGetUniformLocation( mnRadialGradientProgram, "end_color" ); - mnRadialGradientCenterUniform = glGetUniformLocation( mnRadialGradientProgram, "center" ); - - CHECK_GL_ERROR(); + mpProgram->SetBlendMode( GL_ONE_MINUS_DST_COLOR, GL_ZERO ); return true; } -void OpenGLSalGraphicsImpl::BeginSolid( SalColor nColor, sal_uInt8 nTransparency ) -{ - if( mnSolidProgram == 0 ) - { - glClearColor( 1, 1, 1, 1 ); - glClear( GL_COLOR_BUFFER_BIT ); - if( !CreateSolidProgram() ) - return; - } - - if( nTransparency > 0 ) - { - glEnable( GL_BLEND ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - } - glUseProgram( mnSolidProgram ); - glUniformColor( mnColorUniform, nColor, nTransparency ); - - CHECK_GL_ERROR(); -} - -void OpenGLSalGraphicsImpl::BeginSolid( SalColor nColor, double fTransparency ) -{ - if( mnSolidProgram == 0 ) - { - if( !CreateSolidProgram() ) - return; - } - - if( fTransparency > 0.0f ) - { - glEnable( GL_BLEND ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - } - glUseProgram( mnSolidProgram ); - glUniformColorf( mnColorUniform, nColor, fTransparency ); - - CHECK_GL_ERROR(); -} - -void OpenGLSalGraphicsImpl::BeginSolid( SalColor nColor ) -{ - BeginSolid( nColor, 0.0f ); -} - -void OpenGLSalGraphicsImpl::EndSolid( void ) -{ - glUseProgram( 0 ); - glDisable( GL_BLEND ); - - CHECK_GL_ERROR(); -} - -void OpenGLSalGraphicsImpl::BeginInvert( void ) -{ - glEnable( GL_BLEND ); - glBlendFunc( GL_ONE_MINUS_DST_COLOR, GL_ZERO ); - BeginSolid( MAKE_SALCOLOR( 255, 255, 255 ) ); - - CHECK_GL_ERROR(); -} - -void OpenGLSalGraphicsImpl::EndInvert( void ) -{ - EndSolid(); - glDisable( GL_BLEND ); - - CHECK_GL_ERROR(); -} - void OpenGLSalGraphicsImpl::DrawPoint( long nX, long nY ) { GLfloat pPoint[2]; @@ -615,12 +376,8 @@ void OpenGLSalGraphicsImpl::DrawPoint( long nX, long nY ) pPoint[0] = 2 * nX / GetWidth() - 1.0f; pPoint[1] = 1.0f - 2 * nY / GetHeight(); - glEnableVertexAttribArray( GL_ATTRIB_POS ); - glVertexAttribPointer( GL_ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, pPoint ); + mpProgram->SetVertices( pPoint ); glDrawArrays( GL_POINTS, 0, 1 ); - glDisableVertexAttribArray( GL_ATTRIB_POS ); - - CHECK_GL_ERROR(); } void OpenGLSalGraphicsImpl::DrawLine( long nX1, long nY1, long nX2, long nY2 ) @@ -632,12 +389,8 @@ void OpenGLSalGraphicsImpl::DrawLine( long nX1, long nY1, long nX2, long nY2 ) pPoints[2] = (2 * nX2) / GetWidth() - 1.0;; pPoints[3] = 1.0f - 2 * nY2 / GetHeight(); - glEnableVertexAttribArray( GL_ATTRIB_POS ); - glVertexAttribPointer( GL_ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, pPoints ); + mpProgram->SetVertices( pPoints ); glDrawArrays( GL_LINES, 0, 2 ); - glDisableVertexAttribArray( GL_ATTRIB_POS ); - - CHECK_GL_ERROR(); } void OpenGLSalGraphicsImpl::DrawLines( sal_uInt32 nPoints, const SalPoint* pPtAry, bool bClose ) @@ -651,15 +404,11 @@ void OpenGLSalGraphicsImpl::DrawLines( sal_uInt32 nPoints, const SalPoint* pPtAr aPoints[j++] = 1.0f - (2 * pPtAry[i].mnY) / GetHeight(); } - glEnableVertexAttribArray( GL_ATTRIB_POS ); - glVertexAttribPointer( GL_ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, &aPoints[0] ); + mpProgram->SetVertices( &aPoints[0] ); if( bClose ) glDrawArrays( GL_LINE_LOOP, 0, nPoints ); else glDrawArrays( GL_LINE_STRIP, 0, nPoints ); - glDisableVertexAttribArray( GL_ATTRIB_POS ); - - CHECK_GL_ERROR(); } void OpenGLSalGraphicsImpl::DrawConvexPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) @@ -673,12 +422,8 @@ void OpenGLSalGraphicsImpl::DrawConvexPolygon( sal_uInt32 nPoints, const SalPoin aVertices[j+1] = 1.0 - (2 * pPtAry[i].mnY / GetHeight()); } - glEnableVertexAttribArray( GL_ATTRIB_POS ); - glVertexAttribPointer( GL_ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, &aVertices[0] ); + mpProgram->SetVertices( &aVertices[0] ); glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints ); - glDisableVertexAttribArray( GL_ATTRIB_POS ); - - CHECK_GL_ERROR(); } void OpenGLSalGraphicsImpl::DrawConvexPolygon( const Polygon& rPolygon ) @@ -694,12 +439,8 @@ void OpenGLSalGraphicsImpl::DrawConvexPolygon( const Polygon& rPolygon ) aVertices[j+1] = 1.0 - (2 * rPt.Y() / GetHeight()); } - glEnableVertexAttribArray( GL_ATTRIB_POS ); - glVertexAttribPointer( GL_ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, &aVertices[0] ); + mpProgram->SetVertices( &aVertices[0] ); glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints ); - glDisableVertexAttribArray( GL_ATTRIB_POS ); - - CHECK_GL_ERROR(); } void OpenGLSalGraphicsImpl::DrawRect( long nX, long nY, long nWidth, long nHeight ) @@ -768,12 +509,8 @@ void OpenGLSalGraphicsImpl::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rPol } } - glEnableVertexAttribArray( GL_ATTRIB_POS ); - glVertexAttribPointer( GL_ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, pVertices.data() ); + mpProgram->SetVertices( pVertices.data() ); glDrawArrays( GL_TRIANGLES, 0, pVertices.size() / 2 ); - glDisableVertexAttribArray( GL_ATTRIB_POS ); - - CHECK_GL_ERROR(); } void OpenGLSalGraphicsImpl::DrawRegionBand( const RegionBand& rRegion ) @@ -803,50 +540,25 @@ void OpenGLSalGraphicsImpl::DrawRegionBand( const RegionBand& rRegion ) #undef ADD_VERTICE - glEnableVertexAttribArray( GL_ATTRIB_POS ); - glVertexAttribPointer( GL_ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, &aVertices[0] ); + mpProgram->SetVertices( &aVertices[0] ); glDrawArrays( GL_TRIANGLES, 0, aVertices.size() / 2 ); - glDisableVertexAttribArray( GL_ATTRIB_POS ); - - CHECK_GL_ERROR(); } void OpenGLSalGraphicsImpl::DrawTextureRect( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted ) { GLfloat aTexCoord[8]; - rTexture.GetCoord( aTexCoord, rPosAry, bInverted ); - glEnableVertexAttribArray( GL_ATTRIB_TEX ); - glVertexAttribPointer( GL_ATTRIB_TEX, 2, GL_FLOAT, GL_FALSE, 0, aTexCoord ); - + mpProgram->SetTextureCoord( aTexCoord ); DrawRect( rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, rPosAry.mnDestHeight ); - - glDisableVertexAttribArray( GL_ATTRIB_TEX ); - - CHECK_GL_ERROR(); } void OpenGLSalGraphicsImpl::DrawTexture( OpenGLTexture& rTexture, const SalTwoRect& pPosAry, bool bInverted ) { - if( mnTextureProgram == 0 ) - { - if( !CreateTextureProgram() ) - return; - } - - glUseProgram( mnTextureProgram ); - glUniform1i( mnSamplerUniform, 0 ); - glActiveTexture( GL_TEXTURE0 ); - CHECK_GL_ERROR(); - - rTexture.Bind(); + if( !UseProgram( "textureVertexShader", "textureFragmentShader" ) ) + return; + mpProgram->SetTexture( "sampler", rTexture ); DrawTextureRect( rTexture, pPosAry, bInverted ); - rTexture.Unbind(); - CHECK_GL_ERROR(); - - glUseProgram( 0 ); - - CHECK_GL_ERROR(); + mpProgram->Clean(); } void OpenGLSalGraphicsImpl::DrawTransformedTexture( @@ -856,238 +568,105 @@ void OpenGLSalGraphicsImpl::DrawTransformedTexture( const basegfx::B2DPoint& rX, const basegfx::B2DPoint& rY ) { - 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 ); GLfloat aVertices[8] = { 0, (float) rTexture.GetHeight(), 0, 0, (float) rTexture.GetWidth(), 0, (float) rTexture.GetWidth(), (float) rTexture.GetHeight() }; GLfloat aTexCoord[8]; - SalTwoRect aPosAry; if( rMask ) { - if( mnTransformedMaskedTextureProgram == 0 ) - { - if( !CreateTransformedMaskedTextureProgram() ) - return; - } - glUseProgram( mnTransformedMaskedTextureProgram ); - glUniform2f( mnTransformedMaskedViewportUniform, GetWidth(), GetHeight() ); - glUniformMatrix4fv( mnTransformedMaskedTransformUniform, 1, GL_FALSE, glm::value_ptr( mMatrix ) ); - glUniform1i( mnTransformedMaskedSamplerUniform, 0 ); - glUniform1i( mnTransformedMaskedMaskUniform, 1 ); - glActiveTexture( GL_TEXTURE1 ); - rMask.Bind(); + if( !UseProgram( "transformedTextureVertexShader", "maskedTextureFragmentShader" ) ) + return; + mpProgram->SetTexture( "mask", rMask ); rMask.SetFilter( GL_LINEAR ); - glEnable( GL_BLEND ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); } else { - if( mnTransformedTextureProgram == 0 ) - { - if( !CreateTransformedTextureProgram() ) - return; - } - glUseProgram( mnTransformedTextureProgram ); - glUniform2f( mnTransformedViewportUniform, GetWidth(), GetHeight() ); - glUniformMatrix4fv( mnTransformedTransformUniform, 1, GL_FALSE, glm::value_ptr( mMatrix ) ); - glUniform1i( mnTransformedSamplerUniform, 0 ); + if( !UseProgram( "transformedTextureVertexShader", "textureFragmentShader" ) ) + return; } - glActiveTexture( GL_TEXTURE0 ); - rTexture.Bind(); + mpProgram->SetUniform2f( "viewport", GetWidth(), GetHeight() ); + mpProgram->SetTransform( "transform", rTexture, rNull, rX, rY ); + rTexture.GetWholeCoord( aTexCoord ); + mpProgram->SetTexture( "sampler", rTexture ); rTexture.SetFilter( GL_LINEAR ); - CHECK_GL_ERROR(); - - aPosAry.mnSrcX = aPosAry.mnSrcY = 0; - aPosAry.mnSrcWidth = rTexture.GetWidth(); - aPosAry.mnSrcHeight = rTexture.GetHeight(); - rTexture.GetCoord( aTexCoord, aPosAry ); - glEnableVertexAttribArray( GL_ATTRIB_TEX ); - glVertexAttribPointer( GL_ATTRIB_TEX, 2, GL_FLOAT, GL_FALSE, 0, aTexCoord ); - glEnableVertexAttribArray( GL_ATTRIB_POS ); - glVertexAttribPointer( GL_ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, &aVertices[0] ); + mpProgram->SetTextureCoord( aTexCoord ); + mpProgram->SetVertices( &aVertices[0] ); glDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); - glDisableVertexAttribArray( GL_ATTRIB_POS ); - glDisableVertexAttribArray( GL_ATTRIB_TEX ); - - if( rMask ) - { - glDisable( GL_BLEND ); - glActiveTexture( GL_TEXTURE1 ); - rMask.Unbind(); - } - - glActiveTexture( GL_TEXTURE0 ); - rTexture.Unbind(); - glUseProgram( 0 ); - CHECK_GL_ERROR(); + mpProgram->Clean(); } void OpenGLSalGraphicsImpl::DrawAlphaTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted, bool bPremultiplied ) { - glEnable( GL_BLEND ); - if( bPremultiplied ) - glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); - else - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - DrawTexture( rTexture, rPosAry, bInverted ); - glDisable( GL_BLEND ); - CHECK_GL_ERROR(); + if( !UseProgram( "textureVertexShader", "textureFragmentShader" ) ) + return; + mpProgram->SetTexture( "sampler", rTexture ); + mpProgram->SetBlendMode( bPremultiplied ? GL_ONE : GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA ); + DrawTextureRect( rTexture, rPosAry, bInverted ); + mpProgram->Clean(); } void OpenGLSalGraphicsImpl::DrawTextureDiff( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry, bool bInverted ) { - if( mnDiffTextureProgram == 0 ) - { - if( !CreateDiffTextureProgram() ) - return; - } - - glUseProgram( mnDiffTextureProgram ); - glUniform1i( mnDiffTextureUniform, 0 ); - glUniform1i( mnDiffMaskUniform, 1 ); - glActiveTexture( GL_TEXTURE0 ); - rTexture.Bind(); - glActiveTexture( GL_TEXTURE1 ); - rMask.Bind(); - - glEnable( GL_BLEND ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + if( !UseProgram( "textureVertexShader", "diffTextureFragmentShader" ) ) + return; + mpProgram->SetTexture( "texture", rTexture ); + mpProgram->SetTexture( "mask", rMask ); + mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); DrawTextureRect( rTexture, rPosAry, bInverted ); - glDisable( GL_BLEND ); - - glActiveTexture( GL_TEXTURE1 ); - rMask.Unbind(); - glActiveTexture( GL_TEXTURE0 ); - rTexture.Unbind(); - glUseProgram( 0 ); - - CHECK_GL_ERROR(); + mpProgram->Clean(); } void OpenGLSalGraphicsImpl::DrawTextureWithMask( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& pPosAry ) { - if( mnMaskedTextureProgram == 0 ) - { - if( !CreateMaskedTextureProgram() ) - return; - } - - glUseProgram( mnMaskedTextureProgram ); - glUniform1i( mnMaskedSamplerUniform, 0 ); - glUniform1i( mnMaskSamplerUniform, 1 ); - glActiveTexture( GL_TEXTURE0 ); - rTexture.Bind(); - glActiveTexture( GL_TEXTURE1 ); - rMask.Bind(); - - glEnable( GL_BLEND ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + if( !UseProgram( "textureVertexShader", "maskedTextureFragmentShader" ) ) + return; + mpProgram->SetTexture( "sampler", rTexture ); + mpProgram->SetTexture( "mask", rMask ); + mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); DrawTextureRect( rTexture, pPosAry ); - glDisable( GL_BLEND ); - - glActiveTexture( GL_TEXTURE1 ); - rMask.Unbind(); - glActiveTexture( GL_TEXTURE0 ); - rTexture.Unbind(); - glUseProgram( 0 ); - - CHECK_GL_ERROR(); + mpProgram->Clean(); } void OpenGLSalGraphicsImpl::DrawBlendedTexture( OpenGLTexture& rTexture, OpenGLTexture& rMask, OpenGLTexture& rAlpha, const SalTwoRect& rPosAry ) { GLfloat aTexCoord[8]; - - if( mnBlendedTextureProgram == 0 ) - { - if( !CreateBlendedTextureProgram() ) - return; - } - - glUseProgram( mnBlendedTextureProgram ); - glUniform1i( mnBlendedTextureUniform, 0 ); - glUniform1i( mnBlendedMaskUniform, 1 ); - glUniform1i( mnBlendedAlphaUniform, 2 ); - glActiveTexture( GL_TEXTURE0 ); - rTexture.Bind(); - glActiveTexture( GL_TEXTURE1 ); - rMask.Bind(); - glActiveTexture( GL_TEXTURE2 ); - rAlpha.Bind(); - + if( !UseProgram( "blendedTextureVertexShader", "blendedTextureFragmentShader" ) ) + return; + mpProgram->SetTexture( "sampler", rTexture ); + mpProgram->SetTexture( "mask", rMask ); + mpProgram->SetTexture( "alpha", rAlpha ); rAlpha.GetCoord( aTexCoord, rPosAry ); - glEnableVertexAttribArray( GL_ATTRIB_TEX2 ); - glVertexAttribPointer( GL_ATTRIB_TEX2, 2, GL_FLOAT, GL_FALSE, 0, aTexCoord ); - - glEnable( GL_BLEND ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + mpProgram->SetAlphaCoord( aTexCoord ); + mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); DrawTextureRect( rTexture, rPosAry ); - glDisable( GL_BLEND ); - - glDisableVertexAttribArray( GL_ATTRIB_TEX2 ); - - glActiveTexture( GL_TEXTURE0 ); - rTexture.Unbind(); - glActiveTexture( GL_TEXTURE1 ); - rMask.Unbind(); - glActiveTexture( GL_TEXTURE2 ); - rAlpha.Unbind(); - glActiveTexture( GL_TEXTURE0 ); - glUseProgram( 0 ); - - CHECK_GL_ERROR(); + mpProgram->Clean(); } void OpenGLSalGraphicsImpl::DrawMask( OpenGLTexture& rMask, SalColor nMaskColor, const SalTwoRect& pPosAry ) { - if( mnMaskProgram == 0 ) - { - if( !CreateMaskProgram() ) - return; - } - - glUseProgram( mnMaskProgram ); - glUniformColor( mnMaskColorUniform, nMaskColor, 0 ); - glUniform1i( mnMaskUniform, 0 ); - glActiveTexture( GL_TEXTURE0 ); - rMask.Bind(); - - glEnable( GL_BLEND ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + if( !UseProgram( "textureVertexShader", "maskFragmentShader" ) ) + return; + mpProgram->SetColor( "color", nMaskColor, 0 ); + mpProgram->SetTexture( "sampler", rMask ); + mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); DrawTextureRect( rMask, pPosAry ); - glDisable( GL_BLEND ); - - rMask.Unbind(); - glUseProgram( 0 ); - - CHECK_GL_ERROR(); + mpProgram->Clean(); } void OpenGLSalGraphicsImpl::DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect ) { - if( mnLinearGradientProgram == 0 ) - { - if( !CreateLinearGradientProgram() ) - return; - } - - glUseProgram( mnLinearGradientProgram ); - + if( !UseProgram( "textureVertexShader", "linearGradientFragmentShader" ) ) + return; Color aStartCol = rGradient.GetStartColor(); Color aEndCol = rGradient.GetEndColor(); long nFactor = rGradient.GetStartIntensity(); - glUniformColorIntensity( mnLinearGradientStartColorUniform, aStartCol, nFactor ); + mpProgram->SetColorWithIntensity( "start_color", aStartCol, nFactor ); nFactor = rGradient.GetEndIntensity(); - glUniformColorIntensity( mnLinearGradientEndColorUniform, aEndCol, nFactor ); + mpProgram->SetColorWithIntensity( "end_color", aEndCol, nFactor ); Rectangle aBoundRect; Point aCenter; @@ -1098,35 +677,20 @@ void OpenGLSalGraphicsImpl::DrawLinearGradient( const Gradient& rGradient, const GLfloat aTexCoord[8] = { 0, 1, 1, 1, 1, 0, 0, 0 }; GLfloat fMin = 1.0 - 100.0 / (100.0 - rGradient.GetBorder()); aTexCoord[5] = aTexCoord[7] = fMin; - glEnableVertexAttribArray( GL_ATTRIB_TEX ); - glVertexAttribPointer( GL_ATTRIB_TEX, 2, GL_FLOAT, GL_FALSE, 0, aTexCoord ); - + mpProgram->SetTextureCoord( aTexCoord ); DrawConvexPolygon( aPoly ); - - glDisableVertexAttribArray( GL_ATTRIB_TEX ); - CHECK_GL_ERROR(); - - glUseProgram( 0 ); - - CHECK_GL_ERROR(); } void OpenGLSalGraphicsImpl::DrawAxialGradient( const Gradient& rGradient, const Rectangle& rRect ) { - if( mnLinearGradientProgram == 0 ) - { - if( !CreateLinearGradientProgram() ) - return; - } - - glUseProgram( mnLinearGradientProgram ); - + if( !UseProgram( "textureVertexShader", "linearGradientFragmentShader" ) ) + return; Color aStartCol = rGradient.GetStartColor(); Color aEndCol = rGradient.GetEndColor(); long nFactor = rGradient.GetStartIntensity(); - glUniformColorIntensity( mnLinearGradientStartColorUniform, aStartCol, nFactor ); + mpProgram->SetColorWithIntensity( "start_color", aStartCol, nFactor ); nFactor = rGradient.GetEndIntensity(); - glUniformColorIntensity( mnLinearGradientEndColorUniform, aEndCol, nFactor ); + mpProgram->SetColorWithIntensity( "end_color", aEndCol, nFactor ); /** * Draw two rectangles with linear gradient. @@ -1163,33 +727,20 @@ void OpenGLSalGraphicsImpl::DrawAxialGradient( const Gradient& rGradient, const GLfloat aTexCoord[12] = { 0, 1, 1, 0, 2, 0, 3, 1, 4, 0, 5, 0 }; GLfloat fMin = 1.0 - 100.0 / (100.0 - rGradient.GetBorder()); aTexCoord[3] = aTexCoord[5] = aTexCoord[9] = aTexCoord[11] = fMin; - glEnableVertexAttribArray( GL_ATTRIB_TEX ); - glVertexAttribPointer( GL_ATTRIB_TEX, 2, GL_FLOAT, GL_FALSE, 0, aTexCoord ); - + mpProgram->SetTextureCoord( aTexCoord ); DrawConvexPolygon( aPoly ); - - glDisableVertexAttribArray( GL_ATTRIB_TEX ); - glUseProgram( 0 ); - - CHECK_GL_ERROR(); } void OpenGLSalGraphicsImpl::DrawRadialGradient( const Gradient& rGradient, const Rectangle& rRect ) { - if( mnRadialGradientProgram == 0 ) - { - if( !CreateRadialGradientProgram() ) - return; - } - - glUseProgram( mnRadialGradientProgram ); - + if( !UseProgram( "textureVertexShader", "radialGradientFragmentShader" ) ) + return; Color aStartCol = rGradient.GetStartColor(); Color aEndCol = rGradient.GetEndColor(); long nFactor = rGradient.GetStartIntensity(); - glUniformColorIntensity( mnRadialGradientStartColorUniform, aStartCol, nFactor ); + mpProgram->SetColorWithIntensity( "start_color", aStartCol, nFactor ); nFactor = rGradient.GetEndIntensity(); - glUniformColorIntensity( mnRadialGradientEndColorUniform, aEndCol, nFactor ); + mpProgram->SetColorWithIntensity( "end_color", aEndCol, nFactor ); Rectangle aRect; Point aCenter; @@ -1199,18 +750,11 @@ void OpenGLSalGraphicsImpl::DrawRadialGradient( const Gradient& rGradient, const double fRadius = aRect.GetWidth() / 2.0f; GLfloat fWidth = rRect.GetWidth() / fRadius; GLfloat fHeight = rRect.GetHeight() / fRadius; - glUniform2f( mnRadialGradientCenterUniform, (aCenter.X() -rRect.Left()) / fRadius, (aCenter.Y() - rRect.Top()) / fRadius ); - GLfloat aTexCoord[8] = { 0, 0, 0, fHeight, fWidth, fHeight, fWidth, 0 }; - glEnableVertexAttribArray( GL_ATTRIB_TEX ); - glVertexAttribPointer( GL_ATTRIB_TEX, 2, GL_FLOAT, GL_FALSE, 0, aTexCoord ); - + mpProgram->SetTextureCoord( aTexCoord ); + mpProgram->SetUniform2f( "center", (aCenter.X() - rRect.Left()) / fRadius, + (aCenter.Y() - rRect.Top()) / fRadius ); DrawRect( rRect ); - - glDisableVertexAttribArray( GL_ATTRIB_TEX ); - glUseProgram( 0 ); - - CHECK_GL_ERROR(); } @@ -1221,9 +765,8 @@ void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY ) if( mnLineColor != SALCOLOR_NONE ) { PreDraw(); - BeginSolid( mnLineColor ); - DrawPoint( nX, nY ); - EndSolid(); + if( UseSolid( mnLineColor ) ) + DrawPoint( nX, nY ); PostDraw(); } } @@ -1234,9 +777,8 @@ void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY, SalColor nSalColor ) if( nSalColor != SALCOLOR_NONE ) { PreDraw(); - BeginSolid( nSalColor ); - DrawPoint( nX, nY ); - EndSolid(); + if( UseSolid( nSalColor ) ) + DrawPoint( nX, nY ); PostDraw(); } } @@ -1247,9 +789,8 @@ void OpenGLSalGraphicsImpl::drawLine( long nX1, long nY1, long nX2, long nY2 ) if( mnLineColor != SALCOLOR_NONE ) { PreDraw(); - BeginSolid( mnLineColor ); - DrawLine( nX1, nY1, nX2, nY2 ); - EndSolid(); + if( UseSolid( mnLineColor ) ) + DrawLine( nX1, nY1, nX2, nY2 ); PostDraw(); } } @@ -1259,14 +800,10 @@ void OpenGLSalGraphicsImpl::drawRect( long nX, long nY, long nWidth, long nHeigh SAL_INFO( "vcl.opengl", "::drawRect" ); PreDraw(); - if( mnFillColor != SALCOLOR_NONE ) - { - BeginSolid( mnFillColor ); + if( UseSolid( mnFillColor ) ) DrawRect( nX, nY, nWidth, nHeight ); - EndSolid(); - } - if( mnLineColor != SALCOLOR_NONE ) + if( UseSolid( mnLineColor ) ) { const long nX1( nX ); const long nY1( nY ); @@ -1274,10 +811,7 @@ void OpenGLSalGraphicsImpl::drawRect( long nX, long nY, long nWidth, long nHeigh const long nY2( nY + nHeight ); const SalPoint aPoints[] = { { nX1, nY1 }, { nX2, nY1 }, { nX2, nY2 }, { nX1, nY2 } }; - - BeginSolid( mnLineColor ); DrawLines( 4, aPoints, true ); - EndSolid(); } PostDraw(); @@ -1290,9 +824,8 @@ void OpenGLSalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pP if( mnLineColor != SALCOLOR_NONE && nPoints > 1 ) { PreDraw(); - BeginSolid( mnLineColor ); - DrawLines( nPoints, pPtAry, false ); - EndSolid(); + if( UseSolid( mnLineColor ) ) + DrawLines( nPoints, pPtAry, false ); PostDraw(); } } @@ -1316,19 +849,11 @@ void OpenGLSalGraphicsImpl::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPt PreDraw(); - if( mnFillColor != SALCOLOR_NONE ) - { - BeginSolid( mnFillColor ); + if( UseSolid( mnFillColor ) ) DrawPolygon( nPoints, pPtAry ); - EndSolid(); - } - if( mnLineColor != SALCOLOR_NONE ) - { - BeginSolid( mnLineColor ); + if( UseSolid( mnLineColor ) ) DrawLines( nPoints, pPtAry, true ); - EndSolid(); - } PostDraw(); } @@ -1341,21 +866,17 @@ void OpenGLSalGraphicsImpl::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* PreDraw(); - if( mnFillColor != SALCOLOR_NONE ) + if( UseSolid( mnFillColor ) ) { - BeginSolid( mnFillColor ); for( sal_uInt32 i = 0; i < nPoly; i++ ) DrawPolygon( pPoints[i], pPtAry[i] ); - EndSolid(); } - if( mnLineColor != SALCOLOR_NONE ) + if( UseSolid( mnLineColor ) ) { // TODO Use glMultiDrawElements or primitive restart - BeginSolid( mnLineColor ); for( sal_uInt32 i = 0; i < nPoly; i++ ) DrawLines( pPoints[i], pPtAry[i], true ); - EndSolid(); } PostDraw(); @@ -1369,15 +890,13 @@ bool OpenGLSalGraphicsImpl::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rP PreDraw(); - if( mnFillColor != SALCOLOR_NONE ) + if( UseSolid( mnFillColor, fTransparency ) ) { - BeginSolid( mnFillColor, fTransparency ); for( sal_uInt32 i = 0; i < rPolyPolygon.count(); i++ ) { const ::basegfx::B2DPolyPolygon aOnePoly( rPolyPolygon.getB2DPolygon( i ) ); DrawPolyPolygon( aOnePoly ); } - EndSolid(); } PostDraw(); @@ -1454,13 +973,14 @@ bool OpenGLSalGraphicsImpl::drawPolyLine( } PreDraw(); - BeginSolid( mnLineColor, fTransparency ); - for( sal_uInt32 i = 0; i < aAreaPolyPoly.count(); i++ ) + if( UseSolid( mnLineColor, fTransparency ) ) { - const ::basegfx::B2DPolyPolygon aOnePoly( aAreaPolyPoly.getB2DPolygon( i ) ); - DrawPolyPolygon( aOnePoly ); + for( sal_uInt32 i = 0; i < aAreaPolyPoly.count(); i++ ) + { + const ::basegfx::B2DPolyPolygon aOnePoly( aAreaPolyPoly.getB2DPolygon( i ) ); + DrawPolyPolygon( aOnePoly ); + } } - EndSolid(); PostDraw(); return true; @@ -1510,7 +1030,9 @@ void OpenGLSalGraphicsImpl::copyArea( aPosAry.mnSrcHeight = aPosAry.mnDestHeight = nSrcHeight; PreDraw(); - aTexture = OpenGLTexture( nSrcX, GetHeight() - nSrcY - nSrcHeight, nSrcWidth, nSrcHeight ); + // TODO offscreen case + aTexture = OpenGLTexture( nSrcX, GetHeight() - nSrcY - nSrcHeight, + nSrcWidth, nSrcHeight ); DrawTexture( aTexture, aPosAry ); PostDraw(); } @@ -1651,9 +1173,8 @@ void OpenGLSalGraphicsImpl::invert( } else // just invert { - BeginInvert(); - DrawRect( nX, nY, nWidth, nHeight ); - EndInvert(); + if( UseInvert() ) + DrawRect( nX, nY, nWidth, nHeight ); } PostDraw(); @@ -1673,9 +1194,8 @@ void OpenGLSalGraphicsImpl::invert( sal_uInt32 nPoints, const SalPoint* pPtAry, } else // just invert { - BeginInvert(); - DrawPolygon( nPoints, pPtAry ); - EndInvert(); + if( UseInvert() ) + DrawPolygon( nPoints, pPtAry ); } PostDraw(); @@ -1811,9 +1331,8 @@ bool OpenGLSalGraphicsImpl::drawAlphaRect( if( mnFillColor != SALCOLOR_NONE && nTransparency < 100 ) { PreDraw(); - BeginSolid( mnFillColor, nTransparency ); + UseSolid( mnFillColor, nTransparency ); DrawRect( nX, nY, nWidth, nHeight ); - EndSolid(); PostDraw(); } @@ -1862,10 +1381,10 @@ bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly, { Color aCol = rGradient.GetStartColor(); long nF = rGradient.GetStartIntensity(); - BeginSolid( MAKE_SALCOLOR( aCol.GetRed() * nF / 100, - aCol.GetGreen() * nF / 100, - aCol.GetBlue() * nF / 100 ) ); - DrawRect( aBoundRect ); + if( UseSolid( MAKE_SALCOLOR( aCol.GetRed() * nF / 100, + aCol.GetGreen() * nF / 100, + aCol.GetBlue() * nF / 100 ) ) ) + DrawRect( aBoundRect ); } else if( rGradient.GetStyle() == GradientStyle_LINEAR ) { diff --git a/vcl/opengl/maskVertexShader.glsl b/vcl/opengl/maskVertexShader.glsl deleted file mode 100644 index 99d7f37..0000000 --- a/vcl/opengl/maskVertexShader.glsl +++ /dev/null @@ -1,19 +0,0 @@ -/* -*- 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/. - */ - -attribute vec4 position; -attribute vec2 tex_coord_in; -varying vec2 tex_coord; - -void main() { - gl_Position = position; - tex_coord = tex_coord_in; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/opengl/maskedTextureVertexShader.glsl b/vcl/opengl/maskedTextureVertexShader.glsl deleted file mode 100644 index 99d7f37..0000000 --- a/vcl/opengl/maskedTextureVertexShader.glsl +++ /dev/null @@ -1,19 +0,0 @@ -/* -*- 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/. - */ - -attribute vec4 position; -attribute vec2 tex_coord_in; -varying vec2 tex_coord; - -void main() { - gl_Position = position; - tex_coord = tex_coord_in; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/opengl/program.cxx b/vcl/opengl/program.cxx new file mode 100644 index 0000000..c9542c7 --- /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: */ diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx index ce566b0..9fde118 100644 --- a/vcl/opengl/salbmp.cxx +++ b/vcl/opengl/salbmp.cxx @@ -43,13 +43,6 @@ OpenGLSalBitmap::OpenGLSalBitmap() , mnHeight(0) , mnBufWidth(0) , mnBufHeight(0) -, mnTexProgram(0) -, mnTexSamplerUniform(0) -, mnConvProgram(0) -, mnConvSamplerUniform(0) -, mnConvKernelUniform(0) -, mnConvKernelSizeUniform(0) -, mnConvOffsetsUniform(0) { } diff --git a/vcl/opengl/scale.cxx b/vcl/opengl/scale.cxx index d396652..7bcf7c0 100644 --- a/vcl/opengl/scale.cxx +++ b/vcl/opengl/scale.cxx @@ -25,6 +25,7 @@ #include "opengl/bmpop.hxx" #include "opengl/salbmp.hxx" +#include "opengl/program.hxx" #include "opengl/texture.hxx" class ScaleOp : public OpenGLSalBitmapOp @@ -42,75 +43,32 @@ public: void GetSize( Size& rSize ) const SAL_OVERRIDE; }; - -GLuint OpenGLSalBitmap::ImplGetTextureProgram() -{ - if( mnTexProgram == 0 ) - { - mnTexProgram = OpenGLHelper::LoadShaders( "textureVertexShader", - "textureFragmentShader" ); - if( mnTexProgram == 0 ) - return 0; - - glBindAttribLocation( mnTexProgram, 0, "position" ); - glBindAttribLocation( mnTexProgram, 1, "tex_coord_in" ); - mnTexSamplerUniform = glGetUniformLocation( mnTexProgram, "sampler" ); - } - - CHECK_GL_ERROR(); - return mnTexProgram; -} - -GLuint OpenGLSalBitmap::ImplGetConvolutionProgram() -{ - if( mnConvProgram == 0 ) - { - mnConvProgram = OpenGLHelper::LoadShaders( "textureVertexShader", - "convolutionFragmentShader" ); - if( mnConvProgram == 0 ) - return 0; - - glBindAttribLocation( mnConvProgram, 0, "position" ); - glBindAttribLocation( mnConvProgram, 1, "tex_coord_in" ); - mnConvSamplerUniform = glGetUniformLocation( mnConvProgram, "sampler" ); - mnConvKernelUniform = glGetUniformLocation( mnConvProgram, "kernel" ); - mnConvOffsetsUniform = glGetUniformLocation( mnConvProgram, "offsets" ); - } - - CHECK_GL_ERROR(); - return mnConvProgram; -} - bool OpenGLSalBitmap::ImplScaleFilter( const double& rScaleX, const double& rScaleY, GLenum nFilter ) { OpenGLFramebuffer* pFramebuffer; - GLuint nProgram; + OpenGLProgram* pProgram; GLenum nOldFilter; int nNewWidth( mnWidth * rScaleX ); int nNewHeight( mnHeight * rScaleY ); - nProgram = ImplGetTextureProgram(); - if( nProgram == 0 ) + pProgram = mpContext->UseProgram( "textureVertexShader", + "textureFragmentShader" ); + if( !pProgram ) return false; OpenGLTexture aNewTex = OpenGLTexture( nNewWidth, nNewHeight ); pFramebuffer = mpContext->AcquireFramebuffer( aNewTex ); - glUseProgram( nProgram ); - glUniform1i( mnTexSamplerUniform, 0 ); - glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); - glClear( GL_COLOR_BUFFER_BIT ); - maTexture.Bind(); + pProgram->SetTexture( "sampler", maTexture ); nOldFilter = maTexture.GetFilter(); maTexture.SetFilter( nFilter ); - maTexture.Draw(); + pProgram->DrawTexture( maTexture ); maTexture.SetFilter( nOldFilter ); - maTexture.Unbind(); + pProgram->Clean(); - glUseProgram( 0 ); mpContext->ReleaseFramebuffer( pFramebuffer ); mnWidth = nNewWidth; @@ -165,8 +123,8 @@ bool OpenGLSalBitmap::ImplScaleConvolution( const Kernel& aKernel ) { OpenGLFramebuffer* pFramebuffer; + OpenGLProgram* pProgram; GLfloat* pWeights( 0 ); - GLuint nProgram; sal_uInt32 nKernelSize; GLfloat aOffsets[32]; int nNewWidth( mnWidth * rScaleX ); @@ -174,14 +132,11 @@ bool OpenGLSalBitmap::ImplScaleConvolution( // TODO Make sure the framebuffer is alright - nProgram = ImplGetConvolutionProgram(); - if( nProgram == 0 ) + pProgram = mpContext->UseProgram( "textureVertexShader", + "convolutionFragmentShader" ); + if( pProgram == 0 ) return false; - glUseProgram( nProgram ); - glUniform1i( mnConvSamplerUniform, 0 ); - CHECK_GL_ERROR(); - // horizontal scaling in scratch texture if( mnWidth != nNewWidth ) { @@ -194,14 +149,11 @@ bool OpenGLSalBitmap::ImplScaleConvolution( aOffsets[i * 2 + 1] = 0; } ImplCreateKernel( rScaleX, aKernel, pWeights, nKernelSize ); - glUniform1fv( mnConvKernelUniform, 16, pWeights ); - CHECK_GL_ERROR(); - glUniform2fv( mnConvOffsetsUniform, 16, aOffsets ); - CHECK_GL_ERROR(); - - maTexture.Bind(); - maTexture.Draw(); - maTexture.Unbind(); + pProgram->SetUniform1fv( "kernel", 16, pWeights ); + pProgram->SetUniform2fv( "offsets", 16, aOffsets ); + pProgram->SetTexture( "sampler", maTexture ); + pProgram->DrawTexture( maTexture ); + pProgram->Clean(); maTexture = aScratchTex; mpContext->ReleaseFramebuffer( pFramebuffer ); @@ -219,20 +171,16 @@ bool OpenGLSalBitmap::ImplScaleConvolution( aOffsets[i * 2 + 1] = i / (double) mnHeight; } ImplCreateKernel( rScaleY, aKernel, pWeights, nKernelSize ); - glUniform1fv( mnConvKernelUniform, 16, pWeights ); - glUniform2fv( mnConvOffsetsUniform, 16, aOffsets ); - CHECK_GL_ERROR(); - - maTexture.Bind(); - maTexture.Draw(); - maTexture.Unbind(); + pProgram->SetUniform1fv( "kernel", 16, pWeights ); + pProgram->SetUniform2fv( "offsets", 16, aOffsets ); + pProgram->SetTexture( "sampler", maTexture ); + pProgram->DrawTexture( maTexture ); + pProgram->Clean(); maTexture = aScratchTex; mpContext->ReleaseFramebuffer( pFramebuffer ); } - glUseProgram( 0 ); - mnWidth = nNewWidth; mnHeight = nNewHeight; diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx index c8f4684..7618c04 100644 --- a/vcl/opengl/texture.cxx +++ b/vcl/opengl/texture.cxx @@ -188,6 +188,24 @@ void OpenGLTexture::GetCoord( GLfloat* pCoord, const SalTwoRect& rPosAry, bool b } } +void OpenGLTexture::GetWholeCoord( GLfloat* pCoord ) const +{ + if( GetWidth() != mpImpl->mnWidth || GetHeight() != mpImpl->mnHeight ) + { + pCoord[0] = pCoord[2] = maRect.Left() / (double) mpImpl->mnWidth; + pCoord[4] = pCoord[6] = maRect.Right() / (double) mpImpl->mnWidth; + pCoord[3] = pCoord[5] = 1.0f - maRect.Top() / (double) mpImpl->mnHeight; + pCoord[1] = pCoord[7] = 1.0f - maRect.Bottom() / (double) mpImpl->mnHeight; + } + else + { + pCoord[0] = pCoord[2] = 0; + pCoord[4] = pCoord[6] = 1; + pCoord[1] = pCoord[7] = 0; + pCoord[3] = pCoord[5] = 1; + } +} + GLenum OpenGLTexture::GetFilter() const { if( mpImpl ) @@ -226,7 +244,7 @@ void OpenGLTexture::Unbind() bool OpenGLTexture::Draw() { GLfloat aPosition[8] = { -1, -1, -1, 1, 1, 1, 1, -1 }; - GLfloat aTexCoord[8] = { 0, 0, 0, 1, 1, 1, 1, 0 }; + GLfloat aTexCoord[8]; if( mpImpl == NULL ) { @@ -235,15 +253,8 @@ bool OpenGLTexture::Draw() } SAL_INFO( "vcl.opengl", "Drawing texture " << Id() << " [" << maRect.Left() << "," << maRect.Top() << "] " << GetWidth() << "x" << GetHeight() ); - if( GetWidth() != mpImpl->mnWidth || GetHeight() != mpImpl->mnHeight ) - { - // FIXME: lfrb: check math - aTexCoord[0] = aTexCoord[2] = maRect.Left() / (double) mpImpl->mnWidth; - aTexCoord[4] = aTexCoord[6] = maRect.Right() / (double) mpImpl->mnWidth; - aTexCoord[1] = aTexCoord[7] = maRect.Top() / (double) mpImpl->mnHeight; - aTexCoord[3] = aTexCoord[5] = maRect.Bottom() / (double) mpImpl->mnHeight; - } + GetWholeCoord( aTexCoord ); glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, mpImpl->mnTexture ); glEnableVertexAttribArray( 0 ); diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx index 424d2dc..1f82b59 100644 --- a/vcl/source/opengl/OpenGLContext.cxx +++ b/vcl/source/opengl/OpenGLContext.cxx @@ -30,6 +30,7 @@ #include "svdata.hxx" #include <opengl/framebuffer.hxx> +#include <opengl/program.hxx> #include <opengl/texture.hxx> using namespace com::sun::star; @@ -59,6 +60,7 @@ OpenGLContext::OpenGLContext(): mpCurrentFramebuffer(NULL), mpFirstFramebuffer(NULL), mpLastFramebuffer(NULL), + mpCurrentProgram(NULL), mnPainting(0), mpPrevContext(NULL), mpNextContext(NULL) @@ -1382,4 +1384,37 @@ void OpenGLContext::ReleaseFramebuffer( OpenGLFramebuffer* pFramebuffer ) pFramebuffer->DetachTexture(); } +OpenGLProgram* OpenGLContext::GetProgram( const OUString& rVertexShader, const OUString& rFragmentShader ) +{ + boost::unordered_map<ProgramKey, OpenGLProgram*>::iterator it; + ProgramKey aKey( rVertexShader, rFragmentShader ); + + it = maPrograms.find( aKey ); + if( it != maPrograms.end() ) + return it->second; + + OpenGLProgram* pProgram = new OpenGLProgram; + if( !pProgram->Load( rVertexShader, rFragmentShader ) ) + { + delete pProgram; + return NULL; + } + + maPrograms[aKey] = pProgram; + return pProgram; +} + +OpenGLProgram* OpenGLContext::UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader ) +{ + OpenGLProgram* pProgram = GetProgram( rVertexShader, rFragmentShader ); + + if( pProgram == mpCurrentProgram ) + return pProgram; + + mpCurrentProgram = pProgram; + mpCurrentProgram->Use(); + + return mpCurrentProgram; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits