diff options
-rw-r--r-- | vcl/Package_opengl.mk | 1 | ||||
-rw-r--r-- | vcl/inc/openglgdiimpl.hxx | 14 | ||||
-rw-r--r-- | vcl/opengl/gdiimpl.cxx | 161 | ||||
-rw-r--r-- | vcl/opengl/transformedTextureVertexShader.glsl | 24 |
4 files changed, 189 insertions, 11 deletions
diff --git a/vcl/Package_opengl.mk b/vcl/Package_opengl.mk index 18c56fcd07b8..9151d94b675d 100644 --- a/vcl/Package_opengl.mk +++ b/vcl/Package_opengl.mk @@ -21,6 +21,7 @@ $(eval $(call gb_Package_add_files,vcl_opengl_shader,$(LIBO_ETC_FOLDER)/opengl,\ solidVertexShader.glsl \ textureFragmentShader.glsl \ textureVertexShader.glsl \ + transformedTextureVertexShader.glsl \ )) # vim: set noet sw=4 ts=4: diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx index 80d760a69796..29bc7a23d6a7 100644 --- a/vcl/inc/openglgdiimpl.hxx +++ b/vcl/inc/openglgdiimpl.hxx @@ -56,6 +56,17 @@ protected: GLuint mnTextureProgram; GLuint mnSamplerUniform; + GLuint mnTransformedTextureProgram; + GLuint mnTransformedViewportUniform; + GLuint mnTransformedTransformUniform; + GLuint mnTransformedSamplerUniform; + + GLuint mnTransformedMaskedTextureProgram; + GLuint mnTransformedMaskedViewportUniform; + GLuint mnTransformedMaskedTransformUniform; + GLuint mnTransformedMaskedSamplerUniform; + GLuint mnTransformedMaskedMaskUniform; + GLuint mnMaskedTextureProgram; GLuint mnMaskedSamplerUniform; GLuint mnMaskSamplerUniform; @@ -79,7 +90,9 @@ protected: bool CreateSolidProgram( void ); bool CreateTextureProgram( void ); + bool CreateTransformedTextureProgram( void ); bool CreateMaskedTextureProgram( void ); + bool CreateTransformedMaskedTextureProgram( void ); bool CreateMaskProgram( void ); bool CreateLinearGradientProgram( void ); bool CreateRadialGradientProgram( void ); @@ -103,6 +116,7 @@ public: void DrawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon ); void DrawTextureRect( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted = false ); void DrawTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted = false ); + void DrawTransformedTexture( OpenGLTexture& rTexture, OpenGLTexture& rMask, const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX, const basegfx::B2DPoint& rY ); void DrawAlphaTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted = false, bool pPremultiplied = false ); void DrawTextureWithMask( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry ); void DrawMask( OpenGLTexture& rTexture, SalColor nMaskColor, const SalTwoRect& rPosAry ); diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx index 9ed40b6e643d..339f3c6bb571 100644 --- a/vcl/opengl/gdiimpl.cxx +++ b/vcl/opengl/gdiimpl.cxx @@ -33,6 +33,8 @@ #include "salgdi.hxx" #include "opengl/salbmp.hxx" +#include <glm/glm.hpp> +#include <glm/gtc/type_ptr.hpp> #include <vector> #define GL_ATTRIB_POS 0 @@ -72,6 +74,15 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl() , mnColorUniform(0) , mnTextureProgram(0) , mnSamplerUniform(0) + , mnTransformedTextureProgram(0) + , mnTransformedViewportUniform(0) + , mnTransformedTransformUniform(0) + , mnTransformedSamplerUniform(0) + , mnTransformedMaskedTextureProgram(0) + , mnTransformedMaskedViewportUniform(0) + , mnTransformedMaskedTransformUniform(0) + , mnTransformedMaskedSamplerUniform(0) + , mnTransformedMaskedMaskUniform(0) , mnMaskedTextureProgram(0) , mnMaskedSamplerUniform(0) , mnMaskSamplerUniform(0) @@ -338,6 +349,22 @@ bool OpenGLSalGraphicsImpl::CreateTextureProgram( void ) 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::CreateMaskedTextureProgram( void ) { mnMaskedTextureProgram = OpenGLHelper::LoadShaders( "maskedTextureVertexShader", "maskedTextureFragmentShader" ); @@ -353,14 +380,31 @@ bool OpenGLSalGraphicsImpl::CreateMaskedTextureProgram( void ) return true; } +bool OpenGLSalGraphicsImpl::CreateTransformedMaskedTextureProgram( void ) +{ + mnTransformedMaskedTextureProgram = OpenGLHelper::LoadShaders( "transformedTextureVertexShader", "maskedTextureFragmentShader" ); + if( mnTransformedMaskedTextureProgram == 0 ) + 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(); + return true; +} + bool OpenGLSalGraphicsImpl::CreateMaskProgram( void ) { - mnMaskedTextureProgram = OpenGLHelper::LoadShaders( "maskVertexShader", "maskFragmentShader" ); - if( mnMaskedTextureProgram == 0 ) + mnMaskProgram = OpenGLHelper::LoadShaders( "maskVertexShader", "maskFragmentShader" ); + if( mnMaskProgram == 0 ) return false; - glBindAttribLocation( mnTextureProgram, GL_ATTRIB_POS, "position" ); - glBindAttribLocation( mnTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" ); + glBindAttribLocation( mnMaskProgram, GL_ATTRIB_POS, "position" ); + glBindAttribLocation( mnMaskProgram, GL_ATTRIB_TEX, "tex_coord_in" ); mnMaskUniform = glGetUniformLocation( mnMaskProgram, "sampler" ); mnMaskColorUniform = glGetUniformLocation( mnMaskProgram, "mask" ); @@ -675,6 +719,88 @@ void OpenGLSalGraphicsImpl::DrawTexture( OpenGLTexture& rTexture, const SalTwoRe CHECK_GL_ERROR(); } +void OpenGLSalGraphicsImpl::DrawTransformedTexture( + OpenGLTexture& rTexture, + OpenGLTexture& rMask, + const basegfx::B2DPoint& rNull, + 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(); + rMask.SetFilter( GL_LINEAR ); + glEnable( GL_BLEND ); + glBlendFunc( 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 ); + } + + glActiveTexture( GL_TEXTURE0 ); + rTexture.Bind(); + 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] ); + 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(); +} + void OpenGLSalGraphicsImpl::DrawAlphaTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted, bool bPremultiplied ) { glEnable( GL_BLEND ); @@ -1390,13 +1516,26 @@ bool OpenGLSalGraphicsImpl::drawAlphaBitmap( /** draw transformed bitmap (maybe with alpha) where Null, X, Y define the coordinate system */ bool OpenGLSalGraphicsImpl::drawTransformedBitmap( - const basegfx::B2DPoint& /*rNull*/, - const basegfx::B2DPoint& /*rX*/, - const basegfx::B2DPoint& /*rY*/, - const SalBitmap& /*rSourceBitmap*/, - const SalBitmap* /*pAlphaBitmap*/) -{ - return false; + const basegfx::B2DPoint& rNull, + const basegfx::B2DPoint& rX, + const basegfx::B2DPoint& rY, + const SalBitmap& rSrcBitmap, + const SalBitmap* pAlphaBitmap) +{ + const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSrcBitmap); + const OpenGLSalBitmap* pMaskBitmap = static_cast<const OpenGLSalBitmap*>(pAlphaBitmap); + OpenGLTexture& rTexture( rBitmap.GetTexture( maContext ) ); + OpenGLTexture aMask; // no texture + + if( pMaskBitmap != NULL ) + aMask = pMaskBitmap->GetTexture( maContext ); + + SAL_INFO( "vcl.opengl", "::drawTransformedBitmap" ); + PreDraw(); + DrawTransformedTexture( rTexture, aMask, rNull, rX, rY ); + PostDraw(); + + return true; } /** Render solid rectangle with given transparency diff --git a/vcl/opengl/transformedTextureVertexShader.glsl b/vcl/opengl/transformedTextureVertexShader.glsl new file mode 100644 index 000000000000..51485a068871 --- /dev/null +++ b/vcl/opengl/transformedTextureVertexShader.glsl @@ -0,0 +1,24 @@ +/* -*- 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; +uniform vec2 viewport; +uniform mat4 transform; +varying vec2 tex_coord; + +void main() { + vec4 pos = transform * position; + pos.x = (2.0 * pos.x) / viewport.x - 1.0; + pos.y = 1.0 - (2.0 * pos.y / viewport.y); + gl_Position = pos; + tex_coord = tex_coord_in; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |