[Libreoffice-commits] core.git: Branch 'feature/opengl-vcl' - 6 commits - vcl/inc vcl/Library_vclplug_gen.mk vcl/opengl vcl/source vcl/unx vcl/win

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Thu Nov 13 18:45:34 PST 2014


 vcl/Library_vclplug_gen.mk               |    1 
 vcl/inc/generic/genpspgraphics.h         |    1 
 vcl/inc/headless/svpgdi.hxx              |    1 
 vcl/inc/opengl/salbmp.hxx                |    7 
 vcl/inc/opengl/texture.hxx               |   67 +++++---
 vcl/inc/opengl/x11/gdiimpl.hxx           |    2 
 vcl/inc/openglgdiimpl.hxx                |   12 -
 vcl/inc/salgdi.hxx                       |    3 
 vcl/inc/unx/pixmap.hxx                   |   24 +--
 vcl/inc/unx/salgdi.h                     |    5 
 vcl/inc/unx/x11/x11gdiimpl.h             |    2 
 vcl/inc/win/salgdi.h                     |    1 
 vcl/opengl/gdiimpl.cxx                   |  125 +++++++++------
 vcl/opengl/salbmp.cxx                    |   71 +++------
 vcl/opengl/scale.cxx                     |   97 ++++++------
 vcl/opengl/texture.cxx                   |  243 ++++++++++++++++++++++++++-----
 vcl/opengl/x11/gdiimpl.cxx               |   32 +---
 vcl/source/outdev/gradient.cxx           |    7 
 vcl/unx/generic/gdi/gdiimpl.cxx          |   19 --
 vcl/unx/generic/gdi/gdiimpl.hxx          |    2 
 vcl/unx/generic/gdi/pixmap.cxx           |   54 ------
 vcl/unx/generic/gdi/salgdi.cxx           |    5 
 vcl/unx/generic/gdi/salgdi2.cxx          |    4 
 vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx |   59 +++----
 vcl/unx/kde/salnativewidgets-kde.cxx     |  140 +++++++++--------
 vcl/win/source/gdi/salgdi.cxx            |    5 
 vcl/win/source/gdi/winlayout.cxx         |    2 
 27 files changed, 568 insertions(+), 423 deletions(-)

New commits:
commit f2354f58782c5fddcc8bdb9451b9bbf3cef211da
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Thu Nov 13 21:38:58 2014 -0500

    vcl: Make sure the offscreen texture is unique before rendering to it
    
    Change-Id: I265ce62e983e6f44ba51675993c9ec1f071c160e

diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index bb6e113..0d91d48 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -76,6 +76,8 @@ protected:
 
     void ImplSetClipBit( const vcl::Region& rClip, GLuint nMask );
 
+    bool CheckOffscreenTexture();
+
     bool CreateSolidProgram( void );
     bool CreateTextureProgram( void );
     bool CreateMaskedTextureProgram( void );
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 3dc4f9a..d05b08b 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -97,7 +97,7 @@ void OpenGLSalGraphicsImpl::PreDraw()
     maContext.makeCurrent();
     // TODO: lfrb: make sure the render target has the right size
     if( mbOffscreen )
-        glBindFramebuffer( GL_FRAMEBUFFER, mnFramebufferId );
+        CheckOffscreenTexture();
     glViewport( 0, 0, GetWidth(), GetHeight() );
     if( mbUseScissor )
         glEnable( GL_SCISSOR_TEST );
@@ -282,6 +282,28 @@ void OpenGLSalGraphicsImpl::SetOffscreen( bool bOffscreen )
     CHECK_GL_ERROR();
 }
 
+bool OpenGLSalGraphicsImpl::CheckOffscreenTexture()
+{
+    glBindFramebuffer( GL_FRAMEBUFFER, mnFramebufferId );
+
+    if( maOffscreenTex.IsUnique() )
+        return true;
+
+    SalTwoRect aPosAry;
+    aPosAry.mnSrcX = aPosAry.mnDestX = 0;
+    aPosAry.mnSrcY = aPosAry.mnDestY = 0;
+    aPosAry.mnSrcWidth = aPosAry.mnDestWidth = GetWidth();
+    aPosAry.mnSrcHeight = aPosAry.mnDestHeight = GetHeight();
+
+    // TODO: lfrb: User GL_ARB_copy_image?
+    OpenGLTexture aNewTex = OpenGLTexture( GetWidth(), GetHeight() );
+    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, aNewTex.Id(), 0 );
+    glViewport( 0, 0, GetWidth(), GetHeight() );
+    DrawTexture( maOffscreenTex, aPosAry );
+
+    return true;
+}
+
 bool OpenGLSalGraphicsImpl::CreateSolidProgram( void )
 {
     SAL_INFO( "vcl.opengl", "::CreateSolidProgram" );
commit a031e11752521c996a50b4d9c271ef9fb0581edc
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Thu Nov 13 21:37:54 2014 -0500

    vcl: Improve OpenGLTexture implementation by allowing implicit sharing
    
    Change-Id: I6421265325e72023d1affe671d75488185772786

diff --git a/vcl/inc/opengl/salbmp.hxx b/vcl/inc/opengl/salbmp.hxx
index c1f0cdb..dbb29d8 100644
--- a/vcl/inc/opengl/salbmp.hxx
+++ b/vcl/inc/opengl/salbmp.hxx
@@ -40,7 +40,7 @@ class VCL_PLUGIN_PUBLIC OpenGLSalBitmap : public SalBitmap
 {
 private:
     OpenGLContext*                      mpContext;
-    OpenGLTextureSharedPtr              mpTexture;
+    OpenGLTexture                       maTexture;
     bool                                mbDirtyTexture;
     BitmapPalette                       maPalette;
     basebmp::RawMemorySharedArray       maUserBuffer;
@@ -81,9 +81,8 @@ public:
 
 public:
 
-    bool            Create( OpenGLContext& rContext, OpenGLTextureSharedPtr pTex, long nX, long nY, long nWidth, long nHeight );
-    bool            Draw( OpenGLContext& rContext, const SalTwoRect& rPosAry );
-    GLuint          GetTexture( OpenGLContext& rContext ) const;
+    bool            Create( OpenGLContext& rContext, const OpenGLTexture& rTex, long nX, long nY, long nWidth, long nHeight );
+    OpenGLTexture&  GetTexture( OpenGLContext& rContext ) const;
 
 private:
 
diff --git a/vcl/inc/opengl/texture.hxx b/vcl/inc/opengl/texture.hxx
index c0b6541..eb003cf 100644
--- a/vcl/inc/opengl/texture.hxx
+++ b/vcl/inc/opengl/texture.hxx
@@ -20,37 +20,62 @@
 #ifndef INCLUDED_VCL_INC_OPENGL_TEXTURE_H
 #define INCLUDED_VCL_INC_OPENGL_TEXTURE_H
 
-#include <boost/shared_ptr.hpp>
 #include <GL/glew.h>
+#include <vcl/dllapi.h>
 
-class OpenGLTexture
+class ImplOpenGLTexture
 {
-private:
+public:
+    int    mnRefCount;
     GLuint mnTexture;
     int    mnWidth;
     int    mnHeight;
     GLenum mnFilter;
 
-public:
-    OpenGLTexture();
-    OpenGLTexture( int nWidth, int nHeight );
-    OpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData );
-    OpenGLTexture( int nX, int nY, int nWidth, int nHeight );
-    virtual ~OpenGLTexture();
-
-    GLuint Id() const;
-    int GetWidth() const;
-    int GetHeight() const;
-
-    void Bind();
-    void Unbind();
-    bool Draw();
-
-    GLenum GetFilter() const;
-    void SetFilter( GLenum nFilter );
+    ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate );
+    ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData );
+    ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight );
+    ~ImplOpenGLTexture();
 };
 
-typedef boost::shared_ptr< OpenGLTexture > OpenGLTextureSharedPtr;
+class VCL_PLUGIN_PUBLIC OpenGLTexture
+{
+private:
+    // if the rect size doesn't match the mpImpl one, this instance
+    // is a sub-area from the real OpenGL texture
+    Rectangle          maRect;
+
+    ImplOpenGLTexture* mpImpl;
+
+public:
+                    OpenGLTexture();
+                    OpenGLTexture( int nWidth, int nHeight, bool bAllocate = true );
+                    OpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData );
+                    OpenGLTexture( int nX, int nY, int nWidth, int nHeight );
+                    OpenGLTexture( const OpenGLTexture& rTexture );
+                    OpenGLTexture( const OpenGLTexture& rTexture, int nX, int nY, int nWidth, int nHeight );
+    virtual         ~OpenGLTexture();
+
+    bool            IsUnique() const;
+
+    GLuint          Id() const;
+    int             GetWidth() const;
+    int             GetHeight() const;
+    void            GetCoord( GLfloat* pCoord, const SalTwoRect& rPosAry, bool bInverted=false ) const;
+
+    void            Bind();
+    void            Unbind();
+    bool            Draw();
+    void            Read( GLenum nFormat, GLenum nType, sal_uInt8* pData );
+
+    GLenum          GetFilter() const;
+    void            SetFilter( GLenum nFilter );
+
+                    operator bool() const;
+    OpenGLTexture&  operator=( const OpenGLTexture& rTexture );
+    bool            operator==( const OpenGLTexture& rTexture ) const;
+    bool            operator!=( const OpenGLTexture& rTexture ) const;
+};
 
 #endif // INCLUDED_VCL_INC_OPENGL_TEXTURE_H
 
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index 167fe60..bb6e113 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -46,7 +46,7 @@ protected:
 
     bool mbOffscreen;
     GLuint mnFramebufferId;
-    OpenGLTextureSharedPtr mpOffscreenTex;
+    OpenGLTexture maOffscreenTex;
 
     SalColor mnLineColor;
     SalColor mnFillColor;
@@ -99,10 +99,10 @@ protected:
     void DrawRect( const Rectangle& rRect );
     void DrawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry );
     void DrawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon );
-    void DrawTextureRect( const Size& rSize, const SalTwoRect& rPosAry, bool bInverted = false );
-    void DrawTexture( GLuint nTexture, const Size& rSize, const SalTwoRect& rPosAry, bool bInverted = false );
-    void DrawTextureWithMask( GLuint nTexture, GLuint nMask, const Size& rSize, const SalTwoRect& rPosAry );
-    void DrawMask( GLuint nMask, SalColor nMaskColor, const SalTwoRect& rPosAry );
+    void DrawTextureRect( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted = false );
+    void DrawTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted = false );
+    void DrawTextureWithMask( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry );
+    void DrawMask( OpenGLTexture& rTexture, SalColor nMaskColor, const SalTwoRect& rPosAry );
     void DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect );
     void DrawRadialGradient( const Gradient& rGradient, const Rectangle& rRect );
 
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 2f1d82f..3dc4f9a 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -66,7 +66,6 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl()
     , mbUseStencil(false)
     , mbOffscreen(false)
     , mnFramebufferId(0)
