[Libreoffice-commits] core.git: Branch 'feature/opengl-vcl' - vcl/inc vcl/opengl vcl/Package_opengl.mk

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Tue Nov 11 02:15:56 PST 2014


 vcl/Package_opengl.mk                        |    1 
 vcl/inc/openglgdiimpl.hxx                    |    9 ++
 vcl/opengl/gdiimpl.cxx                       |  111 ++++++++++++++++++++++++++-
 vcl/opengl/linearGradientFragmentShader.glsl |   23 +++++
 4 files changed, 142 insertions(+), 2 deletions(-)

New commits:
commit 2e9e71ca3ece1cba70b6b12d0aa0d67bb0b89caf
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 5856fb8..b00fa41 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 )
@@ -1080,9 +1174,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