[Libreoffice-commits] core.git: 22 commits - include/vcl officecfg/registry sfx2/source unotools/source vcl/generic vcl/headless vcl/inc vcl/opengl vcl/Package_opengl.mk vcl/quartz vcl/source vcl/unx vcl/win

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Sat Nov 22 11:14:45 PST 2014


 include/vcl/opengl/OpenGLContext.hxx                    |   11 
 include/vcl/outdev.hxx                                  |    4 
 officecfg/registry/data/org/openoffice/Office/Views.xcu |   12 
 sfx2/source/appl/childwin.cxx                           |    1 
 sfx2/source/sidebar/SidebarChildWindow.cxx              |   30 
 sfx2/source/sidebar/SidebarController.cxx               |   78 -
 unotools/source/config/viewoptions.cxx                  |   10 
 vcl/Package_opengl.mk                                   |    3 
 vcl/generic/print/genpspgraphics.cxx                    |   10 
 vcl/headless/svpgdi.cxx                                 |   10 
 vcl/inc/generic/genpspgraphics.h                        |    6 
 vcl/inc/headless/svpgdi.hxx                             |    5 
 vcl/inc/opengl/win/gdiimpl.hxx                          |    9 
 vcl/inc/opengl/x11/gdiimpl.hxx                          |    8 
 vcl/inc/openglgdiimpl.hxx                               |   51 +
 vcl/inc/quartz/salgdi.h                                 |    8 
 vcl/inc/regionband.hxx                                  |    2 
 vcl/inc/salgdi.hxx                                      |   24 
 vcl/inc/salgdiimpl.hxx                                  |   12 
 vcl/inc/svdata.hxx                                      |    3 
 vcl/inc/unx/gtk/gtkgdi.hxx                              |   14 
 vcl/inc/unx/salgdi.h                                    |   10 
 vcl/inc/unx/x11/x11gdiimpl.h                            |    3 
 vcl/inc/win/salgdi.h                                    |    9 
 vcl/opengl/blendedTextureFragmentShader.glsl            |   27 
 vcl/opengl/blendedTextureVertexShader.glsl              |   22 
 vcl/opengl/diffTextureFragmentShader.glsl               |   26 
 vcl/opengl/gdiimpl.cxx                                  |  431 ++++++++--
 vcl/opengl/scale.cxx                                    |    2 
 vcl/opengl/texture.cxx                                  |    1 
 vcl/opengl/win/gdiimpl.cxx                              |   30 
 vcl/opengl/x11/gdiimpl.cxx                              |   94 +-
 vcl/quartz/salgdicommon.cxx                             |   14 
 vcl/source/gdi/regionband.cxx                           |    2 
 vcl/source/gdi/salgdilayout.cxx                         |   30 
 vcl/source/opengl/OpenGLContext.cxx                     |   39 
 vcl/source/outdev/bitmap.cxx                            |   27 
 vcl/source/outdev/gradient.cxx                          |   19 
 vcl/unx/generic/gdi/gdiimpl.cxx                         |   15 
 vcl/unx/generic/gdi/gdiimpl.hxx                         |   14 
 vcl/unx/generic/gdi/salgdi.cxx                          |    2 
 vcl/unx/generic/gdi/salgdi2.cxx                         |   18 
 vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx                |  685 +++++++++-------
 vcl/unx/kde/salnativewidgets-kde.cxx                    |    2 
 vcl/win/source/gdi/gdiimpl.cxx                          |   20 
 vcl/win/source/gdi/gdiimpl.hxx                          |   12 
 vcl/win/source/gdi/salgdi.cxx                           |   10 
 vcl/win/source/gdi/salgdi_gdiplus.cxx                   |   16 
 48 files changed, 1364 insertions(+), 527 deletions(-)

New commits:
commit 357011b5baef0b9b0b966e84ea2494aa81845e45
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Sat Nov 22 08:11:33 2014 -0500

    vcl: Make sure the active framebuffer is the right one before drawing
    
    Change-Id: Icc30bee1d58dbf8f5e7b65ba90cfdf0c9135b464

diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index d4e0917..1c420e7 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -212,6 +212,9 @@ void OpenGLSalGraphicsImpl::PreDraw()
     // TODO: lfrb: make sure the render target has the right size
     if( mbOffscreen )
         CheckOffscreenTexture();
+    else
+        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+    CHECK_GL_ERROR();
     glViewport( 0, 0, GetWidth(), GetHeight() );
     ImplInitClipRegion();
 
commit bee1ac1305eb9299545b6a6c85ea4e9212065543
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Sat Nov 22 08:10:48 2014 -0500

    vcl: Re-flip native X11 widgets upside down in OpenGL backend
    
    Change-Id: I1819f8e3357dc2f805b0ecebca0659fe073ec611

diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx
index 0a8bf68..0818c59 100644
--- a/vcl/opengl/x11/gdiimpl.cxx
+++ b/vcl/opengl/x11/gdiimpl.cxx
@@ -199,14 +199,14 @@ bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixm
         glXBindTexImageEXT( pDisplay, pGlxMask, GLX_FRONT_LEFT_EXT, NULL );
         aMaskTexture.Unbind();
 
-        DrawTextureDiff( aTexture, aMaskTexture, aPosAry, !bInverted );
+        DrawTextureDiff( aTexture, aMaskTexture, aPosAry, bInverted );
 
         glXReleaseTexImageEXT( pDisplay, pGlxMask, GLX_FRONT_LEFT_EXT );
         glXDestroyPixmap( pDisplay, pGlxMask );
     }
     else
     {
-        DrawTexture( aTexture, aPosAry, !bInverted );
+        DrawTexture( aTexture, aPosAry, bInverted );
     }
 
     CHECK_GL_ERROR();
commit 7a64d1e1ccc190c145c298cb74b3b5ee9bf338e2
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Sat Nov 22 08:09:29 2014 -0500

    vcl: Improve precision and performance of clipping when region is a RegionBand
    
    Change-Id: I7a481ba86d03b0eb8f4b456e38cfa89b6cbc209d

diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index 85ec262..83c5bdb 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -24,6 +24,7 @@
 #include <vcl/dllapi.h>
 
 #include "opengl/texture.hxx"
+#include "regionband.hxx"
 
 #include <tools/poly.hxx>
 #include <vcl/opengl/OpenGLContext.hxx>
@@ -125,6 +126,7 @@ public:
     void DrawRect( const Rectangle& rRect );
     void DrawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry );
     void DrawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon );
+    void DrawRegionBand( const RegionBand& rRegion );
     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 );
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 65c11ca..d4e0917 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -247,7 +247,10 @@ void OpenGLSalGraphicsImpl::ImplSetClipBit( const vcl::Region& rClip, GLuint nMa
 
     glClear( GL_STENCIL_BUFFER_BIT );
     BeginSolid( MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF ) );
-    DrawPolyPolygon( rClip.GetAsB2DPolyPolygon() );
+    if( rClip.getRegionBand() )
+        DrawRegionBand( *rClip.getRegionBand() );
+    else
+        DrawPolyPolygon( rClip.GetAsB2DPolyPolygon() );
     EndSolid();
 
     glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
@@ -793,6 +796,41 @@ void OpenGLSalGraphicsImpl::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rPol
     CHECK_GL_ERROR();
 }
 
+void OpenGLSalGraphicsImpl::DrawRegionBand( const RegionBand& rRegion )
+{
+    RectangleVector aRects;
+    std::vector<GLfloat> aVertices;
+    rRegion.GetRegionRectangles( aRects );
+
+    if( aRects.empty() )
+        return;
+
+#define ADD_VERTICE(pt) \
+    aVertices.push_back( 2 * pt.X() / GetWidth() - 1.0 ); \
+    aVertices.push_back( 1.0 - (2 * pt.Y() / GetHeight()) );
+
+    for( size_t i = 0; i < aRects.size(); ++i )
+    {
+        aRects[i].Bottom() += 1;
+        aRects[i].Right() += 1;
+        ADD_VERTICE( aRects[i].TopLeft() );
+        ADD_VERTICE( aRects[i].TopRight() );
+        ADD_VERTICE( aRects[i].BottomLeft() );
+        ADD_VERTICE( aRects[i].BottomLeft() );
+        ADD_VERTICE( aRects[i].TopRight() );
+        ADD_VERTICE( aRects[i].BottomRight() );
+    }
+
+#undef ADD_VERTICE
+
+    glEnableVertexAttribArray( GL_ATTRIB_POS );
+    glVertexAttribPointer( GL_ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, &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];
commit fa77801f3e57ad94f077230a95bded1067f528e9
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Sat Nov 22 08:07:47 2014 -0500

    vcl: Track the GL context's clip region and update before drawing when needed
    
    Change-Id: Ibec92851dc87f6696ee55a8db10fe160cd97d09c

diff --git a/include/vcl/opengl/OpenGLContext.hxx b/include/vcl/opengl/OpenGLContext.hxx
index e7c129a..ebfa6ff 100644
--- a/include/vcl/opengl/OpenGLContext.hxx
+++ b/include/vcl/opengl/OpenGLContext.hxx
@@ -231,6 +231,7 @@ private:
 #endif
 
 public:
+    vcl::Region maClipRegion;
     int mnPainting;
 
     OpenGLContext* mpPrevContext;
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index cb06707..85ec262 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -38,6 +38,7 @@ protected:
     OpenGLContext* mpContext;
 
     // clipping
+    vcl::Region maClipRegion;
     bool mbUseScissor;
     bool mbUseStencil;
 
@@ -91,6 +92,7 @@ protected:
     GLuint mnRadialGradientEndColorUniform;
     GLuint mnRadialGradientCenterUniform;
 
+    void ImplInitClipRegion();
     void ImplSetClipBit( const vcl::Region& rClip, GLuint nMask );
 
     bool CheckOffscreenTexture();
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 06b7e6b..65c11ca 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -213,13 +213,7 @@ void OpenGLSalGraphicsImpl::PreDraw()
     if( mbOffscreen )
         CheckOffscreenTexture();
     glViewport( 0, 0, GetWidth(), GetHeight() );
-    if( mbUseScissor )
-        glEnable( GL_SCISSOR_TEST );
-    if( mbUseStencil )
-    {
-        glStencilFunc( GL_EQUAL, 1, 0x1 );
-        glEnable( GL_STENCIL_TEST );
-    }
+    ImplInitClipRegion();
 
     CHECK_GL_ERROR();
 }
@@ -263,36 +257,44 @@ void OpenGLSalGraphicsImpl::ImplSetClipBit( const vcl::Region& rClip, GLuint nMa
     CHECK_GL_ERROR();
 }
 
-bool OpenGLSalGraphicsImpl::setClipRegion( const vcl::Region& rClip )
+void OpenGLSalGraphicsImpl::ImplInitClipRegion()
 {
-    SAL_INFO( "vcl.opengl", "::setClipRegion " << rClip );
-
-    if( rClip.IsEmpty() )
+    // make sure the context has the right clipping set
+    if( maClipRegion != mpContext->maClipRegion )
     {
-        ResetClipRegion();
-        return true;
+        mpContext->maClipRegion = maClipRegion;
+        if( maClipRegion.IsRectangle() )
+        {
+            Rectangle aRect( maClipRegion.GetBoundRect() );
+            glScissor( aRect.Left(), GetHeight() - aRect.Bottom() - 1, aRect.GetWidth() + 1, aRect.GetHeight() + 1 );
+        }
+        else if( !maClipRegion.IsEmpty() )
+        {
+            ImplSetClipBit( maClipRegion, 0x01 );
+        }
     }
 
-    if( rClip.IsRectangle() )
+    if( mbUseScissor )
+        glEnable( GL_SCISSOR_TEST );
+    if( mbUseStencil )
     {
-        Rectangle aRect( rClip.GetBoundRect() );
+        glStencilFunc( GL_EQUAL, 1, 0x1 );
+        glEnable( GL_STENCIL_TEST );
+    }
+}
+
+bool OpenGLSalGraphicsImpl::setClipRegion( const vcl::Region& rClip )
+{
+    SAL_INFO( "vcl.opengl", "::setClipRegion " << rClip );
+    maClipRegion = rClip;
 
-        mbUseStencil = false;
+    mbUseStencil = false;
+    mbUseScissor = false;
+    if( maClipRegion.IsRectangle() )
         mbUseScissor = true;
-        maContext.makeCurrent();
-        glViewport( 0, 0, GetWidth(), GetHeight() );
-        glScissor( aRect.Left(), GetHeight() - aRect.Bottom() - 1, aRect.GetWidth(), aRect.GetHeight() );
-    }
-    else
-    {
+    else if ( !maClipRegion.IsEmpty() )
         mbUseStencil = true;
-        mbUseScissor = false;
-        maContext.makeCurrent();
-        glViewport( 0, 0, GetWidth(), GetHeight() );
-        ImplSetClipBit( rClip, 0x01 );
-    }
 
-    CHECK_GL_ERROR();
     return true;
 }
 
@@ -300,6 +302,7 @@ bool OpenGLSalGraphicsImpl::setClipRegion( const vcl::Region& rClip )
 void OpenGLSalGraphicsImpl::ResetClipRegion()
 {
     SAL_INFO( "vcl.opengl", "::ResetClipRegion" );
+    maClipRegion.SetEmpty();
     mbUseScissor = false;
     mbUseStencil = false;
 }
commit 5f86a6165bdedec4fbac2cf22a958245f52168be
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Sat Nov 22 08:04:23 2014 -0500

    vcl: Move the painting fence to the OpenGL context
    
    Change-Id: I462e68a1ad7a56fafe57504959cf169a70665f81