-    , mpOffscreenTex(NULL)
     , mnLineColor(SALCOLOR_NONE)
     , mnFillColor(SALCOLOR_NONE)
     , mnSolidProgram(0)
@@ -260,8 +259,8 @@ void OpenGLSalGraphicsImpl::SetOffscreen( bool bOffscreen )
             return;
 
         // Already enabled and same size
-        if( mpOffscreenTex->GetWidth()  == GetWidth() &&
-            mpOffscreenTex->GetHeight() == GetHeight() )
+        if( maOffscreenTex.GetWidth()  == GetWidth() &&
+            maOffscreenTex.GetHeight() == GetHeight() )
             return;
     }
     else
@@ -276,8 +275,8 @@ void OpenGLSalGraphicsImpl::SetOffscreen( bool bOffscreen )
     if( mbOffscreen )
     {
         glBindFramebuffer( GL_FRAMEBUFFER, mnFramebufferId );
-        mpOffscreenTex.reset( new OpenGLTexture( GetWidth(), GetHeight() ) );
-        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mpOffscreenTex->Id(), 0 );
+        maOffscreenTex = OpenGLTexture( GetWidth(), GetHeight() );
+        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, maOffscreenTex.Id(), 0 );
     }
 
     CHECK_GL_ERROR();
@@ -611,24 +610,11 @@ void OpenGLSalGraphicsImpl::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rPol
     CHECK_GL_ERROR();
 }
 
