[Libreoffice-commits] core.git: 4 commits - vcl/inc vcl/Library_vclplug_gtk.mk vcl/opengl vcl/Package_opengl.mk vcl/unx
Louis-Francis Ratté-Boulianne
lfrb at collabora.com
Tue Nov 11 20:59:31 PST 2014
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 <lfrb at collabora.com>
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 <lfrb at collabora.com>
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 <lfrb at collabora.com>
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 <lfrb at collabora.com>
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: */
More information about the Libreoffice-commits
mailing list