diff --git a/include/vcl/opengl/OpenGLContext.hxx b/include/vcl/opengl/OpenGLContext.hxx
index 01ce323..e7c129a 100644
--- a/include/vcl/opengl/OpenGLContext.hxx
+++ b/include/vcl/opengl/OpenGLContext.hxx
@@ -231,6 +231,8 @@ private:
 #endif
 
 public:
+    int mnPainting;
+
     OpenGLContext* mpPrevContext;
     OpenGLContext* mpNextContext;
 };
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index e84aa7b..cb06707 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -35,8 +35,6 @@ class VCL_PLUGIN_PUBLIC OpenGLSalGraphicsImpl : public SalGraphicsImpl
 {
 protected:
 
-    SalFrame* mpFrame;
-    int mnPainting;
     OpenGLContext* mpContext;
 
     // clipping
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index f049f91..06b7e6b 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -228,7 +228,7 @@ void OpenGLSalGraphicsImpl::PostDraw()
 {
     if( mbOffscreen )
         glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-    else if( mnPainting == 0 )
+    else if( mpContext->mnPainting == 0 )
         glFlush();
     if( mbUseScissor )
         glDisable( GL_SCISSOR_TEST );
@@ -1867,15 +1867,16 @@ bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly,
 
 void OpenGLSalGraphicsImpl::beginPaint()
 {
-    mnPainting++;
     SAL_INFO( "vcl.opengl", "BEGIN PAINT " << this );
+    mpContext->mnPainting++;
 }
 
 void OpenGLSalGraphicsImpl::endPaint()
 {
-    mnPainting--;
     SAL_INFO( "vcl.opengl", "END PAINT " << this );
-    if( mnPainting == 0 )
+    mpContext->mnPainting--;
+    assert( mpContext->mnPainting >= 0 );
+    if( mpContext->mnPainting == 0 && !mbOffscreen )
     {
         mpContext->makeCurrent();
         glFlush();
diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx
index ad1a52c..7df7970 100644
--- a/vcl/source/opengl/OpenGLContext.cxx
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -53,6 +53,7 @@ OpenGLContext::OpenGLContext():
     mbRequestLegacyContext(false),
     mbUseDoubleBufferedRendering(true),
     mbRequestVirtualDevice(false),
+    mnPainting(0),
     mpPrevContext(NULL),
     mpNextContext(NULL)
 {
commit e26237f6cbc0d499c91aa32c3bea1f9daee6578e
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Sat Nov 22 07:58:38 2014 -0500

    vcl: Always use the same OpenGL context when drawing in a window
    
    Change-Id: Ief0e947149c133aaa8e81973e088c4df6432bfdc

diff --git a/include/vcl/opengl/OpenGLContext.hxx b/include/vcl/opengl/OpenGLContext.hxx
index 471e6ce..01ce323 100644
--- a/include/vcl/opengl/OpenGLContext.hxx
+++ b/include/vcl/opengl/OpenGLContext.hxx
@@ -175,6 +175,9 @@ public:
     bool init( HDC hDC, HWND hWnd );
 #endif
 
+    void AddRef();
+    void DeRef();
+
     void makeCurrent();
     void resetCurrent();
     void swapBuffers();
@@ -219,12 +222,17 @@ private:
     SystemChildWindow* m_pChildWindow;
     boost::scoped_ptr<SystemChildWindow> m_pChildWindowGC;
     bool mbInitialized;
+    int  mnRefCount;
     bool mbRequestLegacyContext;
     bool mbUseDoubleBufferedRendering;
     bool mbRequestVirtualDevice;
 #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
     bool mbPixmap; // is a pixmap instead of a window
 #endif
+
+public:
+    OpenGLContext* mpPrevContext;
+    OpenGLContext* mpNextContext;
 };
 
 #endif
diff --git a/vcl/inc/opengl/win/gdiimpl.hxx b/vcl/inc/opengl/win/gdiimpl.hxx
index 557e58a..66a0333 100644
--- a/vcl/inc/opengl/win/gdiimpl.hxx
+++ b/vcl/inc/opengl/win/gdiimpl.hxx
@@ -15,6 +15,8 @@
 #include "openglgdiimpl.hxx"
 #include "win/salgdi.h"
 
+class OpenGLContext;
+
 class WinOpenGLSalGraphicsImpl : public OpenGLSalGraphicsImpl
 {
     friend class WinLayout;
@@ -24,9 +26,16 @@ private:
 public:
     WinOpenGLSalGraphicsImpl(WinSalGraphics& rGraphics);
 
+    virtual void Init() SAL_OVERRIDE;
+
 protected:
     virtual GLfloat GetWidth() const SAL_OVERRIDE;
     virtual GLfloat GetHeight() const SAL_OVERRIDE;
+    virtual bool    IsOffscreen() const SAL_OVERRIDE;
+
+    virtual OpenGLContext* CreateWinContext() SAL_OVERRIDE;
+    virtual bool CompareWinContext( OpenGLContext* pContext ) SAL_OVERRIDE;
+    virtual OpenGLContext* CreatePixmapContext() SAL_OVERRIDE;
 
 public:
     virtual void copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ) SAL_OVERRIDE;
diff --git a/vcl/inc/opengl/x11/gdiimpl.hxx b/vcl/inc/opengl/x11/gdiimpl.hxx
index d25d5d0..f5e5bfb 100644
--- a/vcl/inc/opengl/x11/gdiimpl.hxx
+++ b/vcl/inc/opengl/x11/gdiimpl.hxx
@@ -28,12 +28,16 @@ public:
 protected:
     GLfloat GetWidth() const SAL_OVERRIDE;
     GLfloat GetHeight() const SAL_OVERRIDE;
+    bool    IsOffscreen() const SAL_OVERRIDE;
+
+    virtual OpenGLContext* CreateWinContext() SAL_OVERRIDE;
+    virtual bool CompareWinContext( OpenGLContext* pContext ) SAL_OVERRIDE;
+    virtual OpenGLContext* CreatePixmapContext() SAL_OVERRIDE;
 
 public:
     // implementation of X11GraphicsImpl
 
     virtual void copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ) SAL_OVERRIDE;
-    void Init() SAL_OVERRIDE;
     bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE;
     bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) SAL_OVERRIDE;
 };
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index 2031c91..e84aa7b 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -35,9 +35,9 @@ class VCL_PLUGIN_PUBLIC OpenGLSalGraphicsImpl : public SalGraphicsImpl
 {
 protected:
 
-    OpenGLContext maContext;
     SalFrame* mpFrame;
     int mnPainting;
+    OpenGLContext* mpContext;
 
     // clipping
     bool mbUseScissor;
@@ -144,21 +144,35 @@ public:
     // get the height of the device
     virtual GLfloat GetHeight() const = 0;
 
+    // check whether this instance is used for offscreen rendering
+    virtual bool IsOffscreen() const = 0;
+
     // operations to do before painting
     virtual void PreDraw();
 
     // operations to do after painting
     virtual void PostDraw();
 
-    // enable/disable offscreen rendering
-    virtual void SetOffscreen( bool bOffscreen );
+protected:
+    bool AcquireContext( bool bOffscreen );
+    bool ReleaseContext();
+
+    // create a new context for window rendering
+    virtual OpenGLContext* CreateWinContext() = 0;
 
+    // check whether the given context can be used by this instance
+    virtual bool CompareWinContext( OpenGLContext* pContext ) = 0;
+
+    // create a new context for window rendering
+    virtual OpenGLContext* CreatePixmapContext() = 0;
 
 public:
     OpenGLSalGraphicsImpl();
     virtual ~OpenGLSalGraphicsImpl ();
 
-    OpenGLContext& GetOpenGLContext() { return maContext; }
+    OpenGLContext& GetOpenGLContext() { return *mpContext; }
+
+    virtual void Init() SAL_OVERRIDE;
 
     virtual void freeResources() SAL_OVERRIDE;
 
diff --git a/vcl/inc/salgdiimpl.hxx b/vcl/inc/salgdiimpl.hxx
index 2fd7f56..e92c65f 100644
--- a/vcl/inc/salgdiimpl.hxx
+++ b/vcl/inc/salgdiimpl.hxx
@@ -44,6 +44,8 @@ public:
 
     virtual ~SalGraphicsImpl();
 
+    virtual void Init() = 0;
+
     virtual void freeResources() = 0;
 
     virtual bool setClipRegion( const vcl::Region& ) = 0;
diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx
index c1d9eed..212e036 100644
--- a/vcl/inc/svdata.hxx
+++ b/vcl/inc/svdata.hxx
@@ -89,6 +89,7 @@ class SalI18NImeStatus;
 class DockingManager;
 class VclEventListeners2;
 class SalData;
+class OpenGLContext;
 
 namespace vcl { class DisplayConnection; class SettingsConfigItem; class DeleteOnDeinitBase; }
 
@@ -161,6 +162,8 @@ struct ImplSVGDIData
     OutputDevice*           mpLastPrnGraphics;  // Last OutputDevice with a InfoPrinter Graphics
     VirtualDevice*          mpFirstVirDev;      // First VirtualDevice
     VirtualDevice*          mpLastVirDev;       // Last VirtualDevice
+    OpenGLContext*          mpFirstContext;     // First OpenGLContext
+    OpenGLContext*          mpLastContext;      // Last OpenGLContext
     Printer*                mpFirstPrinter;     // First Printer
     Printer*                mpLastPrinter;      // Last Printer
     ImplPrnQueueList*       mpPrinterQueueList; // List of all printer queue
diff --git a/vcl/inc/unx/x11/x11gdiimpl.h b/vcl/inc/unx/x11/x11gdiimpl.h
index 239d217..22859c3 100644
--- a/vcl/inc/unx/x11/x11gdiimpl.h
+++ b/vcl/inc/unx/x11/x11gdiimpl.h
@@ -17,7 +17,6 @@ class X11GraphicsImpl
 public:
     virtual ~X11GraphicsImpl() {};
 
-    virtual void Init() = 0;
     virtual bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) = 0;
     virtual bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) = 0;
 };
diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index 1af7807..443c1c2 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -181,6 +181,7 @@ public:
 class WinSalGraphics : public SalGraphics
 {
     friend class WinSalGraphicsImpl;
+    friend class WinOpenGLSalGraphicsImpl;
     friend class ScopedFont;
     friend class OpenGLCompatibleDC;
     friend class WinLayout;
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index e5b181b..f049f91 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -31,6 +31,7 @@
 
 #include <vcl/opengl/OpenGLHelper.hxx>
 #include "salgdi.hxx"
+#include "svdata.hxx"
 #include "opengl/salbmp.hxx"
 
 #include <glm/glm.hpp>
@@ -63,8 +64,7 @@
                  1.0f )
 
 OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl()
-    : mpFrame(NULL)
-    , mnPainting(0)
+    : mpContext(0)
     , mbUseScissor(false)
     , mbUseStencil(false)
     , mbOffscreen(false)
@@ -109,11 +109,106 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl()
 
 OpenGLSalGraphicsImpl::~OpenGLSalGraphicsImpl()
 {
+    ReleaseContext();
+}
+
+bool OpenGLSalGraphicsImpl::AcquireContext( bool bOffscreen )
+{
+    ImplSVData* pSVData = ImplGetSVData();
+
+    if( mpContext )
+        mpContext->DeRef();
+
+    if( bOffscreen )
+    {
+        mpContext = CreatePixmapContext();
+        return (mpContext != NULL);
+    }
+
+    OpenGLContext* pContext = pSVData->maGDIData.mpLastContext;
+    while( pContext )
+    {
+        // check if this context can be used by this SalGraphicsImpl instance
+        if( CompareWinContext( pContext )  )
+            break;
+        pContext = pContext->mpPrevContext;
+    }
+
+    if( pContext )
+        pContext->AddRef();
+    else
+        pContext = CreateWinContext();
+
+    mpContext = pContext;
+    return (mpContext != NULL);
+}
+
+bool OpenGLSalGraphicsImpl::ReleaseContext()
+{
+    if( mpContext )
+        mpContext->DeRef();
+    mpContext = NULL;
+    return true;
+}
+
+void OpenGLSalGraphicsImpl::Init()
+{
+    const bool bOffscreen = IsOffscreen();
+
+    // check if we can simply re-use the same context
+    if( mpContext )
+    {
+        if( bOffscreen != mbOffscreen || ( !mbOffscreen && CompareWinContext( mpContext ) ) )
+            ReleaseContext();
+    }
+
+    if( !mpContext && !AcquireContext( bOffscreen ) )
+    {
+        SAL_WARN( "vcl.opengl", "Couldn't acquire context for SalGraphics" );
+        return;
+    }
+
+    mpContext->makeCurrent();
+
+    if( mbOffscreen == bOffscreen )
+    {
+        // Nothing more to do for onscreen case
+        if( !mbOffscreen )
+            return;
+
+        // Already enabled and same size
+        if( maOffscreenTex.GetWidth()  == GetWidth() &&
+            maOffscreenTex.GetHeight() == GetHeight() )
+            return;
+    }
+    else
+    {
+        mbOffscreen = bOffscreen;
+        if( bOffscreen )
+            glGenFramebuffers( 1, &mnFramebufferId );
+        else
+            glDeleteFramebuffers( 1, &mnFramebufferId );
+    }
+
+    // Create/update attached offscreen texture
+    if( mbOffscreen )
+    {
+        glBindFramebuffer( GL_FRAMEBUFFER, mnFramebufferId );
+        maOffscreenTex = OpenGLTexture( GetWidth(), GetHeight() );
+        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, maOffscreenTex.Id(), 0 );
+        GLenum nStatus = glCheckFramebufferStatus( GL_FRAMEBUFFER );
+        if( nStatus != GL_FRAMEBUFFER_COMPLETE )
+            SAL_WARN( "vcl.opengl", "Incomplete framebuffer " << nStatus );
+        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+        CHECK_GL_ERROR();
+    }
 }
 
 void OpenGLSalGraphicsImpl::PreDraw()
 {
-    maContext.makeCurrent();
+    assert( mpContext && mpContext->isInitialized() );
+
+    mpContext->makeCurrent();
     // TODO: lfrb: make sure the render target has the right size
     if( mbOffscreen )
         CheckOffscreenTexture();
@@ -273,46 +368,17 @@ void OpenGLSalGraphicsImpl::SetROPFillColor( SalROPColor /*nROPColor*/ )
 {
 }
 
-// enable/disbale offscreen rendering
-void OpenGLSalGraphicsImpl::SetOffscreen( bool bOffscreen )
-{
-    if( bOffscreen == mbOffscreen )
-    {
-        // Already disabled
-        if( !mbOffscreen )
-            return;
-
-        // Already enabled and same size
-        if( maOffscreenTex.GetWidth()  == GetWidth() &&
-            maOffscreenTex.GetHeight() == GetHeight() )
-            return;
-    }
-    else
-    {
-        mbOffscreen = bOffscreen;
-        if( bOffscreen )
-            glGenFramebuffers( 1, &mnFramebufferId );
-        else
-            glDeleteFramebuffers( 1, &mnFramebufferId );
-    }
-
-    if( mbOffscreen )
-    {
-        glBindFramebuffer( GL_FRAMEBUFFER, mnFramebufferId );
-        maOffscreenTex = OpenGLTexture( GetWidth(), GetHeight() );
-        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, maOffscreenTex.Id(), 0 );
-        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-    }
-
-    CHECK_GL_ERROR();
-}
-
 bool OpenGLSalGraphicsImpl::CheckOffscreenTexture()
 {
     glBindFramebuffer( GL_FRAMEBUFFER, mnFramebufferId );
 
     if( maOffscreenTex.IsUnique() )
+    {
+        GLenum nStatus = glCheckFramebufferStatus( GL_FRAMEBUFFER );
+        if( nStatus != GL_FRAMEBUFFER_COMPLETE )
+            SAL_WARN( "vcl.opengl", "Incomplete framebuffer " << nStatus );
         return true;
+    }
 
     SalTwoRect aPosAry;
     aPosAry.mnSrcX = aPosAry.mnDestX = 0;
@@ -1811,7 +1877,7 @@ void OpenGLSalGraphicsImpl::endPaint()
     SAL_INFO( "vcl.opengl", "END PAINT " << this );
     if( mnPainting == 0 )
     {
-        maContext.makeCurrent();
+        mpContext->makeCurrent();
         glFlush();
     }
 }