-void OpenGLSalGraphicsImpl::DrawTextureRect( const Size& rSize, const SalTwoRect& rPosAry, bool bInverted )
+void OpenGLSalGraphicsImpl::DrawTextureRect( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted )
 {
     GLfloat aTexCoord[8];
 
-    aTexCoord[0] = aTexCoord[2] = rPosAry.mnSrcX / (double) rSize.Width();
-    aTexCoord[4] = aTexCoord[6] = (rPosAry.mnSrcX + rPosAry.mnSrcWidth) / (double) rSize.Width();
-
-    if( !bInverted )
-    {
-        aTexCoord[3] = aTexCoord[5] = (rSize.Height() - rPosAry.mnSrcY) / (double) rSize.Height();
-        aTexCoord[1] = aTexCoord[7] = (rSize.Height() - rPosAry.mnSrcY - rPosAry.mnSrcHeight) / (double) rSize.Height();
-    }
-    else
-    {
-        aTexCoord[1] = aTexCoord[7] = (rSize.Height() - rPosAry.mnSrcY) / (double) rSize.Height();
-        aTexCoord[3] = aTexCoord[5] = (rSize.Height() - rPosAry.mnSrcY - rPosAry.mnSrcHeight) / (double) rSize.Height();
-    }
-
+    rTexture.GetCoord( aTexCoord, rPosAry, bInverted );
     glEnableVertexAttribArray( GL_ATTRIB_TEX );
     glVertexAttribPointer( GL_ATTRIB_TEX, 2, GL_FLOAT, GL_FALSE, 0, aTexCoord );
 
@@ -639,7 +625,7 @@ void OpenGLSalGraphicsImpl::DrawTextureRect( const Size& rSize, const SalTwoRect
     CHECK_GL_ERROR();
 }
 
-void OpenGLSalGraphicsImpl::DrawTexture( GLuint nTexture, const Size& rSize, const SalTwoRect& pPosAry, bool bInverted )
+void OpenGLSalGraphicsImpl::DrawTexture( OpenGLTexture& rTexture, const SalTwoRect& pPosAry, bool bInverted )
 {
     if( mnTextureProgram == 0 )
     {
@@ -651,18 +637,18 @@ void OpenGLSalGraphicsImpl::DrawTexture( GLuint nTexture, const Size& rSize, con
     glUniform1i( mnSamplerUniform, 0 );
     glActiveTexture( GL_TEXTURE0 );
     CHECK_GL_ERROR();
-    glBindTexture( GL_TEXTURE_2D, nTexture );
 
-    DrawTextureRect( rSize, pPosAry, bInverted );
+    rTexture.Bind();
+    DrawTextureRect( rTexture, pPosAry, bInverted );
+    rTexture.Unbind();
     CHECK_GL_ERROR();
 
-    glBindTexture( GL_TEXTURE_2D, 0 );
     glUseProgram( 0 );
 
     CHECK_GL_ERROR();
 }
 
-void OpenGLSalGraphicsImpl::DrawTextureWithMask( GLuint nTexture, GLuint nMask, const Size& rSize, const SalTwoRect& pPosAry )
+void OpenGLSalGraphicsImpl::DrawTextureWithMask( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& pPosAry )
 {
     if( mnMaskedTextureProgram == 0 )
     {
@@ -674,25 +660,25 @@ void OpenGLSalGraphicsImpl::DrawTextureWithMask( GLuint nTexture, GLuint nMask,
     glUniform1i( mnMaskedSamplerUniform, 0 );
     glUniform1i( mnMaskSamplerUniform, 1 );
     glActiveTexture( GL_TEXTURE0 );
-    glBindTexture( GL_TEXTURE_2D, nTexture );
+    rTexture.Bind();
     glActiveTexture( GL_TEXTURE1 );
-    glBindTexture( GL_TEXTURE_2D, nMask );
+    rMask.Bind();
 
     glEnable( GL_BLEND );
     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
-    DrawTextureRect( rSize, pPosAry );
+    DrawTextureRect( rTexture, pPosAry );
     glDisable( GL_BLEND );
 
     glActiveTexture( GL_TEXTURE1 );
-    glBindTexture( GL_TEXTURE_2D, 0 );
+    rMask.Unbind();
     glActiveTexture( GL_TEXTURE0 );
-    glBindTexture( GL_TEXTURE_2D, 0 );
+    rTexture.Unbind();
     glUseProgram( 0 );
 
     CHECK_GL_ERROR();
 }
 
-void OpenGLSalGraphicsImpl::DrawMask( GLuint nMask, SalColor nMaskColor, const SalTwoRect& /*pPosAry*/ )
+void OpenGLSalGraphicsImpl::DrawMask( OpenGLTexture& rMask, SalColor nMaskColor, const SalTwoRect& /*pPosAry*/ )
 {
     if( mnMaskProgram == 0 )
     {
@@ -704,12 +690,11 @@ void OpenGLSalGraphicsImpl::DrawMask( GLuint nMask, SalColor nMaskColor, const S
     glUniformColor( mnMaskColorUniform, nMaskColor, 0 );
     glUniform1i( mnMaskUniform, 0 );
     glActiveTexture( GL_TEXTURE0 );
-    glBindTexture( GL_TEXTURE_2D, nMask );
+    rMask.Bind();
 
-    //DrawTextureRect( pPosAry );
+    //DrawTextureRect( rMask, pPosAry );
 
-    glActiveTexture( GL_TEXTURE0 );
-    glBindTexture( GL_TEXTURE_2D, 0 );
+    rMask.Unbind();
     glUseProgram( 0 );
 
     CHECK_GL_ERROR();
@@ -1122,12 +1107,11 @@ void OpenGLSalGraphicsImpl::drawBitmap( const SalTwoRect& rPosAry, const SalBitm
     assert(dynamic_cast<const OpenGLSalBitmap*>(&rSalBitmap));
 
     const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
-    GLuint nTexture = rBitmap.GetTexture( maContext );
-    const Size aSize = rSalBitmap.GetSize();
+    OpenGLTexture& rTexture = rBitmap.GetTexture( maContext );
 
     SAL_INFO( "vcl.opengl", "::drawBitmap" );
     PreDraw();
-    DrawTexture( nTexture, aSize, rPosAry );
+    DrawTexture( rTexture, rPosAry );
     PostDraw();
 }
 
@@ -1146,12 +1130,12 @@ void OpenGLSalGraphicsImpl::drawBitmap(
 {
     const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
     const OpenGLSalBitmap& rMask = static_cast<const OpenGLSalBitmap&>(rMaskBitmap);
-    const GLuint nTexture( rBitmap.GetTexture( maContext ) );
-    const GLuint nMask( rMask.GetTexture( maContext ) );
+    OpenGLTexture& rTexture( rBitmap.GetTexture( maContext ) );
+    OpenGLTexture& rMaskTex( rMask.GetTexture( maContext ) );
 
     SAL_INFO( "vcl.opengl", "::drawBitmap with MASK" );
     PreDraw();
-    DrawTextureWithMask( nTexture, nMask, rBitmap.GetSize(), rPosAry );
+    DrawTextureWithMask( rTexture, rMaskTex, rPosAry );
     PostDraw();
 }
 
@@ -1161,11 +1145,11 @@ void OpenGLSalGraphicsImpl::drawMask(
             SalColor nMaskColor )
 {
     const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
-    const GLuint nTexture( rBitmap.GetTexture( maContext ) );
+    OpenGLTexture& rTexture( rBitmap.GetTexture( maContext ) );
 
     SAL_INFO( "vcl.opengl", "::drawMask" );
     PreDraw();
-    DrawMask( nTexture, nMaskColor, rPosAry );
+    DrawMask( rTexture, nMaskColor, rPosAry );
     PostDraw();
 }
 
@@ -1175,7 +1159,7 @@ SalBitmap* OpenGLSalGraphicsImpl::getBitmap( long nX, long nY, long nWidth, long
     SAL_INFO( "vcl.opengl", "::getBitmap " << nX << "," << nY <<
               " " << nWidth << "x" << nHeight );
     PreDraw();
-    if( !pBitmap->Create( maContext, mpOffscreenTex, nX, nY, nWidth, nHeight ) )
+    if( !pBitmap->Create( maContext, maOffscreenTex, nX, nY, nWidth, nHeight ) )
     {
         delete pBitmap;
         pBitmap = NULL;
@@ -1276,12 +1260,12 @@ bool OpenGLSalGraphicsImpl::drawAlphaBitmap(
 {
     const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
     const OpenGLSalBitmap& rAlpha = static_cast<const OpenGLSalBitmap&>(rAlphaBitmap);
-    const GLuint nTexture( rBitmap.GetTexture( maContext ) );
-    const GLuint nAlpha( rAlpha.GetTexture( maContext ) );
+    OpenGLTexture& rTexture( rBitmap.GetTexture( maContext ) );
+    OpenGLTexture& rAlphaTex( rAlpha.GetTexture( maContext ) );
 
     SAL_INFO( "vcl.opengl", "::drawAlphaBitmap" );
     PreDraw();
-    DrawTextureWithMask( nTexture, nAlpha, rBitmap.GetSize(), rPosAry );
+    DrawTextureWithMask( rTexture, rAlphaTex, rPosAry );
     PostDraw();
     return true;
 }
@@ -1291,13 +1275,13 @@ bool OpenGLSalGraphicsImpl::drawAlphaBitmap(
             const SalBitmap& rSalBitmap )
 {
     const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
-    const GLuint nTexture( rBitmap.GetTexture( maContext ) );
+    OpenGLTexture& rTexture( rBitmap.GetTexture( maContext ) );
 
     SAL_INFO( "vcl.opengl", "::drawAlphaBitmap" );
     PreDraw();
     glEnable( GL_BLEND );
     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
-    DrawTexture( nTexture, rBitmap.GetSize(), rPosAry );
+    DrawTexture( rTexture, rPosAry );
     glDisable( GL_BLEND );
     PostDraw();
 
diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx
index 1401fb8..ab27ade 100644
--- a/vcl/opengl/salbmp.cxx
+++ b/vcl/opengl/salbmp.cxx
@@ -37,7 +37,6 @@ static bool isValidBitCount( sal_uInt16 nBitCount )
 
 OpenGLSalBitmap::OpenGLSalBitmap()
 : mpContext(NULL)
-, mpTexture()
 , mbDirtyTexture(true)
 , mnBits(0)
 , mnBytesPerRow(0)
@@ -56,7 +55,7 @@ OpenGLSalBitmap::~OpenGLSalBitmap()
     SAL_INFO( "vcl.opengl", "~OpenGLSalBitmap" );
 }
 
-bool OpenGLSalBitmap::Create( OpenGLContext& rContext, OpenGLTextureSharedPtr pTex, long nX, long nY, long nWidth, long nHeight )
+bool OpenGLSalBitmap::Create( OpenGLContext& rContext, const OpenGLTexture& rTex, long nX, long nY, long nWidth, long nHeight )
 {
     static const BitmapPalette aEmptyPalette;
 
@@ -73,13 +72,12 @@ bool OpenGLSalBitmap::Create( OpenGLContext& rContext, OpenGLTextureSharedPtr pT
     mnBits = 32;
     maPalette = aEmptyPalette;
 
-    // TODO: lfrb: Crop texture if size doesn't match the texture one
-    if( pTex )
-        mpTexture = pTex;
+    if( rTex )
+        maTexture = OpenGLTexture( rTex, nX, nY, nWidth, nHeight );
     else
-        mpTexture.reset( new OpenGLTexture( nX, nY, nWidth, nHeight ) );
+        maTexture = OpenGLTexture( nX, nY, nWidth, nHeight );
     mbDirtyTexture = false;
-    SAL_INFO( "vcl.opengl", "Created texture " << mpTexture->Id() );
+    SAL_INFO( "vcl.opengl", "Created texture " << maTexture.Id() );
 
     return true;
 }
@@ -128,7 +126,7 @@ bool OpenGLSalBitmap::Create( const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount
         mnBufHeight = rSourceBitmap.mnBufHeight;
         maPalette = rSourceBitmap.maPalette;
         mpContext = rSourceBitmap.mpContext;
-        mpTexture = rSourceBitmap.mpTexture;
+        maTexture = rSourceBitmap.maTexture;
         mbDirtyTexture = false;
         maUserBuffer = rSourceBitmap.maUserBuffer;
 
@@ -144,36 +142,22 @@ bool OpenGLSalBitmap::Create( const ::com::sun::star::uno::Reference< ::com::sun
     return false;
 }
 
-bool OpenGLSalBitmap::Draw( OpenGLContext& rContext, const SalTwoRect& /*rPosAry*/ )
+OpenGLTexture& OpenGLSalBitmap::GetTexture( OpenGLContext& rContext ) const
 {
+    OpenGLSalBitmap* pThis = const_cast<OpenGLSalBitmap*>(this);
     if( !mpContext )
-        mpContext = &rContext;
-
-    if( !mpTexture || mbDirtyTexture )
-    {
-        if( !CreateTexture() )
-            return false;
-    }
-
-    //DrawTexture( mnTexture, rPosAry );
-    return true;
-}
-
-GLuint OpenGLSalBitmap::GetTexture( OpenGLContext& rContext ) const
-{
-    if( !mpContext )
-        const_cast<OpenGLSalBitmap*>(this)->mpContext = &rContext;
-    if( !mpTexture || mbDirtyTexture )
-        const_cast<OpenGLSalBitmap*>(this)->CreateTexture();
-    SAL_INFO( "vcl.opengl", "Got texture " << mpTexture->Id() );
-    return mpTexture->Id();
+        pThis->mpContext = &rContext;
+    if( !maTexture || mbDirtyTexture )
+        pThis->CreateTexture();
+    SAL_INFO( "vcl.opengl", "Got texture " << maTexture.Id() );
+    return pThis->maTexture;
 }
 
 void OpenGLSalBitmap::Destroy()
 {
     SAL_INFO( "vcl.opengl", "Destroy OpenGLSalBitmap" );
     maPendingOps.clear();
-    mpTexture.reset();
+    maTexture = OpenGLTexture();
     maUserBuffer.reset();
 }
 
@@ -402,8 +386,8 @@ GLuint OpenGLSalBitmap::CreateTexture()
     }
 
     mpContext->makeCurrent();
-    mpTexture.reset( new OpenGLTexture (mnBufWidth, mnBufHeight, nFormat, nType, pData ) );
-    SAL_INFO( "vcl.opengl", "Created texture " << mpTexture->Id() );
+    maTexture = OpenGLTexture (mnBufWidth, mnBufHeight, nFormat, nType, pData );
+    SAL_INFO( "vcl.opengl", "Created texture " << maTexture.Id() );
 
     if( bAllocated )
         delete[] pData;
@@ -418,12 +402,11 @@ GLuint OpenGLSalBitmap::CreateTexture()
     mbDirtyTexture = false;
 
     CHECK_GL_ERROR();
-    return mpTexture->Id();
+    return maTexture.Id();
 }
 
 bool OpenGLSalBitmap::ReadTexture()
 {
-    GLuint nFramebufferId;
     sal_uInt8* pData = maUserBuffer.get();
     GLenum nFormat, nType;
 
@@ -450,18 +433,16 @@ bool OpenGLSalBitmap::ReadTexture()
                     break;
         }
     }
+    else
+    {
+        return false;
+    }
 
     mpContext->makeCurrent();
-    glGenFramebuffers( 1, &nFramebufferId );
-    glBindFramebuffer( GL_FRAMEBUFFER, nFramebufferId );
-
-    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mpTexture->Id(), 0 );
-    glReadPixels( 0, 0, mnWidth, mnHeight, nFormat, nType, pData );
+    maTexture.Read( nFormat, nType, pData );
+    mnBufWidth = mnWidth;
+    mnBufHeight = mnHeight;
 
-    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-    glDeleteFramebuffers( 1, &nFramebufferId );
-
-    CHECK_GL_ERROR();
     return true;
 }
 
@@ -476,7 +457,7 @@ BitmapBuffer* OpenGLSalBitmap::AcquireBuffer( bool /*bReadOnly*/ )
     {
         if( !AllocateUserData() )
             return NULL;
-        if( mpTexture && !ReadTexture() )
+        if( maTexture && !ReadTexture() )
             return NULL;
     }
 
@@ -524,6 +505,7 @@ void OpenGLSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly )
 {
     if( !bReadOnly )
     {
+        maTexture = OpenGLTexture();
         mbDirtyTexture = true;
     }
     delete pBuffer;
@@ -531,6 +513,7 @@ void OpenGLSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly )
 
 bool OpenGLSalBitmap::GetSystemData( BitmapSystemData& /*rData*/ )
 {
+    SAL_WARN( "vcl.opengl", "*** NOT IMPLEMENTED *** GetSystemData" );
 #if 0
     // TODO Implement for ANDROID/OSX/IOS/WIN32
     X11SalBitmap rBitmap;
diff --git a/vcl/opengl/scale.cxx b/vcl/opengl/scale.cxx
index d1b85a5..92fdd3f 100644
--- a/vcl/opengl/scale.cxx
+++ b/vcl/opengl/scale.cxx
@@ -86,7 +86,6 @@ bool OpenGLSalBitmap::ImplScaleFilter(
     const double& rScaleY,
     GLenum        nFilter )
 {
-    OpenGLTexture* pNewTex;
     GLuint nProgram;
     GLuint nFramebufferId;
     GLenum nOldFilter;
@@ -102,15 +101,15 @@ bool OpenGLSalBitmap::ImplScaleFilter(
     glUseProgram( nProgram );
     glUniform1i( mnTexSamplerUniform, 0 );
 
-    pNewTex = new OpenGLTexture( nNewWidth, nNewHeight );
-    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pNewTex->Id(), 0 );
+    OpenGLTexture aNewTex = OpenGLTexture( nNewWidth, nNewHeight );
+    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, aNewTex.Id(), 0 );
 
-    mpTexture->Bind();
-    nOldFilter = mpTexture->GetFilter();
-    mpTexture->SetFilter( nFilter );
-    mpTexture->Draw();
-    mpTexture->SetFilter( nOldFilter );
-    mpTexture->Unbind();
+    maTexture.Bind();
+    nOldFilter = maTexture.GetFilter();
+    maTexture.SetFilter( nFilter );
+    maTexture.Draw();
+    maTexture.SetFilter( nOldFilter );
+    maTexture.Unbind();
 
     glUseProgram( 0 );
     glBindFramebuffer( GL_FRAMEBUFFER, 0 );
@@ -118,7 +117,7 @@ bool OpenGLSalBitmap::ImplScaleFilter(
 
     mnWidth = nNewWidth;
     mnHeight = nNewHeight;
-    mpTexture.reset( pNewTex );
+    maTexture = aNewTex;
 
     CHECK_GL_ERROR();
     return true;
@@ -167,8 +166,6 @@ bool OpenGLSalBitmap::ImplScaleConvolution(
     const double& rScaleY,
     const Kernel& aKernel )
 {
-    OpenGLTexture* pScratchTex;
-    OpenGLTexture* pNewTex;
     GLfloat* pWeights( 0 );
     GLuint nFramebufferId;
     GLuint nProgram;
@@ -190,51 +187,59 @@ bool OpenGLSalBitmap::ImplScaleConvolution(
     CHECK_GL_ERROR();
 
     // horizontal scaling in scratch texture
-    pScratchTex = new OpenGLTexture( nNewWidth, mnHeight );
-    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pScratchTex->Id(), 0 );
-    CHECK_GL_ERROR();
-
-    for( sal_uInt32 i = 0; i < 16; i++ )
+    if( mnWidth != nNewWidth )
     {
-        aOffsets[i * 2] = i / (double) mnWidth;
-        aOffsets[i * 2 + 1] = 0;
-    }
-    ImplCreateKernel( rScaleX, aKernel, pWeights, nKernelSize );
-    glUniform1fv( mnConvKernelUniform, 16, pWeights );
-    CHECK_GL_ERROR();
-    glUniform2fv( mnConvOffsetsUniform, 16, aOffsets );
-    CHECK_GL_ERROR();
+        OpenGLTexture aScratchTex = OpenGLTexture( nNewWidth, mnHeight );
+        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, aScratchTex.Id(), 0 );
+        CHECK_GL_ERROR();
 
-    glViewport( 0, 0, nNewWidth, mnHeight );
-    mpTexture->Bind();
-    mpTexture->Draw();
-    mpTexture->Unbind();
+        for( sal_uInt32 i = 0; i < 16; i++ )
+        {
+            aOffsets[i * 2] = i / (double) mnWidth;
+            aOffsets[i * 2 + 1] = 0;
+        }
+        ImplCreateKernel( rScaleX, aKernel, pWeights, nKernelSize );
+        glUniform1fv( mnConvKernelUniform, 16, pWeights );
+        CHECK_GL_ERROR();
+        glUniform2fv( mnConvOffsetsUniform, 16, aOffsets );
+        CHECK_GL_ERROR();
+
+        glViewport( 0, 0, nNewWidth, mnHeight );
+        maTexture.Bind();
+        maTexture.Draw();
+        maTexture.Unbind();
+
+        maTexture = aScratchTex;
+    }
 
     // vertical scaling in final texture
-    pNewTex = new OpenGLTexture( nNewWidth, nNewHeight );
-    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pNewTex->Id(), 0 );
-
-    for( sal_uInt32 i = 0; i < 16; i++ )
+    if( mnHeight != nNewHeight )
     {
-        aOffsets[i * 2] = 0;
-        aOffsets[i * 2 + 1] = i / (double) mnHeight;
-    }
-    ImplCreateKernel( rScaleY, aKernel, pWeights, nKernelSize );
-    glUniform1fv( mnConvKernelUniform, 16, pWeights );
-    glUniform2fv( mnConvOffsetsUniform, 16, aOffsets );
-    CHECK_GL_ERROR();
+        OpenGLTexture aScratchTex = OpenGLTexture( nNewWidth, nNewHeight );
+        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, aScratchTex.Id(), 0 );
+
+        for( sal_uInt32 i = 0; i < 16; i++ )
+        {
+            aOffsets[i * 2] = 0;
+            aOffsets[i * 2 + 1] = i / (double) mnHeight;
+        }
+        ImplCreateKernel( rScaleY, aKernel, pWeights, nKernelSize );
+        glUniform1fv( mnConvKernelUniform, 16, pWeights );
+        glUniform2fv( mnConvOffsetsUniform, 16, aOffsets );
+        CHECK_GL_ERROR();
 
-    glViewport( 0, 0, nNewWidth, nNewHeight );
-    pScratchTex->Bind();
-    pScratchTex->Draw();
-    pScratchTex->Unbind();
+        glViewport( 0, 0, nNewWidth, nNewHeight );
+        maTexture.Bind();
+        maTexture.Draw();
+        maTexture.Unbind();
+
+        maTexture = aScratchTex;
+    }
 
     glUseProgram( 0 );
     glBindFramebuffer( GL_FRAMEBUFFER, 0 );
     glDeleteFramebuffers( 1, &nFramebufferId );
 
-    delete pScratchTex;
-    mpTexture.reset( pNewTex );
     mnWidth = nNewWidth;
     mnHeight = nNewHeight;
 
diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx
index 0c8dc1d..005fb66 100644
--- a/vcl/opengl/texture.cxx
+++ b/vcl/opengl/texture.cxx
@@ -24,19 +24,12 @@
 
 #include "opengl/texture.hxx"
 
-OpenGLTexture::OpenGLTexture()
-: mnTexture( 0 )
-, mnWidth( -1 )
-, mnHeight( -1 )
-, mnFilter( GL_NEAREST )
-{
-}
-
-OpenGLTexture::OpenGLTexture( int nWidth, int nHeight )
-: mnTexture( 0 )
-, mnWidth( nWidth )
-, mnHeight( nHeight )
-, mnFilter( GL_NEAREST )
+// texture with allocated size
+ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate ) :
+    mnRefCount( 1 ),
+    mnWidth( nWidth ),
+    mnHeight( nHeight ),
+    mnFilter( GL_NEAREST )
 {
     glGenTextures( 1, &mnTexture );
     glBindTexture( GL_TEXTURE_2D, mnTexture );
@@ -44,15 +37,18 @@ OpenGLTexture::OpenGLTexture( int nWidth, int nHeight )
     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
-    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
+    if( bAllocate )
+        glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
     glBindTexture( GL_TEXTURE_2D, 0 );
 }
 
-OpenGLTexture::OpenGLTexture( int nX, int nY, int nWidth, int nHeight )
-: mnTexture( 0 )
-, mnWidth( nWidth )
-, mnHeight( nHeight )
-, mnFilter( GL_NEAREST )
+// texture with content retrieved from FBO
+ImplOpenGLTexture::ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight ) :
+    mnRefCount( 1 ),
+    mnTexture( 0 ),
+    mnWidth( nWidth ),
+    mnHeight( nHeight ),
+    mnFilter( GL_NEAREST )
 {
     glGenTextures( 1, &mnTexture );
     glBindTexture( GL_TEXTURE_2D, mnTexture );
@@ -66,11 +62,13 @@ OpenGLTexture::OpenGLTexture( int nX, int nY, int nWidth, int nHeight )
     CHECK_GL_ERROR();
 }
 
-OpenGLTexture::OpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData )
-: mnTexture( 0 )
-, mnWidth( nWidth )
-, mnHeight( nHeight )
-, mnFilter( GL_NEAREST )
+// texture from buffer data
+ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData ) :
+    mnRefCount( 1 ),
+    mnTexture( 0 ),
+    mnWidth( nWidth ),
+    mnHeight( nHeight ),
+    mnFilter( GL_NEAREST )
 {
     if( !mnTexture )
         glGenTextures( 1, &mnTexture );
@@ -84,37 +82,119 @@ OpenGLTexture::OpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, s
     glBindTexture( GL_TEXTURE_2D, 0 );
 }
 
-OpenGLTexture::~OpenGLTexture()
+ImplOpenGLTexture::~ImplOpenGLTexture()
 {
+    SAL_INFO( "vcl.opengl", "~OpenGLTexture " << mnTexture );
     if( mnTexture != 0 )
         glDeleteTextures( 1, &mnTexture );
 }
 
+OpenGLTexture::OpenGLTexture() :
+    maRect( 0, 0, 0, 0 ),
+    mpImpl( NULL )
+{
+}
+
+OpenGLTexture::OpenGLTexture( int nWidth, int nHeight, bool bAllocate ) :
+    maRect( Point( 0, 0 ), Size( nWidth, nHeight ) )
+{
+    mpImpl = new ImplOpenGLTexture( nWidth, nHeight, bAllocate );
+}
+
+OpenGLTexture::OpenGLTexture( int nX, int nY, int nWidth, int nHeight ) :
+    maRect( Point( 0, 0 ), Size( nWidth, nHeight ) )
+{
+    mpImpl = new ImplOpenGLTexture( nX, nY, nWidth, nHeight );
+}
+
+OpenGLTexture::OpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData ) :
+    maRect( Point( 0, 0 ), Size( nWidth, nHeight ) )
+{
+    mpImpl = new ImplOpenGLTexture( nWidth, nHeight, nFormat, nType, pData );
+}
+
+OpenGLTexture::OpenGLTexture( const OpenGLTexture& rTexture )
+{
+    maRect = rTexture.maRect;
+    mpImpl = rTexture.mpImpl;
+    if( mpImpl )
+        mpImpl->mnRefCount++;
+}
+
+OpenGLTexture::OpenGLTexture( const OpenGLTexture& rTexture,
+                              int nX, int nY, int nWidth, int nHeight )
+{
+    maRect = Rectangle( Point( rTexture.maRect.Left() + nX, rTexture.maRect.Top() + nY ),
+                        Size( nWidth, nHeight ) );
+    mpImpl = rTexture.mpImpl;
+    if( mpImpl )
+        mpImpl->mnRefCount++;
+    SAL_INFO( "vcl.opengl", "Copying texture " << Id() << " [" << maRect.Left() << "," << maRect.Top() << "] " << GetWidth() << "x" << GetHeight() );
+}
+
+OpenGLTexture::~OpenGLTexture()
+{
+    if( mpImpl )
+    {
+        if( mpImpl->mnRefCount == 1 )
+            delete mpImpl;
+        else
+            mpImpl->mnRefCount--;
+    }
+}
+
+bool OpenGLTexture::IsUnique() const
+{
+    return ( mpImpl == NULL || mpImpl->mnRefCount == 1 );
+}
+
 GLuint OpenGLTexture::Id() const
 {
-    return mnTexture;
+    if( mpImpl )
+        return mpImpl->mnTexture;
+    return 0;
 }
 
 int OpenGLTexture::GetWidth() const
 {
-    return mnWidth;
+    return maRect.GetWidth();
 }
 
 int OpenGLTexture::GetHeight() const
 {
-    return mnHeight;
+    return maRect.GetHeight();
+}
+
+void OpenGLTexture::GetCoord( GLfloat* pCoord, const SalTwoRect& rPosAry, bool bInverted ) const
+{
+    SAL_INFO( "vcl.opengl", "Getting coord " << Id() << " [" << maRect.Left() << "," << maRect.Top() << "] " << GetWidth() << "x" << GetHeight() );
+    pCoord[0] = pCoord[2] = (maRect.Left() + rPosAry.mnSrcX) / (double) mpImpl->mnWidth;
+    pCoord[4] = pCoord[6] = (maRect.Left() + rPosAry.mnSrcX + rPosAry.mnSrcWidth) / (double) mpImpl->mnWidth;
+
+    if( !bInverted )
+    {
+        pCoord[3] = pCoord[5] = 1.0f - (maRect.Top() + rPosAry.mnSrcY) / (double) mpImpl->mnHeight;
+        pCoord[1] = pCoord[7] = 1.0f - (maRect.Top() + rPosAry.mnSrcY + rPosAry.mnSrcHeight) / (double) mpImpl->mnHeight;
+    }
+    else
+    {
+        pCoord[1] = pCoord[7] = 1.0f - (maRect.Top() + rPosAry.mnSrcY) / (double) mpImpl->mnHeight;
+        pCoord[3] = pCoord[5] = 1.0f - (maRect.Top() + rPosAry.mnSrcY + rPosAry.mnSrcHeight) / (double) mpImpl->mnHeight;
+    }
 }
 
 GLenum OpenGLTexture::GetFilter() const
 {
-    return mnFilter;
+    if( mpImpl )
+        return mpImpl->mnFilter;
+    return GL_NEAREST;
 }
 
 void OpenGLTexture::SetFilter( GLenum nFilter )
 {
-    mnFilter = nFilter;
-    if( mnTexture )
+    if( mpImpl )
     {
+        mpImpl->mnFilter = nFilter;
         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, nFilter );
         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, nFilter );
     }
