vcl/Library_vclplug_gtk.mk | 1 vcl/Package_opengl.mk | 2 vcl/inc/openglgdiimpl.hxx | 20 ++ vcl/opengl/gdiimpl.cxx | 212 ++++++++++++++++++++++++++- vcl/opengl/linearGradientFragmentShader.glsl | 23 ++ vcl/opengl/radialGradientFragmentShader.glsl | 23 ++ vcl/opengl/x11/gdiimpl.cxx | 33 +++- vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx | 6 8 files changed, 309 insertions(+), 11 deletions(-)
New commits: commit b49bea154047efeb9e487dde6c9742cf31c11400 Author: Louis-Francis Ratté-Boulianne <[email protected]> Date: Tue Nov 11 16:16:57 2014 -0500 vcl: Use offscreen rendering for native GTK widgets with OpenGL backend Change-Id: I142e1b34e54a3cbe149e5af9adeba1250a4ca9a9 diff --git a/vcl/Library_vclplug_gtk.mk b/vcl/Library_vclplug_gtk.mk index db2dd21..ec7f2f8 100644 --- a/vcl/Library_vclplug_gtk.mk +++ b/vcl/Library_vclplug_gtk.mk @@ -65,6 +65,7 @@ $(eval $(call gb_Library_use_externals,vclplug_gtk,\ cairo \ dbus \ gio \ + glew \ gtk \ gthread \ icuuc \ diff --git a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx index 0cf68fd..2473297 100644 --- a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx +++ b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx @@ -41,6 +41,8 @@ #include "fontmanager.hxx" #include <vcl/decoview.hxx> +#include <vcl/opengl/OpenGLHelper.hxx> + typedef struct _cairo_font_options cairo_font_options_t; const char* const tabPrelitDataName="libreoffice-tab-is-prelit"; @@ -533,6 +535,10 @@ void GtkData::initNWF( void ) if( pEnv && *pEnv ) GtkSalGraphics::bNeedPixmapPaint = true; + // use offscreen rendering when using OpenGL backend + if( OpenGLHelper::isVCLOpenGLEnabled() ) + GtkSalGraphics::bNeedPixmapPaint = true; + #if OSL_DEBUG_LEVEL > 1 std::fprintf( stderr, "GtkPlugin: using %s NWF\n", GtkSalGraphics::bNeedPixmapPaint ? "offscreen" : "direct" ); commit e1e787d5e418a328f8023d3b777384b98441a9de Author: Louis-Francis Ratté-Boulianne <[email protected]> Date: Tue Nov 11 15:54:03 2014 -0500 vcl: Add support for radial gradients in OpenGL backend Change-Id: Ie47fb18ae7d5286fe7559c7dffbc54b0856d4d8e diff --git a/vcl/Package_opengl.mk b/vcl/Package_opengl.mk index da40d71..18c56fc 100644 --- a/vcl/Package_opengl.mk +++ b/vcl/Package_opengl.mk @@ -16,6 +16,7 @@ $(eval $(call gb_Package_add_files,vcl_opengl_shader,$(LIBO_ETC_FOLDER)/opengl,\ maskVertexShader.glsl \ maskedTextureFragmentShader.glsl \ maskedTextureVertexShader.glsl \ + radialGradientFragmentShader.glsl \ solidFragmentShader.glsl \ solidVertexShader.glsl \ textureFragmentShader.glsl \ diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx index 535bc72..f80c969 100644 --- a/vcl/inc/openglgdiimpl.hxx +++ b/vcl/inc/openglgdiimpl.hxx @@ -63,13 +63,18 @@ protected: GLuint mnLinearGradientProgram; GLuint mnLinearGradientStartColorUniform; GLuint mnLinearGradientEndColorUniform; - GLuint mnLinearGradientTransformUniform; + + GLuint mnRadialGradientProgram; + GLuint mnRadialGradientStartColorUniform; + GLuint mnRadialGradientEndColorUniform; + GLuint mnRadialGradientCenterUniform; bool CreateSolidProgram( void ); bool CreateTextureProgram( void ); bool CreateMaskedTextureProgram( void ); bool CreateMaskProgram( void ); bool CreateLinearGradientProgram( void ); + bool CreateRadialGradientProgram( void ); void BeginSolid( SalColor nColor, sal_uInt8 nTransparency ); void BeginSolid( SalColor nColor, double fTransparency ); @@ -84,6 +89,7 @@ protected: void DrawConvexPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ); void DrawConvexPolygon( const Polygon& rPolygon ); void DrawRect( long nX, long nY, long nWidth, long nHeight ); + void DrawRect( const Rectangle& rRect ); void DrawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ); void DrawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon ); void DrawTextureRect( const Size& rSize, const SalTwoRect& rPosAry, bool bInverted = false ); @@ -91,6 +97,7 @@ protected: void DrawTextureWithMask( GLuint nTexture, GLuint nMask, const Size& rSize, const SalTwoRect& rPosAry ); void DrawMask( GLuint nMask, SalColor nMaskColor, const SalTwoRect& rPosAry ); void DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect ); + void DrawRadialGradient( const Gradient& rGradient, const Rectangle& rRect ); protected: // get the width of the device diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx index 65c4f30..744aa7f 100644 --- a/vcl/opengl/gdiimpl.cxx +++ b/vcl/opengl/gdiimpl.cxx @@ -75,6 +75,13 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl() , mnMaskProgram(0) , mnMaskUniform(0) , mnMaskColorUniform(0) + , mnLinearGradientProgram(0) + , mnLinearGradientStartColorUniform(0) + , mnLinearGradientEndColorUniform(0) + , mnRadialGradientProgram(0) + , mnRadialGradientStartColorUniform(0) + , mnRadialGradientEndColorUniform(0) + , mnRadialGradientCenterUniform(0) { } @@ -295,7 +302,20 @@ bool OpenGLSalGraphicsImpl::CreateLinearGradientProgram( void ) glBindAttribLocation( mnTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" ); mnLinearGradientStartColorUniform = glGetUniformLocation( mnLinearGradientProgram, "start_color" ); mnLinearGradientEndColorUniform = glGetUniformLocation( mnLinearGradientProgram, "end_color" ); - mnLinearGradientTransformUniform = glGetUniformLocation( mnLinearGradientProgram, "transform" ); + return true; +} + +bool OpenGLSalGraphicsImpl::CreateRadialGradientProgram( void ) +{ + mnRadialGradientProgram = OpenGLHelper::LoadShaders( "textureVertexShader", "radialGradientFragmentShader" ); + if( mnRadialGradientProgram == 0 ) + return false; + + glBindAttribLocation( mnTextureProgram, GL_ATTRIB_POS, "position" ); + glBindAttribLocation( mnTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" ); + mnRadialGradientStartColorUniform = glGetUniformLocation( mnRadialGradientProgram, "start_color" ); + mnRadialGradientEndColorUniform = glGetUniformLocation( mnRadialGradientProgram, "end_color" ); + mnRadialGradientCenterUniform = glGetUniformLocation( mnRadialGradientProgram, "center" ); return true; } @@ -455,6 +475,18 @@ void OpenGLSalGraphicsImpl::DrawRect( long nX, long nY, long nWidth, long nHeigh DrawConvexPolygon( 4, aPoints ); } +void OpenGLSalGraphicsImpl::DrawRect( const Rectangle& rRect ) +{ + long nX1( rRect.Left() ); + long nY1( GetHeight() - rRect.Top() ); + long nX2( rRect.Right() ); + long nY2( GetHeight() - rRect.Bottom() ); + const SalPoint aPoints[] = { { nX1, nY2 }, { nX1, nY1 }, + { nX2, nY1 }, { nX2, nY2 }}; + + DrawConvexPolygon( 4, aPoints ); +} + void OpenGLSalGraphicsImpl::DrawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) { ::basegfx::B2DPolygon aPolygon; @@ -601,18 +633,6 @@ void OpenGLSalGraphicsImpl::DrawMask( GLuint nMask, SalColor nMaskColor, const S void OpenGLSalGraphicsImpl::DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect ) { - if( rGradient.GetBorder() >= 100.0 ) - { - // border >= 100%, draw solid rectangle - Color aCol = rGradient.GetStartColor(); - long nF = rGradient.GetStartIntensity(); - BeginSolid( MAKE_SALCOLOR( aCol.GetRed() * nF / 100, - aCol.GetGreen() * nF / 100, - aCol.GetBlue() * nF / 100 ) ); - DrawRect( rRect.Left(), rRect.Top(), rRect.GetWidth(), rRect.GetHeight() ); - EndSolid(); - return; - } if( mnLinearGradientProgram == 0 ) { @@ -632,10 +652,6 @@ void OpenGLSalGraphicsImpl::DrawLinearGradient( const Gradient& rGradient, const Rectangle aBoundRect; Point aCenter; rGradient.GetBoundRect( rRect, aBoundRect, aCenter ); - aBoundRect.Left()--; - aBoundRect.Top()--; - aBoundRect.Right()++; - aBoundRect.Bottom()++; Polygon aPoly( aBoundRect ); aPoly.Rotate( aCenter, rGradient.GetAngle() % 3600 ); @@ -653,6 +669,43 @@ void OpenGLSalGraphicsImpl::DrawLinearGradient( const Gradient& rGradient, const glUseProgram( 0 ); } +void OpenGLSalGraphicsImpl::DrawRadialGradient( const Gradient& rGradient, const Rectangle& rRect ) +{ + if( mnRadialGradientProgram == 0 ) + { + if( !CreateRadialGradientProgram() ) + return; + } + + glUseProgram( mnRadialGradientProgram ); + + Color aStartCol = rGradient.GetStartColor(); + Color aEndCol = rGradient.GetEndColor(); + long nFactor = rGradient.GetStartIntensity(); + glUniformColorIntensity( mnRadialGradientStartColorUniform, aStartCol, nFactor ); + nFactor = rGradient.GetEndIntensity(); + glUniformColorIntensity( mnRadialGradientEndColorUniform, aEndCol, nFactor ); + + Rectangle aRect; + Point aCenter; + rGradient.GetBoundRect( rRect, aRect, aCenter ); + + // adjust coordinates so that radius has distance equals to 1.0 + 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 ); + + DrawRect( rRect ); + + glDisableVertexAttribArray( GL_ATTRIB_TEX ); + glUseProgram( 0 ); +} + // draw --> LineColor and FillColor and RasterOp and ClipRegion void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY ) @@ -1189,11 +1242,33 @@ bool OpenGLSalGraphicsImpl::drawAlphaRect( bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient) { - const Rectangle aBoundRect( rPolyPoly.GetBoundRect() ); + Rectangle aBoundRect( rPolyPoly.GetBoundRect() ); + + SAL_INFO( "vcl.opengl", "::drawGradient" ); if( aBoundRect.IsEmpty() ) return true; + aBoundRect.Left()--; + aBoundRect.Top()--; + aBoundRect.Right()++; + aBoundRect.Bottom()++; + + // if border >= 100%, draw solid rectangle with start color + if( rGradient.GetBorder() >= 100.0 ) + { + Color aCol = rGradient.GetStartColor(); + long nF = rGradient.GetStartIntensity(); + PreDraw(); + BeginSolid( MAKE_SALCOLOR( aCol.GetRed() * nF / 100, + aCol.GetGreen() * nF / 100, + aCol.GetBlue() * nF / 100 ) ); + DrawRect( aBoundRect ); + EndSolid(); + PostDraw(); + return true; + } + //TODO: lfrb: some missing transformation with the polygon in outdev if( rGradient.GetStyle() == GradientStyle_LINEAR ) { @@ -1202,6 +1277,13 @@ bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly, PostDraw(); return true; } + else if( rGradient.GetStyle() == GradientStyle_RADIAL ) + { + PreDraw(); + DrawRadialGradient( rGradient, aBoundRect ); + PostDraw(); + return true; + } return false; } diff --git a/vcl/opengl/radialGradientFragmentShader.glsl b/vcl/opengl/radialGradientFragmentShader.glsl new file mode 100644 index 0000000..94a86eb --- /dev/null +++ b/vcl/opengl/radialGradientFragmentShader.glsl @@ -0,0 +1,23 @@ +/* -*- 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/. + */ + +#version 120 + +uniform vec4 start_color; +uniform vec4 end_color; +uniform vec2 center; +varying vec2 tex_coord; + +void main(void) +{ + gl_FragColor = mix(end_color, start_color, + clamp(distance(tex_coord, center), 0.0, 1.0)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 74c3dbe87e7256f8f8b3eac3a34415780035f465 Author: Louis-Francis Ratté-Boulianne <[email protected]> Date: Tue Nov 11 13:43:56 2014 -0500 vcl: Read back OpenGL FBO to create offscreen X11 pixmap Change-Id: I330e7d62bf31b4a90b5866d9531f073f7c69c92a diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx index c9e8b68..535bc72 100644 --- a/vcl/inc/openglgdiimpl.hxx +++ b/vcl/inc/openglgdiimpl.hxx @@ -86,8 +86,8 @@ protected: void DrawRect( long nX, long nY, long nWidth, long nHeight ); void DrawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ); void DrawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon ); - void DrawTextureRect( const Size& rSize, const SalTwoRect& rPosAry ); - void DrawTexture( GLuint nTexture, const Size& rSize, const SalTwoRect& rPosAry ); + void DrawTextureRect( const Size& rSize, const SalTwoRect& rPosAry, bool bInverted = false ); + void DrawTexture( GLuint nTexture, const Size& rSize, const SalTwoRect& rPosAry, bool bInverted = false ); void DrawTextureWithMask( GLuint nTexture, GLuint nMask, const Size& rSize, const SalTwoRect& rPosAry ); void DrawMask( GLuint nMask, SalColor nMaskColor, const SalTwoRect& rPosAry ); void DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect ); diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx index 72387e2..65c4f30 100644 --- a/vcl/opengl/gdiimpl.cxx +++ b/vcl/opengl/gdiimpl.cxx @@ -503,14 +503,23 @@ void OpenGLSalGraphicsImpl::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rPol glDisableVertexAttribArray( GL_ATTRIB_POS ); } -void OpenGLSalGraphicsImpl::DrawTextureRect( const Size& rSize, const SalTwoRect& rPosAry ) +void OpenGLSalGraphicsImpl::DrawTextureRect( const Size& rSize, const SalTwoRect& rPosAry, bool bInverted ) { GLfloat aTexCoord[8]; aTexCoord[0] = aTexCoord[2] = rPosAry.mnSrcX / (double) rSize.Width(); aTexCoord[4] = aTexCoord[6] = (rPosAry.mnSrcX + rPosAry.mnSrcWidth) / (double) rSize.Width(); - aTexCoord[3] = aTexCoord[5] = (rSize.Height() - rPosAry.mnSrcY) / (double) rSize.Height(); - aTexCoord[1] = aTexCoord[7] = (rSize.Height() - rPosAry.mnSrcY - rPosAry.mnSrcHeight) / (double) rSize.Height(); + + if( !bInverted ) + { + aTexCoord[3] = aTexCoord[5] = (rSize.Height() - rPosAry.mnSrcY) / (double) rSize.Height(); + aTexCoord[1] = aTexCoord[7] = (rSize.Height() - rPosAry.mnSrcY - rPosAry.mnSrcHeight) / (double) rSize.Height(); + } + else + { + aTexCoord[1] = aTexCoord[7] = (rSize.Height() - rPosAry.mnSrcY) / (double) rSize.Height(); + aTexCoord[3] = aTexCoord[5] = (rSize.Height() - rPosAry.mnSrcY - rPosAry.mnSrcHeight) / (double) rSize.Height(); + } glEnableVertexAttribArray( GL_ATTRIB_TEX ); glVertexAttribPointer( GL_ATTRIB_TEX, 2, GL_FLOAT, GL_FALSE, 0, aTexCoord ); @@ -520,7 +529,7 @@ void OpenGLSalGraphicsImpl::DrawTextureRect( const Size& rSize, const SalTwoRect glDisableVertexAttribArray( GL_ATTRIB_TEX ); } -void OpenGLSalGraphicsImpl::DrawTexture( GLuint nTexture, const Size& rSize, const SalTwoRect& pPosAry ) +void OpenGLSalGraphicsImpl::DrawTexture( GLuint nTexture, const Size& rSize, const SalTwoRect& pPosAry, bool bInverted ) { if( mnTextureProgram == 0 ) { @@ -534,7 +543,7 @@ void OpenGLSalGraphicsImpl::DrawTexture( GLuint nTexture, const Size& rSize, con CHECK_GL_ERROR(); glBindTexture( GL_TEXTURE_2D, nTexture ); - DrawTextureRect( rSize, pPosAry ); + DrawTextureRect( rSize, pPosAry, bInverted ); CHECK_GL_ERROR(); glBindTexture( GL_TEXTURE_2D, 0 ); diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx index 6e803bd..13b7049 100644 --- a/vcl/opengl/x11/gdiimpl.cxx +++ b/vcl/opengl/x11/gdiimpl.cxx @@ -83,9 +83,38 @@ X11Pixmap* X11OpenGLSalGraphicsImpl::GetPixmapFromScreen( const Rectangle& rRect { Display* pDisplay = mrParent.GetXDisplay(); SalX11Screen nScreen = mrParent.GetScreenNumber(); + XVisualInfo aVisualInfo; + X11Pixmap* pPixmap; + XImage* pImage; + sal_uInt8* pData; SAL_INFO( "vcl.opengl", "GetPixmapFromScreen" ); - return new X11Pixmap( pDisplay, nScreen, rRect.GetWidth(), rRect.GetHeight(), 24 ); + // TODO: lfrb: Use context depth + pPixmap = new X11Pixmap( pDisplay, nScreen, rRect.GetWidth(), rRect.GetHeight(), 24 ); + + if( !OpenGLHelper::GetVisualInfo( pDisplay, nScreen.getXScreen(), aVisualInfo ) ) + return pPixmap; + + // make sure everything is synced up before reading back + maContext.makeCurrent(); + glXWaitX(); + + // TODO: lfrb: What if offscreen? + pData = new sal_uInt8[rRect.GetWidth() * rRect.GetHeight() * 4]; + glPixelStorei( GL_PACK_ALIGNMENT, 1 ); + glReadPixels( rRect.Left(), GetHeight() - rRect.Top(), rRect.GetWidth(), rRect.GetHeight(), + GL_RGBA, GL_UNSIGNED_BYTE, pData ); + + pImage = XCreateImage( pDisplay, aVisualInfo.visual, 24, ZPixmap, 0, (char*) pData, + rRect.GetWidth(), rRect.GetHeight(), 8, 0 ); + XInitImage( pImage ); + GC aGC = XCreateGC( pDisplay, pPixmap->GetPixmap(), 0, NULL ); + XPutImage( pDisplay, pPixmap->GetDrawable(), aGC, pImage, + 0, 0, 0, 0, rRect.GetWidth(), rRect.GetHeight() ); + XFreeGC( pDisplay, aGC ); + XDestroyImage( pImage ); + + return pPixmap; } bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) @@ -128,7 +157,7 @@ bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - DrawTexture( nTexture, pPixmap->GetSize(), aPosAry ); + DrawTexture( nTexture, pPixmap->GetSize(), aPosAry, !bInverted ); glXReleaseTexImageEXT( pDisplay, pGlxPixmap, GLX_FRONT_LEFT_EXT ); glDeleteTextures( 1, &nTexture ); commit c7a5ce27e6d27af4d868dedcde1f650fa129e6f8 Author: Louis-Francis Ratté-Boulianne <[email protected]> Date: Tue Nov 11 05:13:40 2014 -0500 vcl: Add initial support for linear gradient with OpenGL Change-Id: Iccc12c94bfd68387dfc0161a5fde4f595edda0e1 diff --git a/vcl/Package_opengl.mk b/vcl/Package_opengl.mk index 79dabb7..da40d71 100644 --- a/vcl/Package_opengl.mk +++ b/vcl/Package_opengl.mk @@ -11,6 +11,7 @@ $(eval $(call gb_Package_Package,vcl_opengl_shader,$(SRCDIR)/vcl/opengl)) $(eval $(call gb_Package_add_files,vcl_opengl_shader,$(LIBO_ETC_FOLDER)/opengl,\ convolutionFragmentShader.glsl \ + linearGradientFragmentShader.glsl \ maskFragmentShader.glsl \ maskVertexShader.glsl \ maskedTextureFragmentShader.glsl \ diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx index 6f920e5..c9e8b68 100644 --- a/vcl/inc/openglgdiimpl.hxx +++ b/vcl/inc/openglgdiimpl.hxx @@ -25,6 +25,7 @@ #include "opengl/texture.hxx" +#include <tools/poly.hxx> #include <vcl/opengl/OpenGLContext.hxx> class SalFrame; @@ -59,10 +60,16 @@ protected: GLuint mnMaskUniform; GLuint mnMaskColorUniform; + GLuint mnLinearGradientProgram; + GLuint mnLinearGradientStartColorUniform; + GLuint mnLinearGradientEndColorUniform; + GLuint mnLinearGradientTransformUniform; + bool CreateSolidProgram( void ); bool CreateTextureProgram( void ); bool CreateMaskedTextureProgram( void ); bool CreateMaskProgram( void ); + bool CreateLinearGradientProgram( void ); void BeginSolid( SalColor nColor, sal_uInt8 nTransparency ); void BeginSolid( SalColor nColor, double fTransparency ); @@ -75,6 +82,7 @@ protected: void DrawLine( long nX1, long nY1, long nX2, long nY2 ); void DrawLines( sal_uInt32 nPoints, const SalPoint* pPtAry, bool bClose ); void DrawConvexPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ); + void DrawConvexPolygon( const Polygon& rPolygon ); void DrawRect( long nX, long nY, long nWidth, long nHeight ); void DrawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ); void DrawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon ); @@ -82,6 +90,7 @@ protected: void DrawTexture( GLuint nTexture, const Size& rSize, const SalTwoRect& rPosAry ); void DrawTextureWithMask( GLuint nTexture, GLuint nMask, const Size& rSize, const SalTwoRect& rPosAry ); void DrawMask( GLuint nMask, SalColor nMaskColor, const SalTwoRect& rPosAry ); + void DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect ); protected: // get the width of the device diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx index 2cf9806..72387e2 100644 --- a/vcl/opengl/gdiimpl.cxx +++ b/vcl/opengl/gdiimpl.cxx @@ -51,6 +51,13 @@ ((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() : mpFrame(NULL) , mbOffscreen(false) @@ -278,6 +285,20 @@ bool OpenGLSalGraphicsImpl::CreateMaskProgram( void ) return true; } +bool OpenGLSalGraphicsImpl::CreateLinearGradientProgram( void ) +{ + mnLinearGradientProgram = OpenGLHelper::LoadShaders( "textureVertexShader", "linearGradientFragmentShader" ); + if( mnLinearGradientProgram == 0 ) + return false; + + glBindAttribLocation( mnTextureProgram, GL_ATTRIB_POS, "position" ); + glBindAttribLocation( mnTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" ); + mnLinearGradientStartColorUniform = glGetUniformLocation( mnLinearGradientProgram, "start_color" ); + mnLinearGradientEndColorUniform = glGetUniformLocation( mnLinearGradientProgram, "end_color" ); + mnLinearGradientTransformUniform = glGetUniformLocation( mnLinearGradientProgram, "transform" ); + return true; +} + void OpenGLSalGraphicsImpl::BeginSolid( SalColor nColor, sal_uInt8 nTransparency ) { if( mnSolidProgram == 0 ) @@ -403,6 +424,25 @@ void OpenGLSalGraphicsImpl::DrawConvexPolygon( sal_uInt32 nPoints, const SalPoin glDisableVertexAttribArray( GL_ATTRIB_POS ); } +void OpenGLSalGraphicsImpl::DrawConvexPolygon( const Polygon& rPolygon ) +{ + sal_uInt16 nPoints = rPolygon.GetSize() - 1; + std::vector<GLfloat> aVertices(nPoints * 2); + sal_uInt32 i, j; + + for( i = 0, j = 0; i < nPoints; i++, j += 2 ) + { + const Point& rPt = rPolygon.GetPoint( i ); + aVertices[j] = (2 * rPt.X()) / GetWidth() - 1.0; + aVertices[j+1] = (2 * (GetHeight() - rPt.Y())) / GetHeight() - 1.0; + } + + glEnableVertexAttribArray( GL_ATTRIB_POS ); + glVertexAttribPointer( GL_ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, &aVertices[0] ); + glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints ); + glDisableVertexAttribArray( GL_ATTRIB_POS ); +} + void OpenGLSalGraphicsImpl::DrawRect( long nX, long nY, long nWidth, long nHeight ) { long nX1( nX ); @@ -550,6 +590,60 @@ void OpenGLSalGraphicsImpl::DrawMask( GLuint nMask, SalColor nMaskColor, const S glUseProgram( 0 ); } +void OpenGLSalGraphicsImpl::DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect ) +{ + if( rGradient.GetBorder() >= 100.0 ) + { + // border >= 100%, draw solid rectangle + Color aCol = rGradient.GetStartColor(); + long nF = rGradient.GetStartIntensity(); + BeginSolid( MAKE_SALCOLOR( aCol.GetRed() * nF / 100, + aCol.GetGreen() * nF / 100, + aCol.GetBlue() * nF / 100 ) ); + DrawRect( rRect.Left(), rRect.Top(), rRect.GetWidth(), rRect.GetHeight() ); + EndSolid(); + return; + } + + if( mnLinearGradientProgram == 0 ) + { + if( !CreateLinearGradientProgram() ) + return; + } + + glUseProgram( mnLinearGradientProgram ); + + Color aStartCol = rGradient.GetStartColor(); + Color aEndCol = rGradient.GetEndColor(); + long nFactor = rGradient.GetStartIntensity(); + glUniformColorIntensity( mnLinearGradientStartColorUniform, aStartCol, nFactor ); + nFactor = rGradient.GetEndIntensity(); + glUniformColorIntensity( mnLinearGradientEndColorUniform, aEndCol, nFactor ); + + Rectangle aBoundRect; + Point aCenter; + rGradient.GetBoundRect( rRect, aBoundRect, aCenter ); + aBoundRect.Left()--; + aBoundRect.Top()--; + aBoundRect.Right()++; + aBoundRect.Bottom()++; + Polygon aPoly( aBoundRect ); + aPoly.Rotate( aCenter, rGradient.GetAngle() % 3600 ); + + 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 ); + + DrawConvexPolygon( aPoly ); + + glDisableVertexAttribArray( GL_ATTRIB_TEX ); + CHECK_GL_ERROR(); + + glUseProgram( 0 ); +} + // draw --> LineColor and FillColor and RasterOp and ClipRegion void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY ) @@ -1083,9 +1177,22 @@ bool OpenGLSalGraphicsImpl::drawAlphaRect( return true; } -bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& /*rPolygon*/, - const Gradient& /*rGradient*/) +bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly, + const Gradient& rGradient) { + const Rectangle aBoundRect( rPolyPoly.GetBoundRect() ); + + if( aBoundRect.IsEmpty() ) + return true; + + //TODO: lfrb: some missing transformation with the polygon in outdev + if( rGradient.GetStyle() == GradientStyle_LINEAR ) + { + PreDraw(); + DrawLinearGradient( rGradient, aBoundRect ); + PostDraw(); + return true; + } return false; } diff --git a/vcl/opengl/linearGradientFragmentShader.glsl b/vcl/opengl/linearGradientFragmentShader.glsl new file mode 100644 index 0000000..7b84c06 --- /dev/null +++ b/vcl/opengl/linearGradientFragmentShader.glsl @@ -0,0 +1,23 @@ +/* -*- 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/. + */ + +#version 120 + +uniform vec4 start_color; +uniform vec4 end_color; +uniform mat3x3 transform; +varying vec2 tex_coord; + +void main(void) +{ + gl_FragColor = mix(start_color, end_color, + clamp(tex_coord.t, 0.0, 1.0)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
_______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