diff --git a/vcl/opengl/win/gdiimpl.cxx b/vcl/opengl/win/gdiimpl.cxx
index 18e0da8..0815927 100644
--- a/vcl/opengl/win/gdiimpl.cxx
+++ b/vcl/opengl/win/gdiimpl.cxx
@@ -68,4 +68,34 @@ GLfloat WinOpenGLSalGraphicsImpl::GetHeight() const
     return 1;
 }
 
+bool WinOpenGLSalGraphicsImpl::IsOffscreen() const
+{
+    WinSalFrame* pFrame = GetWindowPtr( mrParent.gethWnd() );
+    return ( pFrame == NULL );
+}
+
+OpenGLContext* WinOpenGLSalGraphicsImpl::CreateWinContext()
+{
+    OpenGLContext* pContext = new OpenGLContext();
+    pContext->requestSingleBufferedRendering();
+    pContext->init( mrParent.mhLocalDC, mrParent.mhWnd );
+    return pContext;
+}
+
+bool WinOpenGLSalGraphicsImpl::CompareWinContext( OpenGLContext* pContext )
+{
+    if( !pContext || !pContext->isInitialized() )
+        return false;
+    return ( pContext->getOpenGLWindow().hWnd == mrParent.mhWnd );
+}
+
+OpenGLContext* WinOpenGLSalGraphicsImpl::CreatePixmapContext()
+{
+    OpenGLContext* pContext = new OpenGLContext();
+    pContext->requestVirtualDevice();
+    pContext->requestSingleBufferedRendering();
+    pContext->init( mrParent.mhLocalDC, mrParent.mhWnd );
+    return pContext;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx
index afaea92..0a8bf68 100644
--- a/vcl/opengl/x11/gdiimpl.cxx
+++ b/vcl/opengl/x11/gdiimpl.cxx
@@ -59,31 +59,53 @@ GLfloat X11OpenGLSalGraphicsImpl::GetHeight() const
     return 1;
 }
 
-void X11OpenGLSalGraphicsImpl::Init()
+bool X11OpenGLSalGraphicsImpl::IsOffscreen() const
 {
     X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame);
-
-    // Called after eg. a vdev re-size where we need to update the underlying pixmap
-    maContext.resetToReInitialize();
-    if (pProvider)
-    {
-        Window aWin = pProvider->GetX11Window();
-        maContext.init( mrParent.GetXDisplay(), aWin, mrParent.m_nXScreen.getXScreen());
-        SetOffscreen( false );
-    }
+    if( pProvider )
+        return false;
     else if( mrParent.m_pVDev )
-    {
-        maContext.init( mrParent.GetXDisplay(), mrParent.m_pVDev->GetDrawable(),
-                        mrParent.m_pVDev->GetWidth(), mrParent.m_pVDev->GetHeight(),
-                        mrParent.m_nXScreen.getXScreen() );
-        SetOffscreen( true );
-    }
+        return true;
     else
     {
         SAL_WARN( "vcl.opengl", "what happened here?" );
+        return true;
     }
 }
 
+OpenGLContext* X11OpenGLSalGraphicsImpl::CreateWinContext()
+{
+    X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame);
+
+    if( !pProvider )
+        return NULL;
+    Window aWin = pProvider->GetX11Window();
+    OpenGLContext* pContext = new OpenGLContext();
+    pContext->init( mrParent.GetXDisplay(), aWin,
+                    mrParent.m_nXScreen.getXScreen() );
+    return pContext;
+}
+
+bool X11OpenGLSalGraphicsImpl::CompareWinContext( OpenGLContext* pContext )
+{
+    X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame);
+
+    if( !pProvider || !pContext->isInitialized() )
+        return false;
+    return ( pContext->getOpenGLWindow().win == pProvider->GetX11Window() );
+}
+
+OpenGLContext* X11OpenGLSalGraphicsImpl::CreatePixmapContext()
+{
+    if( mrParent.m_pVDev == NULL )
+        return NULL;
+    OpenGLContext* pContext = new OpenGLContext();
+    pContext->init( mrParent.GetXDisplay(), mrParent.m_pVDev->GetDrawable(),
+                    mrParent.m_pVDev->GetWidth(), mrParent.m_pVDev->GetHeight(),
+                    mrParent.m_nXScreen.getXScreen() );
+    return pContext;
+}
+
 void X11OpenGLSalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics )
 {
     OpenGLSalGraphicsImpl *pImpl = pSrcGraphics ? static_cast< OpenGLSalGraphicsImpl* >(pSrcGraphics->GetImpl()) : static_cast< OpenGLSalGraphicsImpl *>(mrParent.GetImpl());
@@ -104,7 +126,7 @@ bool X11OpenGLSalGraphicsImpl::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX,
         return false;
 
     // make sure everything is synced up before reading back
-    maContext.makeCurrent();
+    mpContext->makeCurrent();
     glXWaitX();
 
     // TODO: lfrb: What if offscreen?
diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx
index 6595709..ad1a52c 100644
--- a/vcl/source/opengl/OpenGLContext.cxx
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -27,6 +27,8 @@
 #include <win/saldata.hxx>
 #endif
 
+#include "svdata.hxx"
+
 using namespace com::sun::star;
 
 // TODO use rtl::Static instead of 'static'
@@ -47,13 +49,26 @@ OpenGLContext::OpenGLContext():
     mpWindow(NULL),
     m_pChildWindow(NULL),
     mbInitialized(false),
+    mnRefCount(1),
     mbRequestLegacyContext(false),
     mbUseDoubleBufferedRendering(true),
-    mbRequestVirtualDevice(false)
+    mbRequestVirtualDevice(false),
+    mpPrevContext(NULL),
+    mpNextContext(NULL)
 {
 #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
     mbPixmap = false;
 #endif
+
+    ImplSVData* pSVData = ImplGetSVData();
+    if( pSVData->maGDIData.mpLastContext )
+    {
+        pSVData->maGDIData.mpLastContext->mpNextContext = this;
+        mpPrevContext = pSVData->maGDIData.mpLastContext;
+    }
+    else
+        pSVData->maGDIData.mpFirstContext = this;
+    pSVData->maGDIData.mpLastContext = this;
 }
 
 OpenGLContext::~OpenGLContext()
@@ -67,6 +82,16 @@ OpenGLContext::~OpenGLContext()
         wglDeleteContext( m_aGLWin.hRC );
         ReleaseDC( m_aGLWin.hWnd, m_aGLWin.hDC );
     }
+    ImplSVData* pSVData = ImplGetSVData();
+    if( mpPrevContext )
+        mpPrevContext->mpNextContext = mpNextContext;
+    else
+        pSVData->maGDIData.mpFirstContext = mpNextContext;
+    if( mpNextContext )
+        mpNextContext->mpPrevContext = mpPrevContext;
+    else
+        pSVData->maGDIData.mpLastContext = mpPrevContext;
+
 #elif defined( MACOSX )
     OpenGLWrapper::resetCurrent();
 #elif defined( IOS ) || defined( ANDROID )
@@ -89,6 +114,17 @@ OpenGLContext::~OpenGLContext()
 #endif
 }
 
+void OpenGLContext::AddRef()
+{
+    mnRefCount++;
+}
+
+void OpenGLContext::DeRef()
+{
+    if( --mnRefCount == 0 )
+        delete this;
+}
+
 void OpenGLContext::requestLegacyContext()
 {
     mbRequestLegacyContext = true;
diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx
index e07b56e..80f24f0 100644
--- a/vcl/unx/generic/gdi/salgdi.cxx
+++ b/vcl/unx/generic/gdi/salgdi.cxx
@@ -151,7 +151,7 @@ void X11SalGraphics::SetDrawable( Drawable aDrawable, SalX11Screen nXScreen )
 
     if( hDrawable_ )
     {
-        dynamic_cast<X11GraphicsImpl&>(*mpImpl.get()).Init();
+        mpImpl->Init();
         // TODO: moggi: FIXME nTextPixel_     = GetPixel( nTextColor_ );
     }
 }
diff --git a/vcl/win/source/gdi/gdiimpl.cxx b/vcl/win/source/gdi/gdiimpl.cxx
index 8a4b390..e17b3e1 100644
--- a/vcl/win/source/gdi/gdiimpl.cxx
+++ b/vcl/win/source/gdi/gdiimpl.cxx
@@ -294,6 +294,10 @@ WinSalGraphicsImpl::~WinSalGraphicsImpl()
 
 }
 
+void WinSalGraphicsImpl::Init()
+{
+}
+
 void WinSalGraphicsImpl::freeResources()
 {
 }
diff --git a/vcl/win/source/gdi/gdiimpl.hxx b/vcl/win/source/gdi/gdiimpl.hxx
index ded35ac..65e9d3f 100644
--- a/vcl/win/source/gdi/gdiimpl.hxx
+++ b/vcl/win/source/gdi/gdiimpl.hxx
@@ -52,6 +52,8 @@ public:
 
     virtual ~WinSalGraphicsImpl();
 
+    virtual void Init() SAL_OVERRIDE;
+
     virtual void freeResources() SAL_OVERRIDE;
 
     virtual bool setClipRegion( const vcl::Region& ) SAL_OVERRIDE;
diff --git a/vcl/win/source/gdi/salgdi.cxx b/vcl/win/source/gdi/salgdi.cxx
index 678067d..05279d1 100644
--- a/vcl/win/source/gdi/salgdi.cxx
+++ b/vcl/win/source/gdi/salgdi.cxx
@@ -482,15 +482,7 @@ void WinSalGraphics::InitGraphics()
     ::SetTextAlign( getHDC(), TA_BASELINE | TA_LEFT | TA_NOUPDATECP );
     ::SetBkMode( getHDC(), WIN32_TRANSPARENT );
     ::SetROP2( getHDC(), R2_COPYPEN );
-
-    OpenGLSalGraphicsImpl* pImpl = dynamic_cast<OpenGLSalGraphicsImpl*>(mpImpl.get());
-    if (pImpl)
-    {
-        if (mbVirDev)
-            pImpl->GetOpenGLContext().requestVirtualDevice();
-        pImpl->GetOpenGLContext().requestSingleBufferedRendering();
-        pImpl->GetOpenGLContext().init(mhLocalDC, mhWnd);
-    }
+    mpImpl->Init();
 }
 
 void WinSalGraphics::DeInitGraphics()
commit 90af2a6c403e7f6e5192d54f69b38b85a9e6fbc8
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Fri Nov 21 12:17:02 2014 -0500

    vcl: Use old method for pixmap painting for GTK widgets without OpenGL
    
    Change-Id: Ie6078308f7a7f70683a7f963b15857b5dac753b0

diff --git a/vcl/inc/unx/gtk/gtkgdi.hxx b/vcl/inc/unx/gtk/gtkgdi.hxx
index 9ce374d..568ef5c 100644
--- a/vcl/inc/unx/gtk/gtkgdi.hxx
+++ b/vcl/inc/unx/gtk/gtkgdi.hxx
@@ -133,6 +133,7 @@ public:
     // will be set when UI theme was changed
     static  bool        bThemeChanged;
     static  bool        bNeedPixmapPaint;