@@ -122,23 +202,38 @@ void OpenGLTexture::SetFilter( GLenum nFilter )
 
 void OpenGLTexture::Bind()
 {
-    glBindTexture( GL_TEXTURE_2D, mnTexture );
+    if( mpImpl )
+        glBindTexture( GL_TEXTURE_2D, mpImpl->mnTexture );
 }
 
 void OpenGLTexture::Unbind()
 {
-    glBindTexture( GL_TEXTURE_2D, 0 );
+    if( mpImpl )
+        glBindTexture( GL_TEXTURE_2D, 0 );
 }
 
 bool OpenGLTexture::Draw()
 {
-    const GLfloat aPosition[8] = { -1, -1, -1, 1, 1, 1, 1, -1 };
-    const GLfloat aTexCoord[8] = {  0,  0,  0, 1, 1, 1, 1,  0 };
+    GLfloat aPosition[8] = { -1, -1, -1, 1, 1, 1, 1, -1 };
+    GLfloat aTexCoord[8] = {  0,  0,  0, 1, 1, 1, 1,  0 };
 
-    if( mnTexture == 0 )
+    if( mpImpl == NULL )
+    {
+        SAL_WARN( "vcl.opengl", "Can't draw invalid texture" );
         return false;
+    }
 
-    glBindTexture( GL_TEXTURE_2D, mnTexture );
+    SAL_INFO( "vcl.opengl", "Drawing texture " << Id() << " [" << maRect.Left() << "," << maRect.Top() << "] " << GetWidth() << "x" << GetHeight() );
+    if( GetWidth() != mpImpl->mnWidth || GetHeight() != mpImpl->mnHeight )
+    {
+        // FIXME: lfrb: check math
+        aTexCoord[0] = aTexCoord[2] = maRect.Left() / (double) mpImpl->mnWidth;
+        aTexCoord[4] = aTexCoord[6] = maRect.Right() / (double) mpImpl->mnWidth;
+        aTexCoord[1] = aTexCoord[7] = maRect.Top() / (double) mpImpl->mnHeight;
+        aTexCoord[3] = aTexCoord[5] = maRect.Bottom() / (double) mpImpl->mnHeight;
+    }
+
+    glBindTexture( GL_TEXTURE_2D, mpImpl->mnTexture );
     glEnableVertexAttribArray( 0 );
     glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 0, aPosition );
     glEnableVertexAttribArray( 1 );