+    static  bool        bNeedTwoPasses;
 
     // native widget methods
     virtual bool        IsNativeControlSupported( ControlType nType, ControlPart nPart ) SAL_OVERRIDE;
diff --git a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
index 46ec7b4..f3b1ecf6 100644
--- a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
+++ b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
@@ -49,10 +49,12 @@ const char* const tabPrelitDataName="libreoffice-tab-is-prelit";
 // initialize statics
 bool GtkSalGraphics::bThemeChanged = true;
 bool GtkSalGraphics::bNeedPixmapPaint = false;
+bool GtkSalGraphics::bNeedTwoPasses = false;
 
 enum
 {
     BG_NONE = 0,
+    BG_FILL,
     BG_WHITE,
     BG_BLACK
 };
@@ -511,7 +513,10 @@ void GtkData::initNWF( void )
 
     // use offscreen rendering when using OpenGL backend
     if( OpenGLHelper::isVCLOpenGLEnabled() )
+    {
         GtkSalGraphics::bNeedPixmapPaint = true;
+        GtkSalGraphics::bNeedTwoPasses = true;
+    }
 
     int nScreens = GetGtkSalData()->GetGtkDisplay()->GetXScreenCount();
     gWidgetData = WidgetDataVector( nScreens );
@@ -898,13 +903,24 @@ bool GtkSalGraphics::drawNativeControl(    ControlType nType,
         aPixmapRect = Rectangle( Point( aCtrlRect.Left()-1, aCtrlRect.Top()-1 ),
                                  Size( aCtrlRect.GetWidth()+2, aCtrlRect.GetHeight()+2) );
 
-        xPixmap.reset( NWGetPixmapFromScreen( aPixmapRect, BG_WHITE ) );
-        xMask.reset( NWGetPixmapFromScreen( aPixmapRect, BG_BLACK ) );
-        if( !xPixmap || !xMask )
-            return false;
-        nPasses = 2;
-        gdkDrawable[0] = xPixmap->GetGdkDrawable();
-        gdkDrawable[1] = xMask->GetGdkDrawable();
+        if( bNeedTwoPasses )
+        {
+            xPixmap.reset( NWGetPixmapFromScreen( aPixmapRect, BG_WHITE ) );
+            xMask.reset( NWGetPixmapFromScreen( aPixmapRect, BG_BLACK ) );
+            if( !xPixmap || !xMask )
+                return false;
+            nPasses = 2;
+            gdkDrawable[0] = xPixmap->GetGdkDrawable();
+            gdkDrawable[1] = xMask->GetGdkDrawable();
+        }
+        else
+        {
+            xPixmap.reset( NWGetPixmapFromScreen( aPixmapRect, BG_FILL ) );
+            if( !xPixmap )
+                return false;
+            nPasses = 1;
+            gdkDrawable[0] = xPixmap->GetGdkDrawable();
+        }
 
         aCtrlRect = Rectangle( Point(1,1), aCtrlRect.GetSize() );
         aClip.push_back( aCtrlRect );
@@ -926,7 +942,6 @@ bool GtkSalGraphics::drawNativeControl(    ControlType nType,
     }
 
     bool returnVal = false;
-    SAL_INFO( "vcl.opengl", "Rendering with " << nPasses << " passe(s)" );
 
     for( int i = 0; i < nPasses; ++i )
     {
@@ -1324,6 +1339,62 @@ bool GtkSalGraphics::getNativeControlRegion(  ControlType nType,
 /************************************************************************
  * Individual control drawing functions
  ************************************************************************/
+
+// macros to call before and after the rendering code for a widget
+// it takes care of creating the needed pixmaps
+#define BEGIN_PIXMAP_RENDER(aRect, gdkPixmap) \
+    std::unique_ptr<GdkX11Pixmap> _pixmap, _mask; \
+    int _nPasses = 0; \
+    if( bNeedTwoPasses ) \
+    { \
+        _nPasses = 2; \
+        _pixmap.reset( NWGetPixmapFromScreen( aRect, BG_WHITE ) ); \
+        _mask.reset( NWGetPixmapFromScreen( aRect, BG_BLACK ) ); \
+    } \
+    else \
+    { \
+        _nPasses = 1; \
+        _pixmap.reset( NWGetPixmapFromScreen( aRect, BG_FILL ) ); \
+    } \
+    if( !_pixmap || ( bNeedTwoPasses && !_mask ) ) \
+        return false; \
+    for( int i = 0; i < _nPasses; ++i ) \
+    { \
+        GdkPixmap* gdkPixmap = (i == 0) ? _pixmap->GetGdkPixmap() \
+                                        : _mask->GetGdkPixmap();
+
+#define END_PIXMAP_RENDER(aRect) \
+    } \
+    if( !NWRenderPixmapToScreen( _pixmap.get(), _mask.get(), aRect ) ) \
+        return false;
+
+// same as above but with pixmaps that should be kept for caching
+#define BEGIN_CACHE_PIXMAP_RENDER(aRect, pixmap, mask, gdkPixmap) \
+    int _nPasses = 0; \
+    if( bNeedTwoPasses ) \
+    { \
+        _nPasses = 2; \
+        pixmap = NWGetPixmapFromScreen( aRect, BG_WHITE ); \
+        mask = NWGetPixmapFromScreen( aRect, BG_BLACK ); \
+    } \
+    else \
+    { \
+        _nPasses = 1; \
+        pixmap = NWGetPixmapFromScreen( aRect, BG_FILL ); \
+        mask = NULL; \
+    } \
+    if( !pixmap || ( bNeedTwoPasses && !mask ) ) \
+        return false; \
+    for( int i = 0; i < _nPasses; ++i ) \
+    { \
+        GdkPixmap* gdkPixmap = (i == 0) ? pixmap->GetGdkPixmap() \
+                                        : mask->GetGdkPixmap();
+
+#define END_CACHE_PIXMAP_RENDER(aRect, pixmap, mask) \
+    } \
+    if( !NWRenderPixmapToScreen( pixmap, mask, aRect ) ) \
+        return false;
+
 bool GtkSalGraphics::NWPaintGTKArrow(
             GdkDrawable* gdkDrawable,
             ControlType, ControlPart,
@@ -2427,16 +2498,8 @@ bool GtkSalGraphics::NWPaintGTKSpinBox( ControlType nType, ControlPart nPart,
     else
         pixmapRect = rControlRectangle;
 
-    std::unique_ptr<GdkX11Pixmap> pixmap( NWGetPixmapFromScreen( pixmapRect, BG_WHITE ) );
-    std::unique_ptr<GdkX11Pixmap> mask( NWGetPixmapFromScreen( pixmapRect, BG_BLACK ) );
-    if( !pixmap || !mask )
-        return false;
-
-    for( int i = 0; i < 2; ++i )
+    BEGIN_PIXMAP_RENDER( pixmapRect, gdkPixmap )
     {
-        GdkPixmap* gdkPixmap = (i == 0) ? pixmap->GetGdkPixmap()
-                                        : mask->GetGdkPixmap();
-
         // First render background
         gtk_paint_flat_box(m_pWindow->style,gdkPixmap,GTK_STATE_NORMAL,GTK_SHADOW_NONE,NULL,m_pWindow,"base",
                 -pixmapRect.Left(),
@@ -2478,8 +2541,9 @@ bool GtkSalGraphics::NWPaintGTKSpinBox( ControlType nType, ControlPart nPart,
         NWPaintOneSpinButton( m_nXScreen, gdkPixmap, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption );
         NWPaintOneSpinButton( m_nXScreen, gdkPixmap, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption );
     }
+    END_PIXMAP_RENDER( pixmapRect );
 
-    return NWRenderPixmapToScreen( pixmap.get(), mask.get(), pixmapRect );
+    return true;
 }
 
 static Rectangle NWGetSpinButtonRect( SalX11Screen nScreen,
@@ -2786,18 +2850,13 @@ bool GtkSalGraphics::NWPaintGTKTabItem( ControlType nType, ControlPart,
             return NWRenderPixmapToScreen( pixmap, mask, pixmapRect );
     }
 
-    int nDepth = GetGenericData()->GetSalDisplay()->GetVisual( m_nXScreen ).GetDepth();
-    pixmap = new GdkX11Pixmap( pixmapRect.GetWidth(), pixmapRect.GetHeight(), nDepth );
-    mask = new GdkX11Pixmap( pixmapRect.GetWidth(), pixmapRect.GetHeight(), nDepth );
     GdkRectangle paintRect;
     paintRect.x = paintRect.y = 0;
     paintRect.width = pixmapRect.GetWidth();
     paintRect.height = pixmapRect.GetHeight();
 
-    for( int i = 0; i < 2; ++i )
+    BEGIN_CACHE_PIXMAP_RENDER( pixmapRect, pixmap, mask, gdkPixmap )
     {
-        GdkPixmap* gdkPixmap = (i == 0) ? pixmap->GetGdkPixmap() : mask->GetGdkPixmap();
-
         gtk_paint_flat_box( m_pWindow->style, gdkPixmap, GTK_STATE_NORMAL,
                             GTK_SHADOW_NONE, &paintRect, m_pWindow, "base",
                             -rControlRectangle.Left(),
@@ -2851,6 +2910,7 @@ bool GtkSalGraphics::NWPaintGTKTabItem( ControlType nType, ControlPart,
                 break;
         }
     }
+    END_CACHE_PIXMAP_RENDER( pixmapRect, pixmap, mask )
 
     // cache data
     if( nType == CTRL_TAB_ITEM )
@@ -2858,8 +2918,7 @@ bool GtkSalGraphics::NWPaintGTKTabItem( ControlType nType, ControlPart,
     else
         aCachePage.Fill( nType, nState, pixmapRect, pixmap, mask );
 
-    bool bSuccess = NWRenderPixmapToScreen( pixmap, mask, pixmapRect );
-    return bSuccess;
+    return true;
 }
 
 bool GtkSalGraphics::NWPaintGTKListBox( GdkDrawable* gdkDrawable,
@@ -3434,15 +3493,8 @@ bool GtkSalGraphics::NWPaintGTKListNode(
             break;
     }
 
-    std::unique_ptr<GdkX11Pixmap> pixmap( NWGetPixmapFromScreen( aRect, BG_WHITE ) );
-    std::unique_ptr<GdkX11Pixmap> mask( NWGetPixmapFromScreen( aRect, BG_BLACK ) );
-    if( !pixmap || !mask )
-        return false;
-
-    for( int i = 0; i < 2; ++i )
+    BEGIN_PIXMAP_RENDER( aRect, pixDrawable )
     {
-        GdkDrawable* const &pixDrawable = (i == 0) ? pixmap->GetGdkDrawable()
-                                                   : mask->GetGdkDrawable();
         gtk_paint_expander( gWidgetData[m_nXScreen].gTreeView->style,
                             pixDrawable,
                             stateType,
@@ -3452,8 +3504,9 @@ bool GtkSalGraphics::NWPaintGTKListNode(
                             w/2, h/2,
                             eStyle );
     }
+    END_PIXMAP_RENDER( aRect )
 
-    return NWRenderPixmapToScreen( pixmap.get(), mask.get(), aRect );
+    return true;
 }
 
 bool GtkSalGraphics::NWPaintGTKProgress(
@@ -3469,20 +3522,12 @@ bool GtkSalGraphics::NWPaintGTKProgress(
     gint            w, h;
     w = rControlRectangle.GetWidth();
     h = rControlRectangle.GetHeight();
+    Rectangle aRect( Point( 0, 0 ), Size( w, h ) );
 
     long nProgressWidth = rValue.getNumericVal();
 
-    Rectangle aRect( Point( 0, 0 ), Size( w, h ) );
-    std::unique_ptr<GdkX11Pixmap> pixmap( NWGetPixmapFromScreen( aRect, BG_WHITE ) );
-    std::unique_ptr<GdkX11Pixmap> mask( NWGetPixmapFromScreen( aRect, BG_BLACK ) );
-    if( !pixmap || !mask )
-        return false;
-
-    for( int i = 0; i < 2; ++i )
+    BEGIN_PIXMAP_RENDER( aRect, pixDrawable )
     {
-        GdkDrawable* const &pixDrawable = (i == 0) ? pixmap->GetGdkDrawable()
-                                                   : mask->GetGdkDrawable();
-
         // paint background
         gtk_paint_flat_box(gWidgetData[m_nXScreen].gProgressBar->style, pixDrawable,
                                GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, m_pWindow, "base",
@@ -3524,8 +3569,9 @@ bool GtkSalGraphics::NWPaintGTKProgress(
             }
         }
     }
+    END_PIXMAP_RENDER( rControlRectangle )
 
-    return NWRenderPixmapToScreen( pixmap.get(), mask.get(), rControlRectangle );
+    return true;
 }
 
 bool GtkSalGraphics::NWPaintGTKSlider(
@@ -3545,16 +3591,8 @@ bool GtkSalGraphics::NWPaintGTKSlider(
 
     const SliderValue* pVal = static_cast<const SliderValue*>(&rValue);
 
-    std::unique_ptr<GdkX11Pixmap> pixmap( NWGetPixmapFromScreen( rControlRectangle, BG_WHITE ) );
-    std::unique_ptr<GdkX11Pixmap> mask( NWGetPixmapFromScreen( rControlRectangle, BG_BLACK ) );
-    if( !pixmap || !mask )
-        return false;
-
-    for( int i = 0; i < 2; ++i )
+    BEGIN_PIXMAP_RENDER( rControlRectangle, pixDrawable )
     {
-        GdkDrawable* const &pixDrawable = (i == 0) ? pixmap->GetGdkDrawable()
-                                                   : mask->GetGdkDrawable();
-
         GtkWidget* pWidget = (nPart == PART_TRACK_HORZ_AREA)
                              ? GTK_WIDGET(gWidgetData[m_nXScreen].gHScale)
                              : GTK_WIDGET(gWidgetData[m_nXScreen].gVScale);
@@ -3615,8 +3653,9 @@ bool GtkSalGraphics::NWPaintGTKSlider(
                               eOri );
         }
     }
+    END_PIXMAP_RENDER( rControlRectangle )
 
-    return NWRenderPixmapToScreen( pixmap.get(), mask.get(), rControlRectangle );
+    return true;
 }
 
 static int getFrameWidth(GtkWidget* widget)
@@ -4196,7 +4235,11 @@ GdkX11Pixmap* GtkSalGraphics::NWGetPixmapFromScreen( Rectangle srcRect, int nBgC
 
     pPixmap = new GdkX11Pixmap( srcRect.GetWidth(), srcRect.GetHeight(), nDepth );
 
-    if( nBgColor != BG_NONE )
+    if( nBgColor == BG_FILL )
+    {
+        FillPixmapFromScreen( pPixmap, srcRect.Left(), srcRect.Top() );
+    }
+    else if( nBgColor != BG_NONE )
     {
         cairo_t *cr = gdk_cairo_create( pPixmap->GetGdkDrawable() );
         if( nBgColor == BG_BLACK)
commit 3149cc341b1866d215110f0783227549a99b5920
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Thu Nov 20 22:07:12 2014 -0500

    vcl: Draw native widgets twice on black/white background to synthesize alpha
    
    Change-Id: Ic4c073360070a559855732d2de41ae9085d7d51b

diff --git a/vcl/Package_opengl.mk b/vcl/Package_opengl.mk
index 4a4f30f..d81c0ec 100644
--- a/vcl/Package_opengl.mk
+++ b/vcl/Package_opengl.mk
@@ -12,6 +12,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,\
 	blendedTextureFragmentShader.glsl \
 	blendedTextureVertexShader.glsl \
+	diffTextureFragmentShader.glsl \
 	convolutionFragmentShader.glsl \
 	linearGradientFragmentShader.glsl \
 	maskFragmentShader.glsl \
diff --git a/vcl/inc/opengl/x11/gdiimpl.hxx b/vcl/inc/opengl/x11/gdiimpl.hxx
index a2b863e..d25d5d0 100644
--- a/vcl/inc/opengl/x11/gdiimpl.hxx
+++ b/vcl/inc/opengl/x11/gdiimpl.hxx
@@ -35,7 +35,7 @@ public:
     virtual void copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ) SAL_OVERRIDE;
     void Init() SAL_OVERRIDE;
     bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE;
-    bool RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE;
+    bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) SAL_OVERRIDE;
 };
 
 #endif // INCLUDED_VCL_INC_OPENGL_X11_GDIIMPL_HXX
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index b26e10c..2031c91 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -67,6 +67,10 @@ protected:
     GLuint mnTransformedMaskedSamplerUniform;
     GLuint mnTransformedMaskedMaskUniform;
 
+    GLuint mnDiffTextureProgram;
+    GLuint mnDiffTextureUniform;
+    GLuint mnDiffMaskUniform;
+
     GLuint mnMaskedTextureProgram;
     GLuint mnMaskedSamplerUniform;
     GLuint mnMaskSamplerUniform;
@@ -96,6 +100,7 @@ protected:
     bool CreateSolidProgram( void );
     bool CreateTextureProgram( void );
     bool CreateTransformedTextureProgram( void );
+    bool CreateDiffTextureProgram( void );
     bool CreateMaskedTextureProgram( void );
     bool CreateBlendedTextureProgram( void );
     bool CreateTransformedMaskedTextureProgram( void );
@@ -124,6 +129,7 @@ public:
     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 DrawTextureDiff( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry, bool bInverted = false );
     void DrawTextureWithMask( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry );
     void DrawBlendedTexture( OpenGLTexture& rTexture, OpenGLTexture& rMask, OpenGLTexture& rAlpha, const SalTwoRect& rPosAry );
     void DrawMask( OpenGLTexture& rTexture, SalColor nMaskColor, const SalTwoRect& rPosAry );
diff --git a/vcl/inc/unx/gtk/gtkgdi.hxx b/vcl/inc/unx/gtk/gtkgdi.hxx
index 05d763c..9ce374d 100644
--- a/vcl/inc/unx/gtk/gtkgdi.hxx
+++ b/vcl/inc/unx/gtk/gtkgdi.hxx
@@ -163,8 +163,17 @@ public:
 protected:
     typedef std::list< Rectangle > clipList;
 
-    GdkX11Pixmap* NWGetPixmapFromScreen( Rectangle srcRect );
-    bool NWRenderPixmapToScreen( GdkX11Pixmap* pPixmap, Rectangle dstRect );
+    GdkX11Pixmap* NWGetPixmapFromScreen( Rectangle srcRect, int nBgColor = 0 );
+    bool NWRenderPixmapToScreen( GdkX11Pixmap* pPixmap, GdkX11Pixmap* pMask, Rectangle dstRect );
+
+    bool DoDrawNativeControl( GdkDrawable* pDrawable,
+                           ControlType nType,
+                           ControlPart nPart,
+                           const Rectangle& aCtrlRect,
+                           const clipList& aClip,
+                           ControlState nState,
+                           const ImplControlValue& aValue,
+                           const OUString& rCaption );
 
     bool NWPaintGTKArrow( GdkDrawable* gdkDrawable, ControlType nType, ControlPart nPart,
                            const Rectangle& rControlRectangle,
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index 97f9d60..8ef42ba 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -284,7 +284,7 @@ public:
     bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY );
 
     // render a pixmap to the screen
-    bool RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY );
+    bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY );
 
 
     /*  use to handle GraphicsExpose/NoExpose after XCopyArea & friends
diff --git a/vcl/inc/unx/x11/x11gdiimpl.h b/vcl/inc/unx/x11/x11gdiimpl.h
index 8cd130d..239d217 100644
--- a/vcl/inc/unx/x11/x11gdiimpl.h
+++ b/vcl/inc/unx/x11/x11gdiimpl.h
@@ -19,7 +19,7 @@ public:
 
     virtual void Init() = 0;
     virtual bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) = 0;
-    virtual bool RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) = 0;
+    virtual bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) = 0;
 };
 
 #endif // INCLUDED_VCL_INC_UNX_X11_X11GDIIMPL_HXX
diff --git a/vcl/opengl/diffTextureFragmentShader.glsl b/vcl/opengl/diffTextureFragmentShader.glsl
new file mode 100644
index 0000000..c0a982d
--- /dev/null
+++ b/vcl/opengl/diffTextureFragmentShader.glsl
@@ -0,0 +1,26 @@
+/* -*- 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/.
+ */
+
+/*precision mediump float;*/
+varying vec2 tex_coord;
+uniform sampler2D texture; /* white background */
+uniform sampler2D mask;    /* black background */
+
+void main() {
+    float alpha;
+    vec4 texel0, texel1;
+    texel0 = texture2D(texture, tex_coord);
+    texel1 = texture2D(mask, tex_coord);
+    alpha = 1.0 - abs(texel0.r - texel1.r);
+    if(alpha > 0.0)
+        gl_FragColor = texel1 / alpha;
+    gl_FragColor.a = alpha;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 13f3e6e..e5b181b 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -84,6 +84,9 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl()
     , mnTransformedMaskedTransformUniform(0)
     , mnTransformedMaskedSamplerUniform(0)
     , mnTransformedMaskedMaskUniform(0)
+    , mnDiffTextureProgram(0)
+    , mnDiffTextureUniform(0)
+    , mnDiffMaskUniform(0)
     , mnMaskedTextureProgram(0)
     , mnMaskedSamplerUniform(0)
     , mnMaskSamplerUniform(0)
@@ -373,6 +376,21 @@ bool OpenGLSalGraphicsImpl::CreateTransformedTextureProgram( void )
     return true;
 }
 
+bool OpenGLSalGraphicsImpl::CreateDiffTextureProgram( void )
+{
+    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;
+}
+
 bool OpenGLSalGraphicsImpl::CreateMaskedTextureProgram( void )
 {
     mnMaskedTextureProgram = OpenGLHelper::LoadShaders( "maskedTextureVertexShader", "maskedTextureFragmentShader" );
@@ -838,6 +856,35 @@ void OpenGLSalGraphicsImpl::DrawAlphaTexture( OpenGLTexture& rTexture, const Sal
         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
     DrawTexture( rTexture, rPosAry, bInverted );
     glDisable( GL_BLEND );
+    CHECK_GL_ERROR();
+}
+
+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 );
+    DrawTextureRect( rTexture, rPosAry, bInverted );
+    glDisable( GL_BLEND );
+
+    glActiveTexture( GL_TEXTURE1 );
+    rMask.Unbind();
+    glActiveTexture( GL_TEXTURE0 );
+    rTexture.Unbind();
+    glUseProgram( 0 );
 
     CHECK_GL_ERROR();
 }
diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx
index bfc1bbb..afaea92 100644
--- a/vcl/opengl/x11/gdiimpl.cxx
+++ b/vcl/opengl/x11/gdiimpl.cxx
@@ -126,16 +126,17 @@ bool X11OpenGLSalGraphicsImpl::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX,
     return true;
 }
 
-bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY )
+bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY )
 {
     const int aAttribs[] = {
         GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
-        GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
+        GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
         None
     };
     Display* pDisplay = mrParent.GetXDisplay();
     GLXFBConfig pFbConfig;
     GLXPixmap pGlxPixmap;
+    GLXPixmap pGlxMask;
     SalTwoRect aPosAry;
     bool bInverted;
 
@@ -148,25 +149,48 @@ bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX,
     aPosAry.mnSrcWidth = aPosAry.mnDestWidth = pPixmap->GetWidth();
     aPosAry.mnSrcHeight = aPosAry.mnDestHeight = pPixmap->GetHeight();
 
+    PreDraw();
+    //glClear( GL_COLOR_BUFFER_BIT );
+
     XSync( pDisplay, 0 );
     pFbConfig = OpenGLHelper::GetPixmapFBConfig( pDisplay, bInverted );
     pGlxPixmap = glXCreatePixmap( pDisplay, pFbConfig, pPixmap->GetPixmap(), aAttribs);
+    if( pMask != NULL )
+        pGlxMask = glXCreatePixmap( pDisplay, pFbConfig, pMask->GetPixmap(), aAttribs);
     XSync( pDisplay, 0 );
 
-    PreDraw();
+    if( !pGlxPixmap )
+        SAL_WARN( "vcl.opengl", "Couldn't create GLXPixmap" );
+
+    //TODO: lfrb: glXGetProc to get the functions
 
     OpenGLTexture aTexture( pPixmap->GetWidth(), pPixmap->GetHeight(), false );
     glActiveTexture( GL_TEXTURE0 );
     aTexture.Bind();
-
-    //TODO: lfrb: glXGetProc to get the functions
     glXBindTexImageEXT( pDisplay, pGlxPixmap, GLX_FRONT_LEFT_EXT, NULL );
+    aTexture.Unbind();
+
+    if( pMask != NULL && pGlxMask )
+    {
+        OpenGLTexture aMaskTexture( pMask->GetWidth(), pMask->GetHeight(), false );
+        aMaskTexture.Bind();
+        glXBindTexImageEXT( pDisplay, pGlxMask, GLX_FRONT_LEFT_EXT, NULL );
+        aMaskTexture.Unbind();
 
-    DrawTexture( aTexture, aPosAry, bInverted );
+        DrawTextureDiff( aTexture, aMaskTexture, aPosAry, !bInverted );
+
+        glXReleaseTexImageEXT( pDisplay, pGlxMask, GLX_FRONT_LEFT_EXT );
+        glXDestroyPixmap( pDisplay, pGlxMask );
+    }
+    else
+    {
+        DrawTexture( aTexture, aPosAry, !bInverted );
+    }
+
+    CHECK_GL_ERROR();
 
     glXReleaseTexImageEXT( pDisplay, pGlxPixmap, GLX_FRONT_LEFT_EXT );
     glXDestroyPixmap( pDisplay, pGlxPixmap );
-    aTexture.Unbind();
 
     PostDraw();
 
diff --git a/vcl/unx/generic/gdi/gdiimpl.cxx b/vcl/unx/generic/gdi/gdiimpl.cxx
index bcf8d05..91c4db7 100644
--- a/vcl/unx/generic/gdi/gdiimpl.cxx
+++ b/vcl/unx/generic/gdi/gdiimpl.cxx
@@ -185,8 +185,9 @@ bool X11SalGraphicsImpl::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int n
     return true;
 }
 
-bool X11SalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY )
+bool X11SalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* /*Mask*/, int nX, int nY )
 {
+    // TODO: lfrb: Use the mask
     GC aFontGC = mrParent.GetFontGC();
 
     // The GC can't be null, otherwise we'd have no clip region
diff --git a/vcl/unx/generic/gdi/gdiimpl.hxx b/vcl/unx/generic/gdi/gdiimpl.hxx
index 20c995f..675e2cd 100644
--- a/vcl/unx/generic/gdi/gdiimpl.hxx
+++ b/vcl/unx/generic/gdi/gdiimpl.hxx
@@ -287,7 +287,7 @@ public:
 
     void Init() SAL_OVERRIDE;
     bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE;
-    bool RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE;
+    bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) SAL_OVERRIDE;
 };
 
 #endif
diff --git a/vcl/unx/generic/gdi/salgdi2.cxx b/vcl/unx/generic/gdi/salgdi2.cxx
index b848d660..f1911b6 100644
--- a/vcl/unx/generic/gdi/salgdi2.cxx
+++ b/vcl/unx/generic/gdi/salgdi2.cxx
@@ -89,11 +89,11 @@ bool X11SalGraphics::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY )
     return rImpl.FillPixmapFromScreen( pPixmap, nX, nY );
 }
 
-bool X11SalGraphics::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY )
+bool X11SalGraphics::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY )
 {
     SAL_INFO( "vcl", "RenderPixmapToScreen" );
     X11GraphicsImpl& rImpl = dynamic_cast<X11GraphicsImpl&>(*mpImpl.get());
-    return rImpl.RenderPixmapToScreen( pPixmap, nX, nY );
+    return rImpl.RenderPixmapToScreen( pPixmap, pMask, nX, nY );
 }
 
 extern "C"
diff --git a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
index 10cff10..46ec7b4 100644
--- a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
+++ b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
@@ -50,6 +50,13 @@ const char* const tabPrelitDataName="libreoffice-tab-is-prelit";
 bool GtkSalGraphics::bThemeChanged = true;
 bool GtkSalGraphics::bNeedPixmapPaint = false;
 