@@ -151,4 +246,78 @@ bool OpenGLTexture::Draw()
     return true;
 }
 
+void OpenGLTexture::Read( GLenum nFormat, GLenum nType, sal_uInt8* pData )
+{
+    if( mpImpl == NULL )
+    {
+        SAL_WARN( "vcl.opengl", "Can't read invalid texture" );
+        return;
+    }
+
+    Bind();
+    glPixelStorei( GL_PACK_ALIGNMENT, 1 );
+
+    SAL_INFO( "vcl.opengl", "Reading texture " << Id() << " " << GetWidth() << "x" << GetHeight() );
+
+    if( GetWidth() == mpImpl->mnWidth && GetHeight() == mpImpl->mnHeight )
+    {
+        // XXX: Call not available with GLES 2.0
+        glGetTexImage( GL_TEXTURE_2D, 0, nFormat, nType, pData );
+    }
+    else
+    {
+        GLuint nFramebufferId;
+        glGenFramebuffers( 1, &nFramebufferId );
+        glBindFramebuffer( GL_FRAMEBUFFER, nFramebufferId );
+    CHECK_GL_ERROR();
+
+        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Id(), 0 );
+    CHECK_GL_ERROR();
+        glReadPixels( maRect.Left(), mpImpl->mnHeight - maRect.Top(), GetWidth(), GetHeight(), nFormat, nType, pData );
+    CHECK_GL_ERROR();
+
+        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+        glDeleteFramebuffers( 1, &nFramebufferId );
+
+        int bpp = (nFormat == GL_RGB) ? 3 : 4;
+        memset( pData, 255, GetWidth() * GetHeight() * bpp );
+    }
+
+    Unbind();
+    CHECK_GL_ERROR();
+}
+
+OpenGLTexture::operator bool() const
+{
+    return ( mpImpl != NULL );
+}
+
+OpenGLTexture&  OpenGLTexture::operator=( const OpenGLTexture& rTexture )
+{
+    if( rTexture.mpImpl )
+        rTexture.mpImpl->mnRefCount++;
+    if( mpImpl )
+    {
+        if( mpImpl->mnRefCount == 1 )
+            delete mpImpl;
+        else
+            mpImpl->mnRefCount--;
+    }
+
+    maRect = rTexture.maRect;
+    mpImpl = rTexture.mpImpl;
+
+    return *this;
+}
+
+bool OpenGLTexture::operator==( const OpenGLTexture& rTexture ) const
+{
+    return (mpImpl == rTexture.mpImpl && maRect == rTexture.maRect );
+}
+
+bool OpenGLTexture::operator!=( const OpenGLTexture& rTexture ) const
+{
+    return !( *this == rTexture );
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx
index fe775f5..3a2cfdf 100644
--- a/vcl/opengl/x11/gdiimpl.cxx
+++ b/vcl/opengl/x11/gdiimpl.cxx
@@ -15,6 +15,7 @@
 #include "unx/salgdi.h"
 #include "unx/salvd.h"
 
+#include "opengl/texture.hxx"
 #include "opengl/x11/gdiimpl.hxx"
 
 #include <vcl/opengl/OpenGLContext.hxx>
@@ -124,7 +125,6 @@ bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX,
     Display* pDisplay = mrParent.GetXDisplay();
     GLXFBConfig pFbConfig;
     GLXPixmap pGlxPixmap;
-    GLuint nTexture;
     SalTwoRect aPosAry;
     bool bInverted;
 
@@ -144,21 +144,18 @@ bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX,
 
     PreDraw();
 
-    glGenTextures( 1, &nTexture );
+    OpenGLTexture aTexture( pPixmap->GetWidth(), pPixmap->GetHeight(), false );
     glActiveTexture( GL_TEXTURE0 );
-    glBindTexture( GL_TEXTURE_2D, nTexture );
+    aTexture.Bind();
 
     //TODO: lfrb: glXGetProc to get the functions
     glXBindTexImageEXT( pDisplay, pGlxPixmap, GLX_FRONT_LEFT_EXT, NULL );
 
-    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
-    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
-
-    DrawTexture( nTexture, pPixmap->GetSize(), aPosAry, !bInverted );
+    DrawTexture( aTexture, aPosAry, !bInverted );
 
     glXReleaseTexImageEXT( pDisplay, pGlxPixmap, GLX_FRONT_LEFT_EXT );
-    glDeleteTextures( 1, &nTexture );
     glXDestroyPixmap( pDisplay, pGlxPixmap );
+    aTexture.Unbind();
 
     PostDraw();
 
diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 52fdfb6..3b5204f 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -204,7 +204,7 @@ void WinLayout::DrawText(SalGraphics& rGraphics) const
 
             // FIXME We don't have a method that could paint a texture with
             // transparency yet, use it when we have it
-            pImpl->DrawTexture(aTexture.Id(), Size(width, height), aRects);
+            pImpl->DrawTexture(aTexture, aRects);
         }
 
         DeleteObject(hBitmap);
commit 004a01db85e89cbaf5b254164dbbafe8253cf7fb
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Thu Nov 13 21:31:42 2014 -0500

    vcl: Draw gradient in alpha device even when using native rendering
    
    Change-Id: Iead4ac3e97197f8f863242a2162907b32c3c5b2b