+enum
+{
+    BG_NONE = 0,
+    BG_WHITE,
+    BG_BLACK
+};
+
 GtkSalGraphics::GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow )
     : X11SalGraphics(),
       m_pWindow( pWindow ),
@@ -284,9 +291,12 @@ protected:
 
 GdkX11Pixmap::GdkX11Pixmap( int nWidth, int nHeight, int nDepth )
 : X11Pixmap( nWidth, nHeight )
-, mnDepth( nDepth )
 {
     mpGdkPixmap = gdk_pixmap_new( NULL, nWidth, nHeight, nDepth );
+    mnDepth = gdk_drawable_get_depth( GDK_DRAWABLE( mpGdkPixmap ) );
+
+    GdkScreen *pScreen = gdk_drawable_get_screen( GDK_DRAWABLE( mpGdkPixmap ) );
+    gdk_drawable_set_colormap( GDK_DRAWABLE( mpGdkPixmap ), gdk_screen_get_default_colormap( pScreen ) );
 }
 
 GdkX11Pixmap::~GdkX11Pixmap()
@@ -336,11 +346,12 @@ public:
     ControlState m_nState;
     Rectangle      m_pixmapRect;
     GdkX11Pixmap*  m_pixmap;
+    GdkX11Pixmap*  m_mask;
 
-    NWPixmapCacheData() : m_nType(0), m_nState(0), m_pixmap(0) {}
+    NWPixmapCacheData() : m_nType(0), m_nState(0), m_pixmap(0), m_mask(0) {}
     ~NWPixmapCacheData()
-        { SetPixmap( NULL ); };
-    void SetPixmap( GdkX11Pixmap* pPixmap );
+        { SetPixmap( NULL, NULL ); };
+    void SetPixmap( GdkX11Pixmap* pPixmap, GdkX11Pixmap* pMask );
 };
 
 class NWPixmapCache
@@ -357,8 +368,8 @@ public:
         { delete [] pData; m_idx = 0; m_size = n; pData = new NWPixmapCacheData[m_size]; }
     int GetSize() const { return m_size; }
 
-    bool Find( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap** pPixmap );
-    void Fill( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap* pPixmap );
+    bool Find( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap** pPixmap, GdkX11Pixmap** pMask );
+    void Fill( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap* pPixmap, GdkX11Pixmap* pMask );
 
     void ThemeChanged();
 };
@@ -375,12 +386,15 @@ public:
 
 // --- implementation ---
 
-void NWPixmapCacheData::SetPixmap( GdkX11Pixmap* pPixmap )
+void NWPixmapCacheData::SetPixmap( GdkX11Pixmap* pPixmap, GdkX11Pixmap* pMask )
 {
     if( m_pixmap )
         delete m_pixmap;
+    if( m_mask )
+        delete m_mask;
 
     m_pixmap = pPixmap;
+    m_mask = pMask;
 }
 
 NWPixmapCache::NWPixmapCache( SalX11Screen nScreen )
@@ -403,10 +417,10 @@ void NWPixmapCache::ThemeChanged()
     // throw away cached pixmaps
     int i;
     for(i=0; i<m_size; i++)
-        pData[i].SetPixmap( NULL );
+        pData[i].SetPixmap( NULL, NULL );
 }
 
-bool  NWPixmapCache::Find( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap** pPixmap )
+bool  NWPixmapCache::Find( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap** pPixmap, GdkX11Pixmap** pMask )
 {
     aState &= ~CTRL_CACHING_ALLOWED; // mask clipping flag
     int i;
@@ -419,13 +433,14 @@ bool  NWPixmapCache::Find( ControlType aType, ControlState aState, const Rectang
             pData[i].m_pixmap != NULL )
         {
             *pPixmap = pData[i].m_pixmap;
+            *pMask = pData[i].m_mask;
             return true;
         }
     }
     return false;
 }
 
-void NWPixmapCache::Fill( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap* pPixmap )
+void NWPixmapCache::Fill( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap* pPixmap, GdkX11Pixmap* pMask )
 {
     if( !(aState & CTRL_CACHING_ALLOWED) )
         return;
@@ -435,7 +450,7 @@ void NWPixmapCache::Fill( ControlType aType, ControlState aState, const Rectangl
     pData[m_idx].m_nType = aType;
     pData[m_idx].m_nState = aState;
     pData[m_idx].m_pixmapRect = r_pixmapRect;
-    pData[m_idx].SetPixmap( pPixmap );
+    pData[m_idx].SetPixmap( pPixmap, pMask );
 }
 
 void NWPixmapCacheList::AddCache( NWPixmapCache* pCache )
@@ -494,6 +509,10 @@ void GtkData::initNWF( void )
 
     pSVData->maNWFData.mbDDListBoxNoTextArea = true;
 
+    // use offscreen rendering when using OpenGL backend
+    if( OpenGLHelper::isVCLOpenGLEnabled() )
+        GtkSalGraphics::bNeedPixmapPaint = true;
+
     int nScreens = GetGtkSalData()->GetGtkDisplay()->GetXScreenCount();
     gWidgetData = WidgetDataVector( nScreens );
     for( int i = 0; i < nScreens; i++ )
@@ -530,10 +549,6 @@ 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" );
@@ -864,8 +879,10 @@ bool GtkSalGraphics::drawNativeControl(    ControlType nType,
         aClipRegion = aCtrlRect;
 
     clipList aClip;
-    GdkDrawable* gdkDrawable = GDK_DRAWABLE( GetGdkWindow() );
+    int nPasses = 0;
+    GdkDrawable* gdkDrawable[2];
     std::unique_ptr<GdkX11Pixmap> xPixmap;
+    std::unique_ptr<GdkX11Pixmap> xMask;
     Rectangle aPixmapRect;
     if( ( bNeedPixmapPaint )
         && nType != CTRL_SCROLLBAR
@@ -880,15 +897,22 @@ bool GtkSalGraphics::drawNativeControl(    ControlType nType,
         // outside the rectangle, see e.g. checkbox
         aPixmapRect = Rectangle( Point( aCtrlRect.Left()-1, aCtrlRect.Top()-1 ),
                                  Size( aCtrlRect.GetWidth()+2, aCtrlRect.GetHeight()+2) );
-        xPixmap.reset(NWGetPixmapFromScreen(aPixmapRect));
-        if (!xPixmap)
+
+        xPixmap.reset( NWGetPixmapFromScreen( aPixmapRect, BG_WHITE ) );
+        xMask.reset( NWGetPixmapFromScreen( aPixmapRect, BG_BLACK ) );
+        if( !xPixmap || !xMask )
             return false;
-        gdkDrawable = xPixmap->GetGdkDrawable();
+        nPasses = 2;
+        gdkDrawable[0] = xPixmap->GetGdkDrawable();
+        gdkDrawable[1] = xMask->GetGdkDrawable();
+
         aCtrlRect = Rectangle( Point(1,1), aCtrlRect.GetSize() );
         aClip.push_back( aCtrlRect );
     }
     else
     {
+        nPasses = 1;
+        gdkDrawable[0] = GDK_DRAWABLE( GetGdkWindow() );
         RectangleVector aRectangles;
         aClipRegion.GetRegionRectangles(aRectangles);
 
@@ -901,68 +925,95 @@ bool GtkSalGraphics::drawNativeControl(    ControlType nType,
         }
     }
 
-    assert(gdkDrawable && "rhbz#1050162");
-    if (gdkDrawable == 0)
-        return false;
+    bool returnVal = false;
+    SAL_INFO( "vcl.opengl", "Rendering with " << nPasses << " passe(s)" );
+
+    for( int i = 0; i < nPasses; ++i )
+    {
+        assert(gdkDrawable[i] && "rhbz#1050162");
+        if( gdkDrawable[i] == 0 )
+            return false;
 
-    bool            returnVal = false;
+        returnVal = DoDrawNativeControl( gdkDrawable[i], nType, nPart, aCtrlRect, aClip,
+                                         nState, aValue, rCaption );
+        if( !returnVal )
+            break;
+    }
+
+    if( xPixmap )
+        returnVal = NWRenderPixmapToScreen( xPixmap.get(), xMask.get(), aPixmapRect) && returnVal;
+
+    return( returnVal );
+}
+
+
+bool GtkSalGraphics::DoDrawNativeControl(
+                            GdkDrawable* pDrawable,
+                            ControlType nType,
+                            ControlPart nPart,
+                            const Rectangle& aCtrlRect,
+                            const clipList& aClip,
+                            ControlState nState,
+                            const ImplControlValue& aValue,
+                            const OUString& rCaption )
+{
     if ( (nType==CTRL_PUSHBUTTON) && (nPart==PART_ENTIRE_CONTROL) )
     {
-        returnVal = NWPaintGTKButton( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKButton( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if ( (nType==CTRL_RADIOBUTTON) && (nPart==PART_ENTIRE_CONTROL) )
     {
-        returnVal = NWPaintGTKRadio( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKRadio( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if ( (nType==CTRL_CHECKBOX) && (nPart==PART_ENTIRE_CONTROL) )
     {
-        returnVal = NWPaintGTKCheck( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKCheck( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if ( (nType==CTRL_SCROLLBAR) && ((nPart==PART_DRAW_BACKGROUND_HORZ) || (nPart==PART_DRAW_BACKGROUND_VERT)) )
     {
-        returnVal = NWPaintGTKScrollbar( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKScrollbar( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if ( ((nType==CTRL_EDITBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==HAS_BACKGROUND_TEXTURE)) )
         || ((nType==CTRL_SPINBOX) && (nPart==HAS_BACKGROUND_TEXTURE))
     || ((nType==CTRL_COMBOBOX) && (nPart==HAS_BACKGROUND_TEXTURE))
     || ((nType==CTRL_LISTBOX) && (nPart==HAS_BACKGROUND_TEXTURE)) )
     {
-        returnVal = NWPaintGTKEditBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKEditBox( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if ( ((nType==CTRL_MULTILINE_EDITBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==HAS_BACKGROUND_TEXTURE)) ) )
     {
-        returnVal = NWPaintGTKEditBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKEditBox( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if ( ((nType==CTRL_SPINBOX) || (nType==CTRL_SPINBUTTONS))
         && ((nPart==PART_ENTIRE_CONTROL) || (nPart==PART_ALL_BUTTONS)) )
     {
-        returnVal = NWPaintGTKSpinBox( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKSpinBox( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if ( (nType == CTRL_COMBOBOX) &&
         ( (nPart==PART_ENTIRE_CONTROL)
         ||(nPart==PART_BUTTON_DOWN)
         ) )
     {
-        returnVal = NWPaintGTKComboBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKComboBox( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if ( (nType==CTRL_TAB_ITEM) || (nType==CTRL_TAB_PANE) || (nType==CTRL_TAB_BODY) )
     {
         if ( nType == CTRL_TAB_BODY )
-            returnVal = true;
+            return true;
         else
-            returnVal = NWPaintGTKTabItem( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption);
+            return NWPaintGTKTabItem( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption);
     }
     else if ( (nType==CTRL_LISTBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==PART_WINDOW)) )
     {
-        returnVal = NWPaintGTKListBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKListBox( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if ( nType== CTRL_TOOLBAR )
     {
-        returnVal = NWPaintGTKToolbar( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKToolbar( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if ( nType== CTRL_MENUBAR )
     {
-        returnVal = NWPaintGTKMenubar( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKMenubar( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if(    (nType == CTRL_MENU_POPUP)
         && (  (nPart == PART_ENTIRE_CONTROL)
@@ -974,55 +1025,50 @@ bool GtkSalGraphics::drawNativeControl(    ControlType nType,
     )
     )
     {
-        returnVal = NWPaintGTKPopupMenu( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKPopupMenu( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if( (nType == CTRL_TOOLTIP) && (nPart == PART_ENTIRE_CONTROL) )
     {
-        returnVal = NWPaintGTKTooltip( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKTooltip( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if( (nType == CTRL_PROGRESS) && (nPart == PART_ENTIRE_CONTROL) )
     {
-        returnVal = NWPaintGTKProgress( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKProgress( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if( (nType == CTRL_LISTNODE) && (nPart == PART_ENTIRE_CONTROL) )
     {
-        returnVal = NWPaintGTKListNode( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKListNode( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if( (nType == CTRL_LISTNET) && (nPart == PART_ENTIRE_CONTROL) )
     {
         // don't actually draw anything; gtk treeviews do not draw lines
-        returnVal = TRUE;
+        return TRUE;
     }
     else if( nType == CTRL_SLIDER )
     {
-        returnVal = NWPaintGTKSlider( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKSlider( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if( nType == CTRL_WINDOW_BACKGROUND )
     {
-        returnVal = NWPaintGTKWindowBackground( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKWindowBackground( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if( nType == CTRL_FIXEDLINE )
     {
-        returnVal = NWPaintGTKFixedLine( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+        return NWPaintGTKFixedLine( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
     else if(nType==CTRL_FRAME)
     {
-        returnVal = NWPaintGTKFrame( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption);
+        return NWPaintGTKFrame( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption);
     }
     else if(nType==CTRL_LISTHEADER)
     {
         if(nPart == PART_BUTTON)
-            returnVal = NWPaintGTKListHeader( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+            return NWPaintGTKListHeader( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
         else if(nPart == PART_ARROW)
-            returnVal = NWPaintGTKArrow( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
+            return NWPaintGTKArrow( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
     }
 
-    if( xPixmap )
-    {
-        returnVal = NWRenderPixmapToScreen(xPixmap.get(), aPixmapRect) && returnVal;
-    }
-
-    return( returnVal );
+    return false;
 }
 
 /*
@@ -2114,7 +2160,7 @@ bool GtkSalGraphics::NWPaintGTKScrollbar( ControlType, ControlPart nPart,
                          arrowRect.GetWidth(), arrowRect.GetHeight() );
     }
 
-    bool bRet = NWRenderPixmapToScreen( pixmap, pixmapRect );
+    bool bRet = NWRenderPixmapToScreen( pixmap, NULL, pixmapRect );
     delete pixmap;
 
     return bRet;
@@ -2341,8 +2387,6 @@ bool GtkSalGraphics::NWPaintGTKSpinBox( ControlType nType, ControlPart nPart,
                                         const ImplControlValue& aValue,
                                         const OUString& rCaption )
 {
-    GdkX11Pixmap *       pixmap;
-    GdkPixmap *          gdkPixmap;
     Rectangle            pixmapRect;
     GtkStateType        stateType;
     GtkShadowType        shadowType;
@@ -2383,56 +2427,59 @@ bool GtkSalGraphics::NWPaintGTKSpinBox( ControlType nType, ControlPart nPart,
     else
         pixmapRect = rControlRectangle;
 
-    pixmap = NWGetPixmapFromScreen( pixmapRect );
-    if ( !pixmap )
+    std::unique_ptr<GdkX11Pixmap> pixmap( NWGetPixmapFromScreen( pixmapRect, BG_WHITE ) );
+    std::unique_ptr<GdkX11Pixmap> mask( NWGetPixmapFromScreen( pixmapRect, BG_BLACK ) );
+    if( !pixmap || !mask )
         return false;
-    gdkPixmap = pixmap->GetGdkPixmap();
 
-    // First render background
-    gtk_paint_flat_box(m_pWindow->style,gdkPixmap,GTK_STATE_NORMAL,GTK_SHADOW_NONE,NULL,m_pWindow,"base",
-            -pixmapRect.Left(),
-            -pixmapRect.Top(),
-            pixmapRect.Right(),
-            pixmapRect.Bottom() );
+    for( int i = 0; i < 2; ++i )
+    {
+        GdkPixmap* gdkPixmap = (i == 0) ? pixmap->GetGdkPixmap()
+                                        : mask->GetGdkPixmap();
 
-    upBtnRect = NWGetSpinButtonRect( m_nXScreen, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption );
-    downBtnRect = NWGetSpinButtonRect( m_nXScreen, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption );
+        // First render background
+        gtk_paint_flat_box(m_pWindow->style,gdkPixmap,GTK_STATE_NORMAL,GTK_SHADOW_NONE,NULL,m_pWindow,"base",
+                -pixmapRect.Left(),
+                -pixmapRect.Top(),
+                pixmapRect.Right(),
+                pixmapRect.Bottom() );
 
-    if ( (nType==CTRL_SPINBOX) && (nPart!=PART_ALL_BUTTONS) )
-    {
-        // Draw an edit field for SpinBoxes and ComboBoxes
-        Rectangle aEditBoxRect( pixmapRect );
-        aEditBoxRect.SetSize( Size( pixmapRect.GetWidth() - upBtnRect.GetWidth(), aEditBoxRect.GetHeight() ) );
-        if( Application::GetSettings().GetLayoutRTL() )
-            aEditBoxRect.setX( upBtnRect.GetWidth() );
-        else
-            aEditBoxRect.setX( 0 );
-        aEditBoxRect.setY( 0 );
+        upBtnRect = NWGetSpinButtonRect( m_nXScreen, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption );
+        downBtnRect = NWGetSpinButtonRect( m_nXScreen, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption );
 
-        NWPaintOneEditBox( m_nXScreen, gdkPixmap, NULL, nType, nPart, aEditBoxRect, nState, aValue, rCaption );
-    }
+        if ( (nType==CTRL_SPINBOX) && (nPart!=PART_ALL_BUTTONS) )
+        {
+            // Draw an edit field for SpinBoxes and ComboBoxes
+            Rectangle aEditBoxRect( pixmapRect );
+            aEditBoxRect.SetSize( Size( pixmapRect.GetWidth() - upBtnRect.GetWidth(), aEditBoxRect.GetHeight() ) );
+            if( Application::GetSettings().GetLayoutRTL() )
+                aEditBoxRect.setX( upBtnRect.GetWidth() );
+            else
+                aEditBoxRect.setX( 0 );
+            aEditBoxRect.setY( 0 );
 
-    NWSetWidgetState( gWidgetData[m_nXScreen].gSpinButtonWidget, nState, stateType );
-    gtk_widget_style_get( gWidgetData[m_nXScreen].gSpinButtonWidget, "shadow_type", &shadowType, (char *)NULL );
+            NWPaintOneEditBox( m_nXScreen, gdkPixmap, NULL, nType, nPart, aEditBoxRect, nState, aValue, rCaption );
+        }
 
-    if ( shadowType != GTK_SHADOW_NONE )
-    {
-        Rectangle        shadowRect( upBtnRect );
+        NWSetWidgetState( gWidgetData[m_nXScreen].gSpinButtonWidget, nState, stateType );
+        gtk_widget_style_get( gWidgetData[m_nXScreen].gSpinButtonWidget, "shadow_type", &shadowType, (char *)NULL );
 
-        shadowRect.Union( downBtnRect );
-        gtk_paint_box( gWidgetData[m_nXScreen].gSpinButtonWidget->style, gdkPixmap, GTK_STATE_NORMAL, shadowType, NULL,
-            gWidgetData[m_nXScreen].gSpinButtonWidget, "spinbutton",
-            (shadowRect.Left() - pixmapRect.Left()), (shadowRect.Top() - pixmapRect.Top()),
-            shadowRect.GetWidth(), shadowRect.GetHeight() );
-    }
+        if ( shadowType != GTK_SHADOW_NONE )
+        {
+            Rectangle        shadowRect( upBtnRect );
 
-    NWPaintOneSpinButton( m_nXScreen, gdkPixmap, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption );
-    NWPaintOneSpinButton( m_nXScreen, gdkPixmap, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption );
+            shadowRect.Union( downBtnRect );
+            gtk_paint_box( gWidgetData[m_nXScreen].gSpinButtonWidget->style, gdkPixmap, GTK_STATE_NORMAL, shadowType, NULL,
+                gWidgetData[m_nXScreen].gSpinButtonWidget, "spinbutton",
+                (shadowRect.Left() - pixmapRect.Left()), (shadowRect.Top() - pixmapRect.Top()),
+                shadowRect.GetWidth(), shadowRect.GetHeight() );
+        }
 
-    bool bRet = NWRenderPixmapToScreen( pixmap, pixmapRect );
-    delete pixmap;
+        NWPaintOneSpinButton( m_nXScreen, gdkPixmap, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption );
+        NWPaintOneSpinButton( m_nXScreen, gdkPixmap, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption );
+    }
 
-    return bRet;
+    return NWRenderPixmapToScreen( pixmap.get(), mask.get(), pixmapRect );
 }
 
 static Rectangle NWGetSpinButtonRect( SalX11Screen nScreen,
@@ -2667,7 +2714,7 @@ bool GtkSalGraphics::NWPaintGTKTabItem( ControlType nType, ControlPart,
 {
     OSL_ASSERT( nType != CTRL_TAB_ITEM || aValue.getType() == CTRL_TAB_ITEM );
     GdkX11Pixmap *   pixmap;
-    GdkPixmap *      gdkPixmap;
+    GdkX11Pixmap *   mask;
     Rectangle        pixmapRect;
     Rectangle        tabRect;
     GtkStateType    stateType;
@@ -2730,83 +2777,88 @@ bool GtkSalGraphics::NWPaintGTKTabItem( ControlType nType, ControlPart,
 
     if( nType == CTRL_TAB_ITEM )
     {
-        if( aCacheItems.Find( nType, nState, pixmapRect, &pixmap ) )
-            return NWRenderPixmapToScreen( pixmap, pixmapRect );
+        if( aCacheItems.Find( nType, nState, pixmapRect, &pixmap, &mask ) )
+            return NWRenderPixmapToScreen( pixmap, mask, pixmapRect );
     }
     else
     {
-        if( aCachePage.Find( nType, nState, pixmapRect, &pixmap ) )
-            return NWRenderPixmapToScreen( pixmap, pixmapRect );
+        if( aCachePage.Find( nType, nState, pixmapRect, &pixmap, &mask ) )
+            return NWRenderPixmapToScreen( pixmap, mask, pixmapRect );
     }
 
-    pixmap = new GdkX11Pixmap( pixmapRect.GetWidth(), pixmapRect.GetHeight(),
-                               GetGenericData()->GetSalDisplay()->GetVisual( m_nXScreen ).GetDepth() );
-    gdkPixmap = pixmap->GetGdkPixmap();
+    int nDepth = GetGenericData()->GetSalDisplay()->GetVisual( m_nXScreen ).GetDepth();
+    pixmap = new GdkX11Pixmap( pixmapRect.GetWidth(), pixmapRect.GetHeight(), nDepth );
+    mask = new GdkX11Pixmap( pixmapRect.GetWidth(), pixmapRect.GetHeight(), nDepth );
     GdkRectangle paintRect;
     paintRect.x = paintRect.y = 0;
     paintRect.width = pixmapRect.GetWidth();
     paintRect.height = pixmapRect.GetHeight();
 
-    gtk_paint_flat_box( m_pWindow->style, gdkPixmap, GTK_STATE_NORMAL,
-                        GTK_SHADOW_NONE, &paintRect, m_pWindow, "base",
-                        -rControlRectangle.Left(),
-                        -rControlRectangle.Top(),
-                        pixmapRect.GetWidth()+rControlRectangle.Left(),
-                        pixmapRect.GetHeight()+rControlRectangle.Top());
-
-    NWSetWidgetState( gWidgetData[m_nXScreen].gNotebookWidget, nState, stateType );
-
-    switch( nType )
+    for( int i = 0; i < 2; ++i )
     {
-        case CTRL_TAB_BODY:
-            break;
+        GdkPixmap* gdkPixmap = (i == 0) ? pixmap->GetGdkPixmap() : mask->GetGdkPixmap();
 
-        case CTRL_TAB_PANE:
-            gtk_paint_box_gap( gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, gWidgetData[m_nXScreen].gNotebookWidget,
-                (char *)"notebook", 0, 0, pixmapRect.GetWidth(), pixmapRect.GetHeight(), GTK_POS_TOP, 0, 0 );
-            break;
+        gtk_paint_flat_box( m_pWindow->style, gdkPixmap, GTK_STATE_NORMAL,
+                            GTK_SHADOW_NONE, &paintRect, m_pWindow, "base",
+                            -rControlRectangle.Left(),
+                            -rControlRectangle.Top(),
+                            pixmapRect.GetWidth()+rControlRectangle.Left(),
+                            pixmapRect.GetHeight()+rControlRectangle.Top());
 
-        case CTRL_TAB_ITEM:
+        NWSetWidgetState( gWidgetData[m_nXScreen].gNotebookWidget, nState, stateType );
+
+        switch( nType )
         {
-            stateType = ( nState & CTRL_STATE_SELECTED ) ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE;
+            case CTRL_TAB_BODY:
+                break;
 
-            // First draw the background
-            gtk_paint_flat_box(gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap,
-                                   GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, m_pWindow, "base",
-                                   -rControlRectangle.Left(),
-                                   -rControlRectangle.Top(),
-                                   pixmapRect.GetWidth()+rControlRectangle.Left(),
-                                   pixmapRect.GetHeight()+rControlRectangle.Top());
+            case CTRL_TAB_PANE:
+                gtk_paint_box_gap( gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, gWidgetData[m_nXScreen].gNotebookWidget,
+                    (char *)"notebook", 0, 0, pixmapRect.GetWidth(), pixmapRect.GetHeight(), GTK_POS_TOP, 0, 0 );
+                break;
 
-            // Now the tab itself
-            if( nState & CTRL_STATE_ROLLOVER )
-                g_object_set_data(G_OBJECT(gdkPixmap),tabPrelitDataName,reinterpret_cast<gpointer>(TRUE));
+            case CTRL_TAB_ITEM:
+            {
+                stateType = ( nState & CTRL_STATE_SELECTED ) ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE;
 
-            gtk_paint_extension( gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, stateType, GTK_SHADOW_OUT, NULL, gWidgetData[m_nXScreen].gNotebookWidget,
-                (char *)"tab", (tabRect.Left() - pixmapRect.Left()), (tabRect.Top() - pixmapRect.Top()),
-                tabRect.GetWidth(), tabRect.GetHeight(), GTK_POS_BOTTOM );
+                // First draw the background
+                gtk_paint_flat_box(gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap,
+                                       GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, m_pWindow, "base",
+                                       -rControlRectangle.Left(),
+                                       -rControlRectangle.Top(),
+                                       pixmapRect.GetWidth()+rControlRectangle.Left(),
+                                       pixmapRect.GetHeight()+rControlRectangle.Top());
 
-            g_object_steal_data(G_OBJECT(gdkPixmap),tabPrelitDataName);
+                // Now the tab itself
+                if( nState & CTRL_STATE_ROLLOVER )
+                    g_object_set_data(G_OBJECT(gdkPixmap),tabPrelitDataName,reinterpret_cast<gpointer>(TRUE));
 
-            if ( nState & CTRL_STATE_SELECTED )
-            {
-                gtk_paint_flat_box( m_pWindow->style, gdkPixmap, stateType, GTK_SHADOW_NONE, NULL, m_pWindow,
-                    "base", 0, (pixmapRect.GetHeight() - 1), pixmapRect.GetWidth(), 1 );
+                gtk_paint_extension( gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, stateType, GTK_SHADOW_OUT, NULL, gWidgetData[m_nXScreen].gNotebookWidget,
+                    (char *)"tab", (tabRect.Left() - pixmapRect.Left()), (tabRect.Top() - pixmapRect.Top()),
+                    tabRect.GetWidth(), tabRect.GetHeight(), GTK_POS_BOTTOM );
+
+                g_object_steal_data(G_OBJECT(gdkPixmap),tabPrelitDataName);
+
+                if ( nState & CTRL_STATE_SELECTED )
+                {
+                    gtk_paint_flat_box( m_pWindow->style, gdkPixmap, stateType, GTK_SHADOW_NONE, NULL, m_pWindow,
+                        "base", 0, (pixmapRect.GetHeight() - 1), pixmapRect.GetWidth(), 1 );
+                }
+                break;
             }
-            break;
-        }
 
-        default:
-            break;
+            default:
+                break;
+        }
     }
 
     // cache data
     if( nType == CTRL_TAB_ITEM )
-        aCacheItems.Fill( nType, nState, pixmapRect, pixmap );
+        aCacheItems.Fill( nType, nState, pixmapRect, pixmap, mask );
     else
-        aCachePage.Fill( nType, nState, pixmapRect, pixmap );
+        aCachePage.Fill( nType, nState, pixmapRect, pixmap, mask );
 
-    bool bSuccess = NWRenderPixmapToScreen( pixmap, pixmapRect );
+    bool bSuccess = NWRenderPixmapToScreen( pixmap, mask, pixmapRect );
     return bSuccess;
 }
 
@@ -3382,24 +3434,26 @@ bool GtkSalGraphics::NWPaintGTKListNode(
             break;
     }
 
-    GdkX11Pixmap* pixmap = NWGetPixmapFromScreen( aRect );
-    if( ! pixmap )
+    std::unique_ptr<GdkX11Pixmap> pixmap( NWGetPixmapFromScreen( aRect, BG_WHITE ) );
+    std::unique_ptr<GdkX11Pixmap> mask( NWGetPixmapFromScreen( aRect, BG_BLACK ) );
+    if( !pixmap || !mask )
         return false;
 
-    GdkDrawable* const &pixDrawable = pixmap->GetGdkDrawable();
-    gtk_paint_expander( gWidgetData[m_nXScreen].gTreeView->style,
-                        pixDrawable,
-                        stateType,
-                        NULL,
-                        gWidgetData[m_nXScreen].gTreeView,
-                        "treeview",
-                        w/2, h/2,
-                        eStyle );
-
-    bool bRet = NWRenderPixmapToScreen( pixmap, aRect );
-    delete pixmap;
+    for( int i = 0; i < 2; ++i )
+    {
+        GdkDrawable* const &pixDrawable = (i == 0) ? pixmap->GetGdkDrawable()
+                                                   : mask->GetGdkDrawable();
+        gtk_paint_expander( gWidgetData[m_nXScreen].gTreeView->style,
+                            pixDrawable,
+                            stateType,
+                            NULL,
+                            gWidgetData[m_nXScreen].gTreeView,
+                            "treeview",
+                            w/2, h/2,
+                            eStyle );
+    }
 
-    return bRet;
+    return NWRenderPixmapToScreen( pixmap.get(), mask.get(), aRect );
 }
 
 bool GtkSalGraphics::NWPaintGTKProgress(
@@ -3418,57 +3472,60 @@ bool GtkSalGraphics::NWPaintGTKProgress(
 
     long nProgressWidth = rValue.getNumericVal();
 
-    GdkX11Pixmap* pixmap = NWGetPixmapFromScreen( Rectangle( Point( 0, 0 ), Size( w, h ) ) );
-    if( ! pixmap )
+    Rectangle aRect( Point( 0, 0 ), Size( w, h ) );
+    std::unique_ptr<GdkX11Pixmap> pixmap( NWGetPixmapFromScreen( aRect, BG_WHITE ) );
+    std::unique_ptr<GdkX11Pixmap> mask( NWGetPixmapFromScreen( aRect, BG_BLACK ) );
+    if( !pixmap || !mask )
         return false;
 
-    GdkDrawable* const &pixDrawable = pixmap->GetGdkDrawable();
-
-    // paint background
-    gtk_paint_flat_box(gWidgetData[m_nXScreen].gProgressBar->style, pixDrawable,
-                           GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, m_pWindow, "base",
-                           -rControlRectangle.Left(),-rControlRectangle.Top(),
-                           rControlRectangle.Left()+w,rControlRectangle.Top()+h);
-
-    gtk_paint_flat_box( gWidgetData[m_nXScreen].gProgressBar->style,
-                        pixDrawable,
-                        GTK_STATE_NORMAL,
-                        GTK_SHADOW_NONE,
-                        NULL,
-                        gWidgetData[m_nXScreen].gProgressBar,
-                        "trough",
-                        0, 0, w, h );
-    if( nProgressWidth > 0 )
-    {
-        // paint progress
-        if( Application::GetSettings().GetLayoutRTL() )
-        {
-            gtk_paint_box( gWidgetData[m_nXScreen].gProgressBar->style,
-                           pixDrawable,
-                           GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
-                           NULL,
-                           gWidgetData[m_nXScreen].gProgressBar,
-                           "bar",
-                           w-nProgressWidth, 0, nProgressWidth, h
-                           );
-        }
-        else
+    for( int i = 0; i < 2; ++i )
+    {
+        GdkDrawable* const &pixDrawable = (i == 0) ? pixmap->GetGdkDrawable()
+                                                   : mask->GetGdkDrawable();
+
+        // paint background
+        gtk_paint_flat_box(gWidgetData[m_nXScreen].gProgressBar->style, pixDrawable,
+                               GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, m_pWindow, "base",
+                               -rControlRectangle.Left(),-rControlRectangle.Top(),
+                               rControlRectangle.Left()+w,rControlRectangle.Top()+h);
+
+        gtk_paint_flat_box( gWidgetData[m_nXScreen].gProgressBar->style,
+                            pixDrawable,
+                            GTK_STATE_NORMAL,
+                            GTK_SHADOW_NONE,
+                            NULL,
+                            gWidgetData[m_nXScreen].gProgressBar,
+                            "trough",
+                            0, 0, w, h );
+        if( nProgressWidth > 0 )
         {
-            gtk_paint_box( gWidgetData[m_nXScreen].gProgressBar->style,
-                           pixDrawable,
-                           GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
-                           NULL,
-                           gWidgetData[m_nXScreen].gProgressBar,
-                           "bar",
-                           0, 0, nProgressWidth, h
-                           );
+            // paint progress
+            if( Application::GetSettings().GetLayoutRTL() )
+            {
+                gtk_paint_box( gWidgetData[m_nXScreen].gProgressBar->style,
+                               pixDrawable,
+                               GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
+                               NULL,
+                               gWidgetData[m_nXScreen].gProgressBar,
+                               "bar",
+                               w-nProgressWidth, 0, nProgressWidth, h
+                               );
+            }
+            else
+            {
+                gtk_paint_box( gWidgetData[m_nXScreen].gProgressBar->style,
+                               pixDrawable,
+                               GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
+                               NULL,
+                               gWidgetData[m_nXScreen].gProgressBar,
+                               "bar",
+                               0, 0, nProgressWidth, h
+                               );
+            }
         }
     }
 
-    bool bRet = NWRenderPixmapToScreen( pixmap, rControlRectangle );
-    delete pixmap;
-
-    return bRet;
+    return NWRenderPixmapToScreen( pixmap.get(), mask.get(), rControlRectangle );
 }
 
 bool GtkSalGraphics::NWPaintGTKSlider(
@@ -3488,75 +3545,78 @@ bool GtkSalGraphics::NWPaintGTKSlider(
 
     const SliderValue* pVal = static_cast<const SliderValue*>(&rValue);
 
-    GdkX11Pixmap* pixmap = NWGetPixmapFromScreen( rControlRectangle );
-    if( ! pixmap )
+    std::unique_ptr<GdkX11Pixmap> pixmap( NWGetPixmapFromScreen( rControlRectangle, BG_WHITE ) );
+    std::unique_ptr<GdkX11Pixmap> mask( NWGetPixmapFromScreen( rControlRectangle, BG_BLACK ) );
+    if( !pixmap || !mask )
         return false;
 
-    GdkDrawable* const &pixDrawable = pixmap->GetGdkDrawable();
-    GtkWidget* pWidget = (nPart == PART_TRACK_HORZ_AREA)
-                         ? GTK_WIDGET(gWidgetData[m_nXScreen].gHScale)
-                         : GTK_WIDGET(gWidgetData[m_nXScreen].gVScale);
-    const gchar* pDetail = (nPart == PART_TRACK_HORZ_AREA) ? "hscale" : "vscale";
-    GtkOrientation eOri = (nPart == PART_TRACK_HORZ_AREA) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL;
-    gint slider_width = 10;
-    gint slider_length = 10;
-    gint trough_border = 0;
-    gtk_widget_style_get( pWidget,
-                          "slider-width", &slider_width,
-                          "slider-length", &slider_length,
-                          "trough-border", &trough_border,
-                          NULL);
-
-    GtkStateType eState = (nState & CTRL_STATE_ENABLED) ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE;
-    if( nPart == PART_TRACK_HORZ_AREA )
-    {
-        gtk_paint_box( pWidget->style,
-                       pixDrawable,
-                       eState,
-                       GTK_SHADOW_IN,
-                       NULL,
-                       pWidget,
-                       "trough",
-                       0, (h-slider_width-2*trough_border)/2, w, slider_width + 2*trough_border);
-        gint x = (w - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin);
-        gtk_paint_slider( pWidget->style,
-                          pixDrawable,
-                          eState,
-                          GTK_SHADOW_OUT,
-                          NULL,
-                          pWidget,
-                          pDetail,
-                          x, (h-slider_width)/2,
-                          slider_length, slider_width,
-                          eOri );
-    }
-    else
+    for( int i = 0; i < 2; ++i )
     {
-        gtk_paint_box( pWidget->style,
-                       pixDrawable,
-                       eState,
-                       GTK_SHADOW_IN,
-                       NULL,
-                       pWidget,
-                       "trough",
-                       (w-slider_width-2*trough_border)/2, 0, slider_width + 2*trough_border, h);
-        gint y = (h - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin);
-        gtk_paint_slider( pWidget->style,
-                          pixDrawable,
-                          eState,
-                          GTK_SHADOW_OUT,
-                          NULL,
-                          pWidget,
-                          pDetail,
-                          (w-slider_width)/2, y,
-                          slider_width, slider_length,
-                          eOri );
-    }
-
-    bool bRet = NWRenderPixmapToScreen( pixmap, rControlRectangle );
-    delete pixmap;
+        GdkDrawable* const &pixDrawable = (i == 0) ? pixmap->GetGdkDrawable()
+                                                   : mask->GetGdkDrawable();
 
-    return bRet;
+        GtkWidget* pWidget = (nPart == PART_TRACK_HORZ_AREA)
+                             ? GTK_WIDGET(gWidgetData[m_nXScreen].gHScale)
+                             : GTK_WIDGET(gWidgetData[m_nXScreen].gVScale);
+        const gchar* pDetail = (nPart == PART_TRACK_HORZ_AREA) ? "hscale" : "vscale";
+        GtkOrientation eOri = (nPart == PART_TRACK_HORZ_AREA) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL;
+        gint slider_width = 10;
+        gint slider_length = 10;
+        gint trough_border = 0;
+        gtk_widget_style_get( pWidget,
+                              "slider-width", &slider_width,
+                              "slider-length", &slider_length,
+                              "trough-border", &trough_border,
+                              NULL);
+
+        GtkStateType eState = (nState & CTRL_STATE_ENABLED) ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE;
+        if( nPart == PART_TRACK_HORZ_AREA )
+        {
+            gtk_paint_box( pWidget->style,
+                           pixDrawable,
+                           eState,
+                           GTK_SHADOW_IN,
+                           NULL,
+                           pWidget,
+                           "trough",
+                           0, (h-slider_width-2*trough_border)/2, w, slider_width + 2*trough_border);
+            gint x = (w - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin);
+            gtk_paint_slider( pWidget->style,
+                              pixDrawable,
+                              eState,
+                              GTK_SHADOW_OUT,
+                              NULL,
+                              pWidget,
+                              pDetail,
+                              x, (h-slider_width)/2,
+                              slider_length, slider_width,
+                              eOri );
+        }
+        else
+        {
+            gtk_paint_box( pWidget->style,
+                           pixDrawable,
+                           eState,
+                           GTK_SHADOW_IN,
+                           NULL,
+                           pWidget,
+                           "trough",
+                           (w-slider_width-2*trough_border)/2, 0, slider_width + 2*trough_border, h);
+            gint y = (h - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin);
+            gtk_paint_slider( pWidget->style,
+                              pixDrawable,
+                              eState,

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list