diff --git a/vcl/source/outdev/gradient.cxx b/vcl/source/outdev/gradient.cxx
index c018fea..e6cb969 100644
--- a/vcl/source/outdev/gradient.cxx
+++ b/vcl/source/outdev/gradient.cxx
@@ -41,6 +41,8 @@ void OutputDevice::DrawGradient( const Rectangle& rRect,
 void OutputDevice::DrawGradient( const tools::PolyPolygon& rPolyPoly,
                                  const Gradient& rGradient )
 {
+    bool bDrawn = false;
+
     if ( mnDrawMode & DRAWMODE_NOGRADIENT )
         return;     // nothing to draw!
 
@@ -52,11 +54,10 @@ void OutputDevice::DrawGradient( const tools::PolyPolygon& rPolyPoly,
 
     if ( mpGraphics || AcquireGraphics() )
     {
-        if ( mpGraphics->DrawGradient( rPolyPoly, rGradient, this ) )
-            return;
+        bDrawn = mpGraphics->DrawGradient( rPolyPoly, rGradient, this );
     }
 
-    if ( rPolyPoly.Count() && rPolyPoly[ 0 ].GetSize() )
+    if ( !bDrawn && rPolyPoly.Count() && rPolyPoly[ 0 ].GetSize() )
     {
         if ( mnDrawMode & ( DRAWMODE_BLACKGRADIENT | DRAWMODE_WHITEGRADIENT | DRAWMODE_SETTINGSGRADIENT) )
         {
commit 2b6894c83104c82a0603f6c92b9fd7493e5d0766
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Thu Nov 13 21:30:05 2014 -0500

    vcl: Implement copyBits in the OpenGL backend
    
    Change-Id: I101afd11394d3d024d38519afd61d700114702ac

diff --git a/vcl/inc/generic/genpspgraphics.h b/vcl/inc/generic/genpspgraphics.h
index 882e475..382a693 100644
--- a/vcl/inc/generic/genpspgraphics.h
+++ b/vcl/inc/generic/genpspgraphics.h
@@ -71,6 +71,7 @@ public:
                                            const psp::FastPrintFontInfo& );
 
     // overload all pure virtual methods
+    virtual SalGraphicsImpl*GetImpl() const SAL_OVERRIDE { return NULL; };
     virtual void            GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY ) SAL_OVERRIDE;
     virtual sal_uInt16      GetBitCount() const SAL_OVERRIDE;
     virtual long            GetGraphicsWidth() const SAL_OVERRIDE;
diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx
index 9f2604f..4da3ffa 100644
--- a/vcl/inc/headless/svpgdi.hxx
+++ b/vcl/inc/headless/svpgdi.hxx
@@ -137,6 +137,7 @@ public:
     SvpSalGraphics();
     virtual ~SvpSalGraphics();
 
+    virtual SalGraphicsImpl* GetImpl() const SAL_OVERRIDE { return NULL; };
     virtual void            GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY ) SAL_OVERRIDE;
     virtual sal_uInt16      GetBitCount() const SAL_OVERRIDE;
     virtual long            GetGraphicsWidth() const SAL_OVERRIDE;
diff --git a/vcl/inc/salgdi.hxx b/vcl/inc/salgdi.hxx
index 2453450..4a567f5 100644
--- a/vcl/inc/salgdi.hxx
+++ b/vcl/inc/salgdi.hxx
@@ -29,6 +29,7 @@
 #include <vcl/salnativewidgets.hxx>
 #include <vcl/metric.hxx>
 
+#include "salgdiimpl.hxx"
 #include "salglyphid.hxx"
 #include "sallayout.hxx"
 
@@ -82,6 +83,8 @@ public:
                                 SalGraphics();
     virtual                     ~SalGraphics();
 
+    virtual SalGraphicsImpl*    GetImpl() const = 0;
+
     void                        setAntiAliasB2DDraw(bool bNew) { m_bAntiAliasB2DDraw = bNew; }
     bool                        getAntiAliasB2DDraw() const { return m_bAntiAliasB2DDraw; }
 
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index bc41041..31bc172 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -128,6 +128,7 @@ public:
             void            Init( class ImplSalPrinterData *pPrinter );
             void            DeInit();
 
+    SalGraphicsImpl*            GetImpl() const SAL_OVERRIDE;
     inline  const SalDisplay*   GetDisplay() const;
     inline  Display*            GetXDisplay() const;
     inline  const SalVisual&    GetVisual() const;
diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index 82cfb38..74e8fe0 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -203,6 +203,7 @@ public:
     explicit WinSalGraphics(WinSalGraphics::Type eType, bool bScreen, HWND hWnd);
     virtual ~WinSalGraphics();
 
+    SalGraphicsImpl* GetImpl() const SAL_OVERRIDE;
     bool isPrinter() const;
     bool isVirtualDevice() const;
     bool isWindow() const;
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 770b2b8..2f1d82f 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -30,6 +30,7 @@
 #include <basegfx/polygon/b2dtrapezoid.hxx>
 
 #include <vcl/opengl/OpenGLHelper.hxx>
+#include "salgdi.hxx"
 #include "opengl/salbmp.hxx"
 
 #include <vector>
@@ -1082,13 +1083,13 @@ void OpenGLSalGraphicsImpl::copyArea(
 
 // CopyBits and DrawBitmap --> RasterOp and ClipRegion
 // CopyBits() --> pSrcGraphics == NULL, then CopyBits on same Graphics
-void OpenGLSalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, SalGraphics* /*pSrcGraphics*/ )
+void OpenGLSalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics )
 {
-    // TODO Check if SalGraphicsImpl is the same
-    const bool bSameGraphics( false );
+    OpenGLSalGraphicsImpl *pImpl = pSrcGraphics ? dynamic_cast< OpenGLSalGraphicsImpl* >(pSrcGraphics->GetImpl()) : NULL;
 
     SAL_INFO( "vcl.opengl", "::copyBits" );
-    if( bSameGraphics &&
+
+    if( pImpl == this &&
         (rPosAry.mnSrcWidth == rPosAry.mnDestWidth) &&
         (rPosAry.mnSrcHeight == rPosAry.mnDestHeight))
     {
@@ -1102,6 +1103,16 @@ void OpenGLSalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, SalGraphics* /*
         return;
     }
 
+    if( pImpl->mbOffscreen )
+    {
+        Size aSize( pImpl->GetWidth(), pImpl->GetHeight() );
+        PreDraw();
+        DrawTexture( pImpl->maOffscreenTex, rPosAry );
+        PostDraw();
+        return;
+    }
+
+    SAL_WARN( "vcl.opengl", "*** NOT IMPLEMENTED *** copyBits" );
     // TODO Copy from one FBO to the other (glBlitFramebuffer)
 }
 
diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx
index 2723db4..e1fa280 100644
--- a/vcl/unx/generic/gdi/salgdi.cxx
+++ b/vcl/unx/generic/gdi/salgdi.cxx
@@ -121,6 +121,11 @@ void X11SalGraphics::freeResources()
     bFontGC_ = false;
 }
 
+SalGraphicsImpl* X11SalGraphics::GetImpl() const
+{
+    return mpImpl.get();
+}
+
 void X11SalGraphics::SetDrawable( Drawable aDrawable, SalX11Screen nXScreen )
 {
     // shortcut if nothing changed
diff --git a/vcl/win/source/gdi/salgdi.cxx b/vcl/win/source/gdi/salgdi.cxx
index b920a50..fbc4057 100644
--- a/vcl/win/source/gdi/salgdi.cxx
+++ b/vcl/win/source/gdi/salgdi.cxx
@@ -618,6 +618,11 @@ WinSalGraphics::~WinSalGraphics()
     delete [] mpFontKernPairs;
 }
 
+SalGraphicsImpl* WinSalGraphics::GetImpl() const
+{
+    return mpImpl.get();
+}
+
 bool WinSalGraphics::isPrinter() const
 {
     return mbPrinter;
commit b1e3b48a58d87fa2c0721294b6a277bdc8b492b4
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Thu Nov 13 09:33:22 2014 -0500

    vcl: Use backend-independent functions to fill/render pixmap on KDE
    
    Change-Id: I662a05d988f5989fc2ac0d06003851c56105e184

diff --git a/vcl/unx/kde/salnativewidgets-kde.cxx b/vcl/unx/kde/salnativewidgets-kde.cxx
index c3eac72..aa86e31 100644
--- a/vcl/unx/kde/salnativewidgets-kde.cxx
+++ b/vcl/unx/kde/salnativewidgets-kde.cxx
@@ -79,6 +79,54 @@
 using namespace ::com::sun::star;
 using namespace ::rtl;
 
+
+/** Qt implementation of X11Pixmap
+
+    Wrapper around a QPixmap.
+ */
+
+class KDEX11Pixmap : public X11Pixmap
+{
+public:
+    KDEX11Pixmap( int nWidth, int nHeight );
+    virtual ~KDEX11Pixmap() {};
+
+    virtual int          GetDepth() const SAL_OVERRIDE;
+    virtual SalX11Screen GetScreen() const SAL_OVERRIDE;
+    virtual Pixmap       GetPixmap() const SAL_OVERRIDE;
+    QPixmap              GetQPixmap() const;
+
+protected:
+    QPixmap mqPixmap;
+};
+
+KDEX11Pixmap::KDEX11Pixmap( int nWidth, int nHeight )
+: X11Pixmap( nWidth, nHeight )
+, mqPixmap( nWidth, nHeight )
+{
+}
+
+int KDEX11Pixmap::GetDepth() const
+{
+    return mqPixmap.x11Depth();
+}
+
+SalX11Screen KDEX11Pixmap::GetScreen() const
+{
+    return SalX11Screen( mqPixmap.x11Screen() );
+}
+
+Pixmap KDEX11Pixmap::GetPixmap() const
+{
+    return mqPixmap.handle();
+}
+
+QPixmap KDEX11Pixmap::GetQPixmap() const
+{
+    return mqPixmap;
+}
+
+
 /** Cached native widgets.
 
     A class which caches and paints the native widgets.
@@ -261,19 +309,12 @@ class WidgetPainter
         @param aValue
         The value (true/false, ...)
 
-        @param dpy
-        The display to be used by the X calls.
-
-        @param drawable
-        The destination X window.
-
-        @param gc
-        The graphics context.
+        @param pGraphics
+        The SalGraphics instance to read/write screen.
     */
         bool drawStyledWidget( QWidget *pWidget,
                 ControlState nState, const ImplControlValue& aValue,
-                Display *dpy, ::Window drawable, SalX11Screen nXScreen,
-                int nDepth, GC gc,
+                KDESalGraphics* pGraphics,
                 ControlPart nPart = PART_ENTIRE_CONTROL );
 
     /** 'Get' method for push button.
@@ -465,8 +506,7 @@ WidgetPainter::~WidgetPainter( void )
 
 bool WidgetPainter::drawStyledWidget( QWidget *pWidget,
     ControlState nState, const ImplControlValue& aValue,
-    Display *dpy, ::Window drawable, SalX11Screen nXScreen,
-    int nDepth, GC gc, ControlPart nPart )
+    KDESalGraphics* pGraphics, ControlPart nPart )
 {
     if ( !pWidget )
         return false;
@@ -479,9 +519,10 @@ bool WidgetPainter::drawStyledWidget( QWidget *pWidget,
     pWidget->setEnabled( nState & CTRL_STATE_ENABLED );
 
     // Create pixmap to paint to
-    QPixmap  qPixmap( pWidget->width(), pWidget->height() );
-    QPainter qPainter( &qPixmap );
-    QRect    qRect( 0, 0, pWidget->width(), pWidget->height() );
+    KDEX11Pixmap xPixmap( pWidget->width(), pWidget->height() );
+    QPixmap      qPixmap( xPixmap.GetQPixmap() );
+    QPainter     qPainter( &qPixmap );
+    QRect        qRect( 0, 0, pWidget->width(), pWidget->height() );
 
     // Use the background of the widget
     qPixmap.fill( pWidget, QPoint(0, 0) );
@@ -513,15 +554,7 @@ bool WidgetPainter::drawStyledWidget( QWidget *pWidget,
     {
         // Bitblt from the screen, because the radio buttons are usually not
         // rectangular, and there could be a bitmap under them
-        GC aTmpGC = XCreateGC( dpy, qPixmap.handle(), 0, NULL );
-        X11SalGraphics::CopyScreenArea(
-            dpy,
-            drawable, nXScreen, nDepth,
-            qPixmap.handle(), SalX11Screen( qPixmap.x11Screen() ), qPixmap.x11Depth(),
-            aTmpGC,
-            qWidgetPos.x(), qWidgetPos.y(), qRect.width(), qRect.height(),
-            0, 0 );
-        XFreeGC( dpy, aTmpGC );
+        pGraphics->FillPixmapFromScreen( &xPixmap, qWidgetPos.x(), qWidgetPos.y() );
 
         QApplication::style().drawControl( QStyle::CE_RadioButton,
             &qPainter, pWidget, qRect,
@@ -820,12 +853,7 @@ bool WidgetPainter::drawStyledWidget( QWidget *pWidget,
         return false;
 
     // Bitblt it to the screen
-    X11SalGraphics::CopyScreenArea(
-        dpy, qPixmap.handle(), SalX11Screen( qPixmap.x11Screen() ), qPixmap.x11Depth(),
-        drawable, nXScreen, nDepth,
-        gc,
-        0, 0, qRect.width(), qRect.height(),
-        qWidgetPos.x(), qWidgetPos.y() );
+    pGraphics->RenderPixmapToScreen( xPixmap, qWidgetPos.x(), qWidgetPos.y() );
 
     // Restore widget's position
     pWidget->move( qWidgetPos );
@@ -1382,121 +1410,101 @@ bool KDESalGraphics::drawNativeControl( ControlType nType, ControlPart nPart,
 {
     bool bReturn = false;
 
-    Display *dpy = GetXDisplay();
-    ::Window drawable = GetDrawable();
-    GC gc = SelectPen(); //SelectFont(); // GC with current clipping region set
-
     if ( (nType == CTRL_PUSHBUTTON) && (nPart == PART_ENTIRE_CONTROL) )
     {
     bReturn = pWidgetPainter->drawStyledWidget(
         pWidgetPainter->pushButton( rControlRegion, (nState & CTRL_STATE_DEFAULT) ),
-        nState, aValue,
-        dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
+        nState, aValue, this );
     }
     else if ( (nType == CTRL_RADIOBUTTON) && (nPart == PART_ENTIRE_CONTROL) )
     {
     bReturn = pWidgetPainter->drawStyledWidget(
         pWidgetPainter->radioButton( rControlRegion ),
-        nState, aValue,
-        dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
+        nState, aValue, this );
     }
     else if ( (nType == CTRL_CHECKBOX) && (nPart == PART_ENTIRE_CONTROL) )
     {
     bReturn = pWidgetPainter->drawStyledWidget(
         pWidgetPainter->checkBox( rControlRegion ),
-        nState, aValue,
-        dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
+        nState, aValue, this );
     }
     else if ( (nType == CTRL_COMBOBOX) && (nPart == PART_ENTIRE_CONTROL) )
     {
     bReturn = pWidgetPainter->drawStyledWidget(
         pWidgetPainter->comboBox( rControlRegion, true ),
-        nState, aValue,
-        dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
+        nState, aValue, this );
     }
     else if ( (nType == CTRL_EDITBOX) && (nPart == PART_ENTIRE_CONTROL) )
     {
     bReturn = pWidgetPainter->drawStyledWidget(
         pWidgetPainter->lineEdit( rControlRegion ),
-        nState, aValue,
-        dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
+        nState, aValue, this );
     }
     else if ( (nType == CTRL_LISTBOX) && (nPart == PART_ENTIRE_CONTROL) )
     {
     bReturn = pWidgetPainter->drawStyledWidget(
         pWidgetPainter->comboBox( rControlRegion, false ),
-        nState, aValue,
-        dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
+        nState, aValue, this );
     }
     else if ( (nType == CTRL_LISTBOX) && (nPart == PART_WINDOW) )
     {
     bReturn = pWidgetPainter->drawStyledWidget(
         pWidgetPainter->listView( rControlRegion ),
-        nState, aValue,
-        dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
+        nState, aValue, this );
     }
     else if ( (nType == CTRL_SPINBOX) && (nPart == PART_ENTIRE_CONTROL) )
     {
     bReturn = pWidgetPainter->drawStyledWidget(
         pWidgetPainter->spinWidget( rControlRegion ),
-        nState, aValue,
-        dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
+        nState, aValue, this );
     }
     else if ( (nType==CTRL_TAB_ITEM) && (nPart == PART_ENTIRE_CONTROL) )
     {
     bReturn = pWidgetPainter->drawStyledWidget(
         pWidgetPainter->tabBar( rControlRegion ),
-        nState, aValue,
-        dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
+        nState, aValue, this );
     }
     else if ( (nType==CTRL_TAB_PANE) && (nPart == PART_ENTIRE_CONTROL) )
     {
     bReturn = pWidgetPainter->drawStyledWidget(
         pWidgetPainter->tabWidget( rControlRegion ),
-        nState, aValue,
-        dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
+        nState, aValue, this );
     }
     else if ( (nType == CTRL_SCROLLBAR) && (nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT) )
     {
     bReturn = pWidgetPainter->drawStyledWidget(
         pWidgetPainter->scrollBar( rControlRegion, nPart == PART_DRAW_BACKGROUND_HORZ, aValue ),
-        nState, aValue,
-        dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
+        nState, aValue, this );
     }
     else if ( (nType == CTRL_TOOLBAR) && (nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT || nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT) )
     {
         bReturn = pWidgetPainter->drawStyledWidget(
                 pWidgetPainter->toolBar( rControlRegion, nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_THUMB_VERT ),
-                nState, aValue,
-                dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc, nPart );
+                nState, aValue, this, nPart );
     }
     else if ( (nType == CTRL_TOOLBAR) && (nPart == PART_BUTTON) )
     {
         bReturn = pWidgetPainter->drawStyledWidget(
                 pWidgetPainter->toolButton( rControlRegion ),
-                nState, aValue,
-                dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc, nPart );
+                nState, aValue, this, nPart );
     }
     else if ( (nType == CTRL_MENUBAR) && (nPart == PART_ENTIRE_CONTROL || nPart == PART_MENU_ITEM) )
     {
         bReturn = pWidgetPainter->drawStyledWidget(
                 pWidgetPainter->menuBar( rControlRegion ),
-                nState, aValue,
-                dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc, nPart );
+                nState, aValue, this, nPart );
     }
     else if ( (nType == CTRL_MENU_POPUP) && (nPart == PART_ENTIRE_CONTROL || nPart == PART_MENU_ITEM) )
     {
         bReturn = pWidgetPainter->drawStyledWidget(
                 pWidgetPainter->popupMenu( rControlRegion ),
-                nState, aValue,
-                dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
+                nState, aValue, this );
     }
     else if ( (nType == CTRL_PROGRESS) && (nPart == PART_ENTIRE_CONTROL) )
     {
         bReturn = pWidgetPainter->drawStyledWidget(
                 pWidgetPainter->progressBar( rControlRegion ),
-                nState, aValue,
-                dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
+                nState, aValue, this );
     }
 
     return bReturn;
commit d84040da1ed128dfd87386abe906f5f0014befd8
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Thu Nov 13 09:32:41 2014 -0500

    vcl: Replace GetPixmapFromScreen by FillPixmapFromScreen
    
    Change-Id: I2cb960d194ee5bc38beece97e8b21cc6fa3b3fbc

diff --git a/vcl/Library_vclplug_gen.mk b/vcl/Library_vclplug_gen.mk
index 73e5d01..76be2c1 100644
--- a/vcl/Library_vclplug_gen.mk
+++ b/vcl/Library_vclplug_gen.mk
@@ -94,7 +94,6 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_gen,\
     vcl/unx/generic/gdi/x11cairotextrender \
     vcl/unx/generic/gdi/gcach_xpeer \
 	vcl/unx/generic/gdi/gdiimpl \
-	vcl/unx/generic/gdi/pixmap \
 	vcl/unx/generic/gdi/openglx11cairotextrender \
     vcl/unx/generic/gdi/salbmp \
     vcl/unx/generic/gdi/salgdi2 \
diff --git a/vcl/inc/opengl/x11/gdiimpl.hxx b/vcl/inc/opengl/x11/gdiimpl.hxx
index 878c7c2..00eaf8c 100644
--- a/vcl/inc/opengl/x11/gdiimpl.hxx
+++ b/vcl/inc/opengl/x11/gdiimpl.hxx
@@ -33,7 +33,7 @@ public:
     // implementation of X11GraphicsImpl
 
     void Init() SAL_OVERRIDE;
-    X11Pixmap* GetPixmapFromScreen( const Rectangle& rRect ) SAL_OVERRIDE;
+    bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE;
     bool RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE;
 };
 
diff --git a/vcl/inc/unx/pixmap.hxx b/vcl/inc/unx/pixmap.hxx
index b65170f..ec3c932 100644
--- a/vcl/inc/unx/pixmap.hxx
+++ b/vcl/inc/unx/pixmap.hxx
@@ -19,27 +19,25 @@
 class VCLPLUG_GEN_PUBLIC X11Pixmap
 {
 public:
-    X11Pixmap();
-    X11Pixmap( Display *pDisplay, SalX11Screen nScreen, int nWidth, int nHeight, int nDepth );
-    X11Pixmap( X11Pixmap& rOther );
-    virtual ~X11Pixmap();
+    X11Pixmap( int nWidth, int nHeight )
+    {
+        mnWidth = nWidth;
+        mnHeight = nHeight;
+    }
 
-    Pixmap GetPixmap() const { return mpPixmap; };
-    Drawable GetDrawable() const { return mpPixmap; };
+    virtual ~X11Pixmap() {};
+
+    virtual int GetDepth() const = 0;
+    virtual SalX11Screen GetScreen() const = 0;
+    virtual Pixmap GetPixmap() const = 0;
+    Drawable GetDrawable() const { return GetPixmap(); };
     int GetWidth() const { return mnWidth; };
     int GetHeight() const { return mnHeight; };
     Size GetSize() const { return Size( mnWidth, mnHeight ); };
-    int GetDepth() const { return mnDepth; };
-    SalX11Screen GetScreen() const { return mnScreen; }
 
 protected:
-    Display*        mpDisplay;
-    SalX11Screen    mnScreen;
-    Pixmap          mpPixmap;
-    bool            mbDeletePixmap;
     int             mnWidth;
     int             mnHeight;
-    int             mnDepth;
 };
 
 #endif // INCLUDED_VCL_INC_UNX_PIXMAP_HXX
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index 6fc4f72..bc41041 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -274,8 +274,8 @@ public:
     virtual void               BeginPaint() SAL_OVERRIDE;
     virtual void               EndPaint() SAL_OVERRIDE;
 
-    // create a pixmap from a screen region
-    X11Pixmap* GetPixmapFromScreen( const Rectangle& rRect );
+    // fill a pixmap from a screen region
+    bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY );
 
     // render a pixmap to the screen
     bool RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY );
diff --git a/vcl/inc/unx/x11/x11gdiimpl.h b/vcl/inc/unx/x11/x11gdiimpl.h
index 911ea71..8cd130d 100644
--- a/vcl/inc/unx/x11/x11gdiimpl.h
+++ b/vcl/inc/unx/x11/x11gdiimpl.h
@@ -18,7 +18,7 @@ public:
     virtual ~X11GraphicsImpl() {};
 
     virtual void Init() = 0;
-    virtual X11Pixmap* GetPixmapFromScreen( const Rectangle& rRect ) = 0;
+    virtual bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) = 0;
     virtual bool RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) = 0;
 };
 
diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx
index 184abab..fe775f5 100644
--- a/vcl/opengl/x11/gdiimpl.cxx
+++ b/vcl/opengl/x11/gdiimpl.cxx
@@ -79,42 +79,39 @@ void X11OpenGLSalGraphicsImpl::Init()
     }
 }
 
-X11Pixmap* X11OpenGLSalGraphicsImpl::GetPixmapFromScreen( const Rectangle& rRect )
+bool X11OpenGLSalGraphicsImpl::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY )
 {
     Display* pDisplay = mrParent.GetXDisplay();
     SalX11Screen nScreen = mrParent.GetScreenNumber();
     XVisualInfo aVisualInfo;
-    X11Pixmap* pPixmap;
     XImage* pImage;
     char* pData;
 
-    SAL_INFO( "vcl.opengl", "GetPixmapFromScreen" );
-    // TODO: lfrb: Use context depth
-    pPixmap = new X11Pixmap( pDisplay, nScreen, rRect.GetWidth(), rRect.GetHeight(), 24 );
+    SAL_INFO( "vcl.opengl", "FillPixmapFromScreen" );
 
     if( !OpenGLHelper::GetVisualInfo( pDisplay, nScreen.getXScreen(), aVisualInfo ) )
-        return pPixmap;
+        return false;
 
     // make sure everything is synced up before reading back
     maContext.makeCurrent();
     glXWaitX();
 
     // TODO: lfrb: What if offscreen?
-    pData = (char*) malloc( rRect.GetWidth() * rRect.GetHeight() * 4 );
+    pData = (char*) malloc( pPixmap->GetWidth() * pPixmap->GetHeight() * 4 );
     glPixelStorei( GL_PACK_ALIGNMENT, 1 );
-    glReadPixels( rRect.Left(), GetHeight() - rRect.Top(), rRect.GetWidth(), rRect.GetHeight(),
+    glReadPixels( nX, GetHeight() - nY, pPixmap->GetWidth(), pPixmap->GetHeight(),
                   GL_RGBA, GL_UNSIGNED_BYTE, pData );
 
     pImage = XCreateImage( pDisplay, aVisualInfo.visual, 24, ZPixmap, 0, pData,
-                           rRect.GetWidth(), rRect.GetHeight(), 8, 0 );
+                           pPixmap->GetWidth(), pPixmap->GetHeight(), 8, 0 );
     XInitImage( pImage );
     GC aGC = XCreateGC( pDisplay, pPixmap->GetPixmap(), 0, NULL );
     XPutImage( pDisplay, pPixmap->GetDrawable(), aGC, pImage,
-               0, 0, 0, 0, rRect.GetWidth(), rRect.GetHeight() );
+               0, 0, 0, 0, pPixmap->GetWidth(), pPixmap->GetHeight() );
     XFreeGC( pDisplay, aGC );
     XDestroyImage( pImage );
 
-    return pPixmap;
+    return true;
 }
 
 bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY )
diff --git a/vcl/unx/generic/gdi/gdiimpl.cxx b/vcl/unx/generic/gdi/gdiimpl.cxx
index 4adea62..ee7e596 100644
--- a/vcl/unx/generic/gdi/gdiimpl.cxx
+++ b/vcl/unx/generic/gdi/gdiimpl.cxx
@@ -159,22 +159,16 @@ void X11SalGraphicsImpl::Init()
     mnBrushPixel = mrParent.GetPixel( mnBrushColor );
 }
 
-X11Pixmap* X11SalGraphicsImpl::GetPixmapFromScreen( const Rectangle& rRect )
+bool X11SalGraphicsImpl::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY )
 {
     //TODO lfrb: don't hardcode the depth
     Display* pDpy = mrParent.GetXDisplay();
-    X11Pixmap* pPixmap = new X11Pixmap( pDpy, mrParent.GetScreenNumber(),
-                                        rRect.GetWidth(), rRect.GetHeight(), 24 );
     GC aTmpGC = XCreateGC( pDpy, pPixmap->GetPixmap(), 0, NULL );
 
-    if( !pPixmap || !aTmpGC )
+    if( !aTmpGC )
     {
-        if ( pPixmap )
-            delete pPixmap;
-        if ( aTmpGC )
-            XFreeGC( pDpy, aTmpGC );
-        SAL_WARN( "vcl", "Could not get valid pixmap from screen" );
-        return NULL;
+        SAL_WARN( "vcl", "Could not create GC from screen" );
+        return false;
     }
 
     // Copy the background of the screen into a composite pixmap
@@ -184,12 +178,11 @@ X11Pixmap* X11SalGraphicsImpl::GetPixmapFromScreen( const Rectangle& rRect )
                              pPixmap->GetDrawable(), pPixmap->GetScreen(),
                              pPixmap->GetDepth(),
                              aTmpGC,
-                             rRect.Left(), rRect.Top(),
-                             rRect.GetWidth(), rRect.GetHeight(),
+                             nX, nY, pPixmap->GetWidth(), pPixmap->GetHeight(),
                              0, 0 );
 
     XFreeGC( pDpy, aTmpGC );
-    return pPixmap;
+    return true;
 }
 
 bool X11SalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY )
diff --git a/vcl/unx/generic/gdi/gdiimpl.hxx b/vcl/unx/generic/gdi/gdiimpl.hxx
index fed9bc6..2d9294a 100644
--- a/vcl/unx/generic/gdi/gdiimpl.hxx
+++ b/vcl/unx/generic/gdi/gdiimpl.hxx
@@ -274,7 +274,7 @@ public:
     // implementation of X11GraphicsImpl
 
     void Init() SAL_OVERRIDE;
-    X11Pixmap* GetPixmapFromScreen( const Rectangle& rRect ) SAL_OVERRIDE;
+    bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE;
     bool RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE;
 };
 
diff --git a/vcl/unx/generic/gdi/pixmap.cxx b/vcl/unx/generic/gdi/pixmap.cxx
deleted file mode 100644
index 0440c46..0000000
--- a/vcl/unx/generic/gdi/pixmap.cxx
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- 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/.
- */
-
-#include "unx/pixmap.hxx"
-
-X11Pixmap::X11Pixmap()
-: mpDisplay( NULL )
-, mnScreen( 0 )
-, mpPixmap( 0 )
-, mbDeletePixmap( false )
-, mnWidth( -1 )
-, mnHeight( -1 )
-, mnDepth( 0 )
-{
-}
-
-X11Pixmap::X11Pixmap( Display* pDisplay, SalX11Screen nScreen, int nWidth, int nHeight, int nDepth )
-: mpDisplay( pDisplay )
-, mnScreen( nScreen )
-, mbDeletePixmap( true )
-, mnWidth( nWidth )
-, mnHeight( nHeight )
-, mnDepth( nDepth )
-{
-    Window root = RootWindow( pDisplay, 0 );
-    mpPixmap = XCreatePixmap( pDisplay, root, nWidth, nHeight, nDepth );
-}
-
-X11Pixmap::X11Pixmap( X11Pixmap& rOther )
-: mpDisplay( rOther.mpDisplay )
-, mnScreen( rOther.mnScreen )
-, mbDeletePixmap( rOther.mbDeletePixmap )
-, mnWidth( rOther.mnWidth )
-, mnHeight( rOther.mnHeight )
-, mnDepth( rOther.mnDepth )
-{
-    mpPixmap = rOther.mpPixmap;
-    rOther.mpPixmap = 0;
-    rOther.mbDeletePixmap = false;
-}
-
-X11Pixmap::~X11Pixmap()
-{
-    if (mbDeletePixmap && mpPixmap)
-        XFreePixmap( mpDisplay, mpPixmap );
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/generic/gdi/salgdi2.cxx b/vcl/unx/generic/gdi/salgdi2.cxx
index fe7199c..548f6e2 100644
--- a/vcl/unx/generic/gdi/salgdi2.cxx
+++ b/vcl/unx/generic/gdi/salgdi2.cxx
@@ -83,10 +83,10 @@ void X11SalGraphics::CopyScreenArea( Display* pDisplay,
     }
 }
 
-X11Pixmap* X11SalGraphics::GetPixmapFromScreen( const Rectangle& rRect )
+bool X11SalGraphics::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY )
 {
     X11GraphicsImpl* pImpl = dynamic_cast<X11GraphicsImpl*>(mpImpl.get());
-    return pImpl->GetPixmapFromScreen( rRect );
+    return pImpl->FillPixmapFromScreen( pPixmap, nX, nY );
 }
 
 bool X11SalGraphics::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY )
diff --git a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
index 2473297..1ad8269 100644
--- a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
+++ b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
@@ -269,49 +269,44 @@ class GdkX11Pixmap : public X11Pixmap
 {
 public:
     GdkX11Pixmap( int nWidth, int nHeight, int nDepth );
-    GdkX11Pixmap( X11Pixmap& rOther, GdkWindow *pWindow );
     virtual ~GdkX11Pixmap();
 
-    GdkPixmap*   GetGdkPixmap() const;
-    GdkDrawable* GetGdkDrawable() const;
+    virtual int          GetDepth() const SAL_OVERRIDE;
+    virtual SalX11Screen GetScreen() const SAL_OVERRIDE;
+    virtual Pixmap       GetPixmap() const SAL_OVERRIDE;
+    GdkPixmap*           GetGdkPixmap() const;
+    GdkDrawable*         GetGdkDrawable() const;
 
 protected:
     GdkPixmap* mpGdkPixmap;
+    int        mnDepth;
 };
 
 GdkX11Pixmap::GdkX11Pixmap( int nWidth, int nHeight, int nDepth )
+: X11Pixmap( nWidth, nHeight )
+, mnDepth( nDepth )
 {
     mpGdkPixmap = gdk_pixmap_new( NULL, nWidth, nHeight, nDepth );
-
-    //mpDisplay = ?
-    mnScreen = SalX11Screen( gdk_screen_get_number( gdk_drawable_get_screen( GDK_DRAWABLE(mpGdkPixmap) ) ) );
-    mnWidth = nWidth;
-    mnHeight = nHeight;
-    mnDepth = nDepth;
-    mpPixmap = GDK_PIXMAP_XID( mpGdkPixmap );
 }
 
-GdkX11Pixmap::GdkX11Pixmap( X11Pixmap& rOther, GdkWindow *pWindow )
-    : X11Pixmap(rOther)
+GdkX11Pixmap::~GdkX11Pixmap()
 {
-    GdkColormap* pColormap;
+    g_object_unref( mpGdkPixmap );
+}
 
-#if GTK_CHECK_VERSION(2,24,0)
-    GdkScreen *pScreen = gdk_window_get_screen( pWindow );
-    mpGdkPixmap = gdk_pixmap_foreign_new_for_screen( pScreen, mpPixmap,
-                                                     mnWidth, mnHeight,
-                                                     mnDepth );
-#else
-    mpGdkPixmap = gdk_pixmap_foreign_new( mpPixmap );
-#endif
+int GdkX11Pixmap::GetDepth() const
+{
+    return mnDepth;
+}
 
-    pColormap = gdk_drawable_get_colormap( pWindow );
-    gdk_drawable_set_colormap( GDK_DRAWABLE (mpGdkPixmap), pColormap );
+SalX11Screen GdkX11Pixmap::GetScreen() const
+{
+    return SalX11Screen( gdk_screen_get_number( gdk_drawable_get_screen( GDK_DRAWABLE(mpGdkPixmap) ) ) );
 }
 
-GdkX11Pixmap::~GdkX11Pixmap()
+Pixmap GdkX11Pixmap::GetPixmap() const
 {
-    g_object_unref( mpGdkPixmap );
+    return GDK_PIXMAP_XID( mpGdkPixmap );
 }
 
 GdkPixmap* GdkX11Pixmap::GetGdkPixmap() const
@@ -4136,17 +4131,11 @@ void GtkSalGraphics::updateSettings( AllSettings& rSettings )
 
 GdkX11Pixmap* GtkSalGraphics::NWGetPixmapFromScreen( Rectangle srcRect )
 {
-    X11Pixmap* pPixmap;
-    GdkX11Pixmap* pResult;
-
-    pPixmap = GetPixmapFromScreen( srcRect );
-    if( pPixmap == NULL )
-        return NULL;
-
-    pResult = new GdkX11Pixmap( *pPixmap, GetGdkWindow() );
-    delete pPixmap;
+    GdkX11Pixmap* pPixmap;
 
-    return pResult;
+    pPixmap = new GdkX11Pixmap( srcRect.GetWidth(), srcRect.GetHeight(), 24 );
+    FillPixmapFromScreen( pPixmap, srcRect.Left(), srcRect.Top() );
+    return pPixmap;
 }
 
 /************************************************************************


More information about the Libreoffice-commits mailing list