[Libreoffice-commits] core.git: 5 commits - include/vcl vcl/CppunitTest_vcl_outdev.mk vcl/headless vcl/inc vcl/Library_vcl.mk vcl/Library_vclplug_gen.mk vcl/Module_vcl.mk vcl/opengl vcl/qa vcl/quartz vcl/source vcl/unx vcl/win

Michael Meeks michael.meeks at collabora.com
Mon Dec 1 23:43:27 PST 2014


 include/vcl/opengl/OpenGLContext.hxx       |   15 ++
 vcl/CppunitTest_vcl_outdev.mk              |   52 +++++++++
 vcl/Library_vcl.mk                         |    1 
 vcl/Library_vclplug_gen.mk                 |    1 
 vcl/Module_vcl.mk                          |    1 
 vcl/headless/svpvd.cxx                     |   12 --
 vcl/inc/headless/svpvd.hxx                 |    5 
 vcl/inc/opengl/framebuffer.hxx             |   45 ++++++++
 vcl/inc/opengl/salbmp.hxx                  |    1 
 vcl/inc/opengl/texture.hxx                 |    3 
 vcl/inc/opengl/win/gdiimpl.hxx             |    9 -
 vcl/inc/opengl/x11/gdiimpl.hxx             |    9 -
 vcl/inc/opengl/x11/salvd.hxx               |   56 ++++++++++
 vcl/inc/openglgdiimpl.hxx                  |   26 ++--
 vcl/inc/quartz/salvd.h                     |    1 
 vcl/inc/salframe.hxx                       |    9 +
 vcl/inc/salgeom.hxx                        |   12 ++
 vcl/inc/salvd.hxx                          |    8 -
 vcl/inc/svdata.hxx                         |    2 
 vcl/inc/unx/salgdi.h                       |    6 -
 vcl/inc/unx/salvd.h                        |   24 +---
 vcl/inc/win/salgdi.h                       |    4 
 vcl/inc/win/salvd.h                        |    7 +
 vcl/opengl/framebuffer.cxx                 |   70 ++++++++++++
 vcl/opengl/gdiimpl.cxx                     |  137 +++++++++++--------------
 vcl/opengl/salbmp.cxx                      |   17 +--
 vcl/opengl/scale.cxx                       |   35 ++----
 vcl/opengl/win/gdiimpl.cxx                 |   56 ----------
 vcl/opengl/x11/gdiimpl.cxx                 |   95 ++++++-----------
 vcl/opengl/x11/salvd.cxx                   |   97 +++++++++++++++++
 vcl/qa/cppunit/outdev.cxx                  |   67 ++++++++++++
 vcl/quartz/salvd.cxx                       |   16 --
 vcl/source/gdi/salgdilayout.cxx            |    2 
 vcl/source/gdi/virdev.cxx                  |    6 -
 vcl/source/opengl/OpenGLContext.cxx        |  127 ++++++++++++++++++++---
 vcl/unx/generic/gdi/gdiimpl.cxx            |   10 -
 vcl/unx/generic/gdi/salgdi.cxx             |   22 ++--
 vcl/unx/generic/gdi/salvd.cxx              |  157 +++++++++++------------------
 vcl/unx/generic/gdi/x11cairotextrender.cxx |   36 ++----
 vcl/win/source/gdi/salgdi.cxx              |    4 
 vcl/win/source/gdi/salprn.cxx              |    2 
 vcl/win/source/gdi/salvd.cxx               |   17 +--
 vcl/win/source/window/salframe.cxx         |    4 
 43 files changed, 832 insertions(+), 454 deletions(-)

New commits:
commit 5dcaefdae5ddf5ee70b4dd453afee69cdf8fc9d7
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Sat Nov 29 22:55:31 2014 +0000

    vcl: Consolidate size information around the GeometryProvider.
    
    Conflicts:
    	vcl/inc/openglgdiimpl.hxx
    
    Change-Id: I1d764a8dba1850d2475f08e1014a085846f336c3

diff --git a/vcl/inc/opengl/win/gdiimpl.hxx b/vcl/inc/opengl/win/gdiimpl.hxx
index da1a278..30ade23 100644
--- a/vcl/inc/opengl/win/gdiimpl.hxx
+++ b/vcl/inc/opengl/win/gdiimpl.hxx
@@ -24,13 +24,10 @@ private:
     WinSalGraphics& mrParent;
 
 public:
-    WinOpenGLSalGraphicsImpl(WinSalGraphics& rGraphics);
+    WinOpenGLSalGraphicsImpl(WinSalGraphics& rGraphics,
+                             SalGeometryProvider *mpProvider);
 
 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 UseContext( OpenGLContext* pContext ) SAL_OVERRIDE;
     virtual OpenGLContext* CreatePixmapContext() SAL_OVERRIDE;
diff --git a/vcl/inc/opengl/x11/gdiimpl.hxx b/vcl/inc/opengl/x11/gdiimpl.hxx
index 53ebe5b..d6ef010 100644
--- a/vcl/inc/opengl/x11/gdiimpl.hxx
+++ b/vcl/inc/opengl/x11/gdiimpl.hxx
@@ -26,10 +26,6 @@ public:
     virtual ~X11OpenGLSalGraphicsImpl();
 
 protected:
-    GLfloat GetWidth() const SAL_OVERRIDE;
-    GLfloat GetHeight() const SAL_OVERRIDE;
-    bool    IsOffscreen() const SAL_OVERRIDE;
-
     virtual OpenGLContext* CreateWinContext() SAL_OVERRIDE;
     virtual OpenGLContext* CreatePixmapContext() SAL_OVERRIDE;
     virtual bool UseContext( OpenGLContext* pContext ) SAL_OVERRIDE;
@@ -38,6 +34,9 @@ public:
     // implementation of X11GraphicsImpl
 
     virtual void copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ) SAL_OVERRIDE;
+
+    virtual 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 ac42527..39e39fc 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -20,6 +20,7 @@
 #ifndef INCLUDED_VCL_OPENGLGDIIMPL_HXX
 #define INCLUDED_VCL_OPENGLGDIIMPL_HXX
 
+#include "salgeom.hxx"
 #include "salgdiimpl.hxx"
 #include <vcl/dllapi.h>
 
@@ -40,6 +41,8 @@ class VCL_PLUGIN_PUBLIC OpenGLSalGraphicsImpl : public SalGraphicsImpl
 protected:
 
     boost::shared_ptr<OpenGLContext> mpContext;
+    /// Pointer to the SalFrame or SalVirtualDevice
+    SalGeometryProvider* mpParent;
     OpenGLFramebuffer* mpFramebuffer;
 
     // clipping
@@ -144,13 +147,13 @@ public:
 
 public:
     // get the width of the device
-    virtual GLfloat GetWidth() const = 0;
+    GLfloat GetWidth() const { return mpParent ? mpParent->GetWidth() : 1; }
 
     // get the height of the device
-    virtual GLfloat GetHeight() const = 0;
+    GLfloat GetHeight() const { return mpParent ? mpParent->GetHeight() : 1; }
 
     // check whether this instance is used for offscreen rendering
-    virtual bool IsOffscreen() const = 0;
+    bool IsOffscreen() const { return mpParent ? mpParent->IsOffScreen() : true; }
 
     // operations to do before painting
     virtual void PreDraw();
@@ -172,7 +175,7 @@ protected:
     virtual bool UseContext( OpenGLContext* pContext ) = 0;
 
 public:
-    OpenGLSalGraphicsImpl();
+    OpenGLSalGraphicsImpl(SalGeometryProvider* pParent);
     virtual ~OpenGLSalGraphicsImpl ();
 
     OpenGLContext* GetOpenGLContext();
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index edf47b1..29697a9 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -29,6 +29,7 @@
 #include <vcl/metric.hxx>
 
 #include "salgdi.hxx"
+#include "salgeom.hxx"
 #include "sallayout.hxx"
 #include "vclpluginapi.h"
 
@@ -132,6 +133,7 @@ public:
     inline  const SalDisplay*   GetDisplay() const;
     inline  Display*            GetXDisplay() const;
     inline  const SalVisual&    GetVisual() const;
+    SalGeometryProvider    *GetGeometryProvider() const;
     inline  Drawable        GetDrawable() const { return hDrawable_; }
     void                    SetDrawable( Drawable d, SalX11Screen nXScreen );
     XRenderPictFormat*      GetXRenderFormat() const;
diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index 443c1c2..5a46cb1f 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -21,6 +21,7 @@
 #define INCLUDED_VCL_INC_WIN_SALGDI_H
 
 #include "sallayout.hxx"
+#include "salgeom.hxx"
 #include "salgdi.hxx"
 #include "outfont.hxx"
 #include "PhysicalFontFace.hxx"
@@ -243,7 +244,8 @@ public:
     HFONT                   ImplDoSetFont( FontSelectPattern* i_pFont, float& o_rFontScale, HFONT& o_rOldFont );
 
 public:
-    explicit WinSalGraphics(WinSalGraphics::Type eType, bool bScreen, HWND hWnd);
+    explicit WinSalGraphics(WinSalGraphics::Type eType, bool bScreen, HWND hWnd,
+                            SalGeometryProvider *pProvider);
     virtual ~WinSalGraphics();
 
     SalGraphicsImpl* GetImpl() const SAL_OVERRIDE;
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index beae9dd..2f0dd29 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -63,8 +63,9 @@
                  ((float) aColor.GetBlue()) * nFactor / 25500.0,  \
                  1.0f )
 
-OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl()
+OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl(SalGeometryProvider* pParent)
     : mpContext(0)
+    , mpParent(pParent)
     , mpFramebuffer(NULL)
     , mbUseScissor(false)
     , mbUseStencil(false)
diff --git a/vcl/opengl/win/gdiimpl.cxx b/vcl/opengl/win/gdiimpl.cxx
index 2bd31bf..939d4e0 100644
--- a/vcl/opengl/win/gdiimpl.cxx
+++ b/vcl/opengl/win/gdiimpl.cxx
@@ -13,7 +13,9 @@
 #include <win/saldata.hxx>
 #include <win/salframe.h>
 
-WinOpenGLSalGraphicsImpl::WinOpenGLSalGraphicsImpl(WinSalGraphics& rGraphics):
+WinOpenGLSalGraphicsImpl::WinOpenGLSalGraphicsImpl(WinSalGraphics& rGraphics,
+                                                   SalGeometryProvider *mpProvider):
+    OpenGLSalGraphicsImpl(mpProvider),
     mrParent(rGraphics)
 {
 }
@@ -24,56 +26,6 @@ void WinOpenGLSalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, SalGraphics*
     OpenGLSalGraphicsImpl::DoCopyBits( rPosAry, *pImpl );
 }
 
-GLfloat WinOpenGLSalGraphicsImpl::GetWidth() const
-{
-    if( mrParent.gethWnd() && IsWindow( mrParent.gethWnd() ) )
-    {
-        WinSalFrame* pFrame = GetWindowPtr( mrParent.gethWnd() );
-        if( pFrame )
-        {
-            if( pFrame->maGeometry.nWidth )
-                return pFrame->maGeometry.nWidth;
-            else
-            {
-                // TODO: perhaps not needed, maGeometry should always be up-to-date
-                RECT aRect;
-                GetClientRect( mrParent.gethWnd(), &aRect );
-                return aRect.right;
-            }
-        }
-    }
-
-    return 1;
-}
-
-GLfloat WinOpenGLSalGraphicsImpl::GetHeight() const
-{
-    if( mrParent.gethWnd() && IsWindow( mrParent.gethWnd() ) )
-    {
-        WinSalFrame* pFrame = GetWindowPtr( mrParent.gethWnd() );
-        if( pFrame )
-        {
-            if( pFrame->maGeometry.nHeight )
-                return pFrame->maGeometry.nHeight;
-            else
-            {
-                // TODO: perhaps not needed, maGeometry should always be up-to-date
-                RECT aRect;
-                GetClientRect( mrParent.gethWnd(), &aRect );
-                return aRect.bottom;
-            }
-        }
-    }
-
-    return 1;
-}
-
-bool WinOpenGLSalGraphicsImpl::IsOffscreen() const
-{
-    WinSalFrame* pFrame = GetWindowPtr( mrParent.gethWnd() );
-    return ( pFrame == NULL );
-}
-
 OpenGLContext* WinOpenGLSalGraphicsImpl::CreateWinContext()
 {
     OpenGLContext* pContext = new OpenGLContext();
diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx
index 07b8abf..e5070d7 100644
--- a/vcl/opengl/x11/gdiimpl.cxx
+++ b/vcl/opengl/x11/gdiimpl.cxx
@@ -26,7 +26,7 @@
 #include <vcl/opengl/OpenGLHelper.hxx>
 
 X11OpenGLSalGraphicsImpl::X11OpenGLSalGraphicsImpl( X11SalGraphics& rParent ):
-    OpenGLSalGraphicsImpl(),
+    OpenGLSalGraphicsImpl(rParent.GetGeometryProvider()),
     mrParent(rParent)
 {
 }
@@ -35,36 +35,11 @@ X11OpenGLSalGraphicsImpl::~X11OpenGLSalGraphicsImpl()
 {
 }
 
-GLfloat X11OpenGLSalGraphicsImpl::GetWidth() const
+void X11OpenGLSalGraphicsImpl::Init()
 {
-    if( mrParent.m_pFrame )
-        return mrParent.m_pFrame->maGeometry.nWidth;
-    else if( mrParent.m_pVDev )
-        return static_cast< X11OpenGLSalVirtualDevice* >(mrParent.m_pVDev)->GetWidth();
-    return 1;
-}
-
-GLfloat X11OpenGLSalGraphicsImpl::GetHeight() const
-{
-    if( mrParent.m_pFrame )
-        return mrParent.m_pFrame->maGeometry.nHeight;
-    else if( mrParent.m_pVDev )
-        return static_cast< X11OpenGLSalVirtualDevice* >(mrParent.m_pVDev)->GetHeight();
-    return 1;
-}
-
-bool X11OpenGLSalGraphicsImpl::IsOffscreen() const
-{
-    X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame);
-    if( pProvider )
-        return false;
-    else if( mrParent.m_pVDev )
-        return true;
-    else
-    {
-        SAL_WARN( "vcl.opengl", "what happened here?" );
-        return true;
-    }
+    // The m_pFrame and m_pVDev pointers are updated late in X11
+    mpParent = mrParent.GetGeometryProvider();
+    OpenGLSalGraphicsImpl::Init();
 }
 
 OpenGLContext* X11OpenGLSalGraphicsImpl::CreateWinContext()
diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx
index 38aa7a3..7772972 100644
--- a/vcl/unx/generic/gdi/salgdi.cxx
+++ b/vcl/unx/generic/gdi/salgdi.cxx
@@ -487,4 +487,12 @@ void X11SalGraphics::EndPaint()
     return mpImpl->endPaint();
 }
 
+SalGeometryProvider *X11SalGraphics::GetGeometryProvider() const
+{
+    if (m_pFrame)
+        return static_cast< SalGeometryProvider * >(m_pFrame);
+    else
+        return static_cast< SalGeometryProvider * >(m_pVDev);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/win/source/gdi/salgdi.cxx b/vcl/win/source/gdi/salgdi.cxx
index 4c36bb3..c2d644d 100644
--- a/vcl/win/source/gdi/salgdi.cxx
+++ b/vcl/win/source/gdi/salgdi.cxx
@@ -613,7 +613,7 @@ OpenGLTexture* OpenGLCompatibleDC::getTexture()
     return new OpenGLTexture(maRects.mnSrcWidth, maRects.mnSrcHeight, GL_BGRA, GL_UNSIGNED_BYTE, reinterpret_cast<sal_uInt8*>(mpData));
 }
 
-WinSalGraphics::WinSalGraphics(WinSalGraphics::Type eType, bool bScreen, HWND hWnd):
+WinSalGraphics::WinSalGraphics(WinSalGraphics::Type eType, bool bScreen, HWND hWnd, SalGeometryProvider *pProvider):
     mhLocalDC(0),
     mbPrinter(eType == WinSalGraphics::PRINTER),
     mbVirDev(eType == WinSalGraphics::VIRTUAL_DEVICE),
@@ -634,7 +634,7 @@ WinSalGraphics::WinSalGraphics(WinSalGraphics::Type eType, bool bScreen, HWND hW
     mnPenWidth(GSL_PEN_WIDTH)
 {
     if (OpenGLHelper::isVCLOpenGLEnabled() && !mbPrinter)
-        mpImpl.reset(new WinOpenGLSalGraphicsImpl(*this));
+        mpImpl.reset(new WinOpenGLSalGraphicsImpl(*this, pProvider));
     else
         mpImpl.reset(new WinSalGraphicsImpl(*this));
 
diff --git a/vcl/win/source/gdi/salprn.cxx b/vcl/win/source/gdi/salprn.cxx
index ad22b4e..7822662 100644
--- a/vcl/win/source/gdi/salprn.cxx
+++ b/vcl/win/source/gdi/salprn.cxx
@@ -1045,7 +1045,7 @@ static HDC ImplCreateSalPrnIC( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetup
 
 static WinSalGraphics* ImplCreateSalPrnGraphics( HDC hDC )
 {
-    WinSalGraphics* pGraphics = new WinSalGraphics(WinSalGraphics::PRINTER, false, 0);
+    WinSalGraphics* pGraphics = new WinSalGraphics(WinSalGraphics::PRINTER, false, 0, /* CHECKME */ NULL);
     pGraphics->SetLayout( 0 );
     pGraphics->setHDC(hDC);
     pGraphics->InitGraphics();
diff --git a/vcl/win/source/gdi/salvd.cxx b/vcl/win/source/gdi/salvd.cxx
index cea8a76..6758b09 100644
--- a/vcl/win/source/gdi/salvd.cxx
+++ b/vcl/win/source/gdi/salvd.cxx
@@ -105,7 +105,7 @@ SalVirtualDevice* WinSalInstance::CreateVirtualDevice( SalGraphics* pSGraphics,
     {
         WinSalVirtualDevice*    pVDev = new WinSalVirtualDevice;
         SalData*                pSalData = GetSalData();
-        WinSalGraphics*         pVirGraphics = new WinSalGraphics(WinSalGraphics::VIRTUAL_DEVICE, pGraphics->isScreen(), 0);
+        WinSalGraphics*         pVirGraphics = new WinSalGraphics(WinSalGraphics::VIRTUAL_DEVICE, pGraphics->isScreen(), 0, pVDev);
         pVirGraphics->SetLayout( 0 );   // by default no! mirroring for VirtualDevices, can be enabled with EnableRTL()
         pVirGraphics->setHDC(hDC);
         if ( pSalData->mhDitherPal && pVirGraphics->isScreen() )
@@ -115,8 +115,8 @@ SalVirtualDevice* WinSalInstance::CreateVirtualDevice( SalGraphics* pSGraphics,
         }
         pVirGraphics->InitGraphics();
 
-        mnWidth = nDX;
-        mnHeight = nDY;
+        pVDev->mnWidth = nDX;
+        pVDev->mnHeight = nDY;
         pVDev->setHDC(hDC);
         pVDev->mhBmp        = hBmp;
         if( hBmp )
@@ -207,6 +207,9 @@ bool WinSalVirtualDevice::SetSize( long nDX, long nDY )
         HBITMAP hNewBmp = ImplCreateVirDevBitmap(getHDC(), nDX, nDY, mnBitCount, &pDummy);
         if ( hNewBmp )
         {
+            mnWidth = nDX;
+            mnHeight = nDY;
+
             SelectBitmap( getHDC(), hNewBmp );
             DeleteBitmap( mhBmp );
             mhBmp = hNewBmp;
@@ -215,6 +218,8 @@ bool WinSalVirtualDevice::SetSize( long nDX, long nDY )
         else
         {
             ImplWriteLastError( GetLastError(), "ImplCreateVirDevBitmap in SetSize" );
+            mnWidth = 0;
+            mnHeight = 0;
             return FALSE;
         }
     }
diff --git a/vcl/win/source/window/salframe.cxx b/vcl/win/source/window/salframe.cxx
index c8f5f3f..a048e2e 100644
--- a/vcl/win/source/window/salframe.cxx
+++ b/vcl/win/source/window/salframe.cxx
@@ -983,7 +983,7 @@ SalGraphics* WinSalFrame::AcquireGraphics()
 
         if ( !mpGraphics2 )
         {
-            mpGraphics2 = new WinSalGraphics(WinSalGraphics::WINDOW, true, mhWnd);
+            mpGraphics2 = new WinSalGraphics(WinSalGraphics::WINDOW, true, mhWnd, this);
             mpGraphics2->setHDC(0);
         }
 
@@ -1014,7 +1014,7 @@ SalGraphics* WinSalFrame::AcquireGraphics()
             HDC hDC = GetDC( mhWnd );
             if ( hDC )
             {
-                mpGraphics = new WinSalGraphics(WinSalGraphics::WINDOW, true, mhWnd);
+                mpGraphics = new WinSalGraphics(WinSalGraphics::WINDOW, true, mhWnd, this);
                 mpGraphics->setHDC(hDC);
                 if ( pSalData->mhDitherPal )
                 {
commit c31ed7004dfb3e8e37ddeb9fddf0f015b661dd12
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Sat Nov 29 22:14:36 2014 +0000

    vcl: create a GeometryProvider interface.
    
    Implemented by both SalFrame and SalVirtualDevice, to help us to
    un-tangle code that needs to operate on resources associated with
    both of these without special cases.
    
    Change-Id: If681a002647e20c57186577fe039d4ac85bba872

diff --git a/vcl/inc/headless/svpvd.hxx b/vcl/inc/headless/svpvd.hxx
index eb6b8d1..fa9d042 100644
--- a/vcl/inc/headless/svpvd.hxx
+++ b/vcl/inc/headless/svpvd.hxx
@@ -47,6 +47,10 @@ public:
                                           ) SAL_OVERRIDE;
 
     basebmp::BitmapDeviceSharedPtr getBitmapDevice() { return m_aDevice; }
+
+    // SalGeometryProvider
+    virtual long GetWidth() const SAL_OVERRIDE { return m_aDevice.get() ? m_aDevice->getSize().getX() : 0; }
+    virtual long GetHeight() const SAL_OVERRIDE { return m_aDevice.get() ? m_aDevice->getSize().getY() : 0; }
 };
 
 #endif // INCLUDED_VCL_INC_HEADLESS_SVPVD_HXX
diff --git a/vcl/inc/opengl/x11/salvd.hxx b/vcl/inc/opengl/x11/salvd.hxx
index 7696e04..7f5f1f5 100644
--- a/vcl/inc/opengl/x11/salvd.hxx
+++ b/vcl/inc/opengl/x11/salvd.hxx
@@ -36,10 +36,12 @@ public:
                                const SystemGraphicsData *pData );
     virtual ~X11OpenGLSalVirtualDevice();
 
+    // SalGeometryProvider
+    virtual long GetWidth() const SAL_OVERRIDE { return mnWidth; }
+    virtual long GetHeight() const SAL_OVERRIDE { return mnHeight; }
+
     SalDisplay *            GetDisplay() const { return mpDisplay; }
     sal_uInt16              GetDepth() const { return mnDepth; }
-    int                     GetWidth() const { return mnWidth; }
-    int                     GetHeight() const { return mnHeight; }
     SalX11Screen            GetXScreenNumber() const { return mnXScreen; }
 
     virtual SalGraphics*    AcquireGraphics() SAL_OVERRIDE;
diff --git a/vcl/inc/salframe.hxx b/vcl/inc/salframe.hxx
index f427c24..cfc41b7 100644
--- a/vcl/inc/salframe.hxx
+++ b/vcl/inc/salframe.hxx
@@ -96,7 +96,9 @@ typedef sal_uInt64 SalExtStyle;
 
 struct SystemParentData;
 
-class VCL_PLUGIN_PUBLIC SalFrame : public vcl::DeletionNotifier
+class VCL_PLUGIN_PUBLIC SalFrame
+    : public vcl::DeletionNotifier
+    , public SalGeometryProvider
 {
     // the VCL window corresponding to this frame
     vcl::Window*            m_pWindow;
@@ -108,6 +110,11 @@ public:
 
     SalFrameGeometry        maGeometry;
 
+    // SalGeometryProvider
+    virtual long GetWidth() const SAL_OVERRIDE { return maGeometry.nWidth; }
+    virtual long GetHeight() const SAL_OVERRIDE { return maGeometry.nHeight; }
+    virtual bool IsOffScreen() const SAL_OVERRIDE { return false; }
+
     // SalGraphics or NULL, but two Graphics for all SalFrames
     // must be returned
     virtual SalGraphics*    AcquireGraphics() = 0;
diff --git a/vcl/inc/salgeom.hxx b/vcl/inc/salgeom.hxx
index 138a6d9..d54c58a 100644
--- a/vcl/inc/salgeom.hxx
+++ b/vcl/inc/salgeom.hxx
@@ -20,6 +20,8 @@
 #ifndef INCLUDED_VCL_INC_SALGEOM_HXX
 #define INCLUDED_VCL_INC_SALGEOM_HXX
 
+#include <vcl/dllapi.h>
+
 typedef struct _SalFrameGeometry {
     // screen position of upper left corner of drawable area in pixel
     long                nX, nY;
@@ -40,6 +42,16 @@ typedef struct _SalFrameGeometry {
     {}
 } SalFrameGeometry;
 
+/// Interface used to share logic on sizing between
+/// SalVirtualDevices and SalFrames
+class VCL_PLUGIN_PUBLIC SalGeometryProvider {
+public:
+    virtual ~SalGeometryProvider() {}
+    virtual long GetWidth() const = 0;
+    virtual long GetHeight() const = 0;
+    virtual bool IsOffScreen() const = 0;
+};
+
 #endif // INCLUDED_VCL_INC_SALGEOM_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/salvd.hxx b/vcl/inc/salvd.hxx
index 1397935..c07722f 100644
--- a/vcl/inc/salvd.hxx
+++ b/vcl/inc/salvd.hxx
@@ -22,15 +22,20 @@
 
 #include <basebmp/bitmapdevice.hxx>
 #include <vcl/dllapi.h>
+#include <salgeom.hxx>
 
 class SalGraphics;
 
 class VCL_PLUGIN_PUBLIC SalVirtualDevice
+        : public SalGeometryProvider
 {
 public:
     SalVirtualDevice() {}
     virtual ~SalVirtualDevice();
 
+    // SalGeometryProvider
+    virtual bool IsOffScreen() const SAL_OVERRIDE { return true; }
+
     // SalGraphics or NULL, but two Graphics for all SalVirtualDevices
     // must be returned
     virtual SalGraphics*    AcquireGraphics() = 0;
diff --git a/vcl/inc/unx/salvd.h b/vcl/inc/unx/salvd.h
index 9b520a7..0b08521 100644
--- a/vcl/inc/unx/salvd.h
+++ b/vcl/inc/unx/salvd.h
@@ -64,8 +64,6 @@ public:
     }
     Pixmap          GetDrawable() const { return hDrawable_; }
     sal_uInt16      GetDepth() const { return nDepth_; }
-    int                     GetWidth() const { return nDX_; }
-    int                     GetHeight() const { return nDY_; }
     SalX11Screen            GetXScreenNumber() const { return m_nXScreen; }
 
     virtual SalGraphics*    AcquireGraphics() SAL_OVERRIDE;
@@ -73,6 +71,10 @@ public:
 
     /// Set new size, without saving the old contents
     virtual bool        SetSize( long nNewDX, long nNewDY ) SAL_OVERRIDE;
+
+    // SalGeometryProvider
+    virtual long GetWidth() const SAL_OVERRIDE { return nDX_; }
+    virtual long GetHeight() const SAL_OVERRIDE { return nDY_; }
 };
 
 #endif // INCLUDED_VCL_INC_UNX_SALVD_H
diff --git a/vcl/inc/win/salvd.h b/vcl/inc/win/salvd.h
index 9abb46b..6ecba54 100644
--- a/vcl/inc/win/salvd.h
+++ b/vcl/inc/win/salvd.h
@@ -43,6 +43,8 @@ public:
     sal_uInt16              mnBitCount;             // BitCount (0 or 1)
     bool                    mbGraphics;             // is Graphics used
     bool                    mbForeignDC;            // uses a foreign DC instead of a bitmap
+    long                    mnWidth;
+    long                    mnHeight;
 
     WinSalVirtualDevice();
     virtual ~WinSalVirtualDevice();
@@ -52,6 +54,10 @@ public:
     virtual bool                    SetSize( long nNewDX, long nNewDY );
 
     static HBITMAP ImplCreateVirDevBitmap(HDC hDC, long nDX, long nDY, sal_uInt16 nBitCount, void **ppDummy);
+
+    // SalGeometryProvider
+    virtual long GetWidth() const SAL_OVERRIDE { return mnWidth; }
+    virtual long GetHeight() const SAL_OVERRIDE { return mnHeight; }
 };
 
 
diff --git a/vcl/opengl/x11/salvd.cxx b/vcl/opengl/x11/salvd.cxx
index 4fde8f8..7996cff 100644
--- a/vcl/opengl/x11/salvd.cxx
+++ b/vcl/opengl/x11/salvd.cxx
@@ -80,6 +80,7 @@ void X11OpenGLSalVirtualDevice::ReleaseGraphics( SalGraphics* )
     mbGraphics = false;
 }
 
+
 bool X11OpenGLSalVirtualDevice::SetSize( long nDX, long nDY )
 {
     if( !nDX ) nDX = 1;
diff --git a/vcl/unx/generic/gdi/x11cairotextrender.cxx b/vcl/unx/generic/gdi/x11cairotextrender.cxx
index 2533107..0449b98 100644
--- a/vcl/unx/generic/gdi/x11cairotextrender.cxx
+++ b/vcl/unx/generic/gdi/x11cairotextrender.cxx
@@ -96,30 +96,26 @@ void X11CairoTextRender::clipRegion(cairo_t* cr)
 
 size_t X11CairoTextRender::GetWidth() const
 {
-    if( mrParent.m_pFrame )
-        return mrParent.m_pFrame->maGeometry.nWidth;
-    else if( mrParent.m_pVDev )
-    {
-        long nWidth = 0;
-        long nHeight = 0;
-        mrParent.m_pVDev->GetSize( nWidth, nHeight );
-        return nWidth;
-    }
-    return 1;
+    SalGeometryProvider *pProvider = mrParent.m_pFrame;
+    if( !pProvider )
+        pProvider = mrParent.m_pVDev;
+
+    if( pProvider )
+        return pProvider->GetWidth();
+    else
+        return 1;
 }
 
 size_t X11CairoTextRender::GetHeight() const
 {
-    if( mrParent.m_pFrame )
-        return mrParent.m_pFrame->maGeometry.nHeight;
-    else if( mrParent.m_pVDev )
-    {
-        long nWidth = 0;
-        long nHeight = 0;
-        mrParent.m_pVDev->GetSize( nWidth, nHeight );
-        return nHeight;
-    }
-    return 1;
+    SalGeometryProvider *pProvider = mrParent.m_pFrame;
+    if( !pProvider )
+        pProvider = mrParent.m_pVDev;
+
+    if( pProvider )
+        return pProvider->GetHeight();
+    else
+        return 1;
 }
 
 void X11CairoTextRender::drawSurface(cairo_t* /*cr*/)
diff --git a/vcl/win/source/gdi/salvd.cxx b/vcl/win/source/gdi/salvd.cxx
index b5986b1..cea8a76 100644
--- a/vcl/win/source/gdi/salvd.cxx
+++ b/vcl/win/source/gdi/salvd.cxx
@@ -115,6 +115,8 @@ SalVirtualDevice* WinSalInstance::CreateVirtualDevice( SalGraphics* pSGraphics,
         }
         pVirGraphics->InitGraphics();
 
+        mnWidth = nDX;
+        mnHeight = nDY;
         pVDev->setHDC(hDC);
         pVDev->mhBmp        = hBmp;
         if( hBmp )
@@ -152,6 +154,8 @@ WinSalVirtualDevice::WinSalVirtualDevice()
     mnBitCount = 0;             // BitCount (0 or 1)
     mbGraphics = FALSE;         // is Graphics used
     mbForeignDC = FALSE;        // uses a foreign DC instead of a bitmap
+    mnWidth = 0;
+    mnHeight = 0;
 }
 
 WinSalVirtualDevice::~WinSalVirtualDevice()
commit c22d5338fad383800b35efa458561bb89b604922
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Sat Nov 29 21:42:47 2014 +0000

    vcl: remove SalVirtualDevice::GetWidth
    
    It is presumed that #i59315# is fixed already, and that this is no
    longer necessary.
    
    Change-Id: Ifb2f6550fac2481c4fec269b38d6e806753cb53e

diff --git a/vcl/headless/svpvd.cxx b/vcl/headless/svpvd.cxx
index dc280db..e2f9042 100644
--- a/vcl/headless/svpvd.cxx
+++ b/vcl/headless/svpvd.cxx
@@ -93,18 +93,6 @@ bool SvpSalVirtualDevice::SetSizeUsingBuffer( long nNewDX, long nNewDY,
     return true;
 }
 
-void SvpSalVirtualDevice::GetSize( long& rWidth, long& rHeight )
-{
-    if( m_aDevice.get() )
-    {
-        B2IVector aDevSize( m_aDevice->getSize() );
-        rWidth = aDevSize.getX();
-        rHeight = aDevSize.getY();
-    }
-    else
-        rWidth = rHeight = 0;
-}
-
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/headless/svpvd.hxx b/vcl/inc/headless/svpvd.hxx
index e69bf8f..eb6b8d1 100644
--- a/vcl/inc/headless/svpvd.hxx
+++ b/vcl/inc/headless/svpvd.hxx
@@ -45,7 +45,6 @@ public:
                                             const basebmp::RawMemorySharedArray &pBuffer,
                                             const bool bTopDown
                                           ) SAL_OVERRIDE;
-    virtual void            GetSize( long& rWidth, long& rHeight ) SAL_OVERRIDE;
 
     basebmp::BitmapDeviceSharedPtr getBitmapDevice() { return m_aDevice; }
 };
diff --git a/vcl/inc/opengl/x11/salvd.hxx b/vcl/inc/opengl/x11/salvd.hxx
index 0d7143b..7696e04 100644
--- a/vcl/inc/opengl/x11/salvd.hxx
+++ b/vcl/inc/opengl/x11/salvd.hxx
@@ -47,7 +47,6 @@ public:
 
                             // Set new size, without saving the old contents
     virtual bool            SetSize( long nNewDX, long nNewDY ) SAL_OVERRIDE;
-    virtual void            GetSize( long& rWidth, long& rHeight ) SAL_OVERRIDE;
 };
 
 #endif // INCLUDED_VCL_INC_OPENGL_X11_SALVD_H
diff --git a/vcl/inc/quartz/salvd.h b/vcl/inc/quartz/salvd.h
index f48a19a..e1d1d51 100644
--- a/vcl/inc/quartz/salvd.h
+++ b/vcl/inc/quartz/salvd.h
@@ -61,7 +61,6 @@ public:
     virtual SalGraphics*            AcquireGraphics() SAL_OVERRIDE;
     virtual void                    ReleaseGraphics( SalGraphics* pGraphics ) SAL_OVERRIDE;
     virtual bool                    SetSize( long nNewDX, long nNewDY ) SAL_OVERRIDE;
-    virtual void                       GetSize( long& rWidth, long& rHeight ) SAL_OVERRIDE;
 };
 
 #endif // INCLUDED_VCL_INC_QUARTZ_SALVD_H
diff --git a/vcl/inc/salvd.hxx b/vcl/inc/salvd.hxx
index f5a63ee..1397935 100644
--- a/vcl/inc/salvd.hxx
+++ b/vcl/inc/salvd.hxx
@@ -49,9 +49,6 @@ public:
             // pBuffer (and bTopDown).
             return SetSize( nNewDX, nNewDY );
         }
-
-    /// Get actual VDev size in pixel
-    virtual void            GetSize( long& rWidth, long& rHeight ) = 0;
 };
 
 #endif // INCLUDED_VCL_INC_SALVD_HXX
diff --git a/vcl/inc/unx/salvd.h b/vcl/inc/unx/salvd.h
index b1caa68..9b520a7 100644
--- a/vcl/inc/unx/salvd.h
+++ b/vcl/inc/unx/salvd.h
@@ -71,9 +71,8 @@ public:
     virtual SalGraphics*    AcquireGraphics() SAL_OVERRIDE;
     virtual void            ReleaseGraphics( SalGraphics* pGraphics ) SAL_OVERRIDE;
 
-                            // Set new size, without saving the old contents
+    /// Set new size, without saving the old contents
     virtual bool        SetSize( long nNewDX, long nNewDY ) SAL_OVERRIDE;
-    virtual void            GetSize( long& rWidth, long& rHeight ) SAL_OVERRIDE;
 };
 
 #endif // INCLUDED_VCL_INC_UNX_SALVD_H
diff --git a/vcl/inc/win/salvd.h b/vcl/inc/win/salvd.h
index 2c59f47..9abb46b 100644
--- a/vcl/inc/win/salvd.h
+++ b/vcl/inc/win/salvd.h
@@ -50,7 +50,6 @@ public:
     virtual SalGraphics*            AcquireGraphics();
     virtual void                    ReleaseGraphics( SalGraphics* pGraphics );
     virtual bool                    SetSize( long nNewDX, long nNewDY );
-    virtual void                    GetSize( long& rWidth, long& rHeight );
 
     static HBITMAP ImplCreateVirDevBitmap(HDC hDC, long nDX, long nDY, sal_uInt16 nBitCount, void **ppDummy);
 };
diff --git a/vcl/opengl/x11/salvd.cxx b/vcl/opengl/x11/salvd.cxx
index b7c4eea..4fde8f8 100644
--- a/vcl/opengl/x11/salvd.cxx
+++ b/vcl/opengl/x11/salvd.cxx
@@ -93,10 +93,4 @@ bool X11OpenGLSalVirtualDevice::SetSize( long nDX, long nDY )
     return true;
 }
 
-void X11OpenGLSalVirtualDevice::GetSize( long& rWidth, long& rHeight )
-{
-    rWidth  = mnWidth;
-    rHeight = mnHeight;
-}
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/quartz/salvd.cxx b/vcl/quartz/salvd.cxx
index f430908..a524c1e 100644
--- a/vcl/quartz/salvd.cxx
+++ b/vcl/quartz/salvd.cxx
@@ -277,20 +277,4 @@ bool AquaSalVirtualDevice::SetSize( long nDX, long nDY )
     return (mxLayer != NULL);
 }
 
-void AquaSalVirtualDevice::GetSize( long& rWidth, long& rHeight )
-{
-    if( mxLayer )
-    {
-        const CGSize aSize = CGLayerGetSize( mxLayer );
-        rWidth = static_cast<long>(aSize.width);
-        rHeight = static_cast<long>(aSize.height);
-        CG_TRACE( "CGLayerGetSize(" << mxLayer << ") = " << aSize << "(" << rWidth << "x" << rHeight << ")" );
-    }
-    else
-    {
-        rWidth = 0;
-        rHeight = 0;
-    }
-}
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/virdev.cxx b/vcl/source/gdi/virdev.cxx
index d783cd9..063bef1 100644
--- a/vcl/source/gdi/virdev.cxx
+++ b/vcl/source/gdi/virdev.cxx
@@ -164,12 +164,6 @@ void VirtualDevice::ImplInitVirDev( const OutputDevice* pOutDev,
     mbScreenComp    = true;
     mnAlphaDepth    = -1;
 
-    // #i59315# init vdev size from system object, when passed a
-    // SystemGraphicsData. Otherwise, output size will always
-    // incorrectly stay at (1,1)
-    if( pData && mpVirDev )
-        mpVirDev->GetSize(mnOutWidth,mnOutHeight);
-
     if( mnBitCount < 8 )
         SetAntialiasing( ANTIALIASING_DISABLE_TEXT );
 
diff --git a/vcl/unx/generic/gdi/salvd.cxx b/vcl/unx/generic/gdi/salvd.cxx
index 7967a4d..b4bcfa1 100644
--- a/vcl/unx/generic/gdi/salvd.cxx
+++ b/vcl/unx/generic/gdi/salvd.cxx
@@ -214,10 +214,4 @@ bool X11SalVirtualDevice::SetSize( long nDX, long nDY )
     return true;
 }
 
-void X11SalVirtualDevice::GetSize( long& rWidth, long& rHeight )
-{
-    rWidth  = GetWidth();
-    rHeight = GetHeight();
-}
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/win/source/gdi/salvd.cxx b/vcl/win/source/gdi/salvd.cxx
index c85133d..b5986b1 100644
--- a/vcl/win/source/gdi/salvd.cxx
+++ b/vcl/win/source/gdi/salvd.cxx
@@ -216,10 +216,4 @@ bool WinSalVirtualDevice::SetSize( long nDX, long nDY )
     }
 }
 
-void WinSalVirtualDevice::GetSize( long& rWidth, long& rHeight )
-{
-    rWidth = GetDeviceCaps( getHDC(), HORZRES );
-    rHeight= GetDeviceCaps( getHDC(), VERTRES );
-}
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 1c6843f426314637e542949e8c71542a1c33d3c9
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Fri Nov 28 16:11:25 2014 +0000

    vcl: initial outdev unit test - for VirtualDevices.
    
    Change-Id: Ia2bb1f8110c738cfbf6ff84293af115b32abeb93

diff --git a/vcl/CppunitTest_vcl_outdev.mk b/vcl/CppunitTest_vcl_outdev.mk
new file mode 100644
index 0000000..a5adcee
--- /dev/null
+++ b/vcl/CppunitTest_vcl_outdev.mk
@@ -0,0 +1,52 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,vcl_outdev))
+
+$(eval $(call gb_CppunitTest_set_include,vcl_outdev,\
+    $$(INCLUDE) \
+    -I$(SRCDIR)/vcl/inc \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,vcl_outdev, \
+	vcl/qa/cppunit/outdev \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,vcl_outdev,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_libraries,vcl_outdev, \
+	comphelper \
+	cppu \
+	cppuhelper \
+	sal \
+	svt \
+	test \
+	tl \
+	unotest \
+	vcl \
+	$(gb_UWINAPI) \
+))
+
+$(eval $(call gb_CppunitTest_use_api,vcl_outdev,\
+	udkapi \
+	offapi \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,vcl_outdev))
+$(eval $(call gb_CppunitTest_use_vcl,vcl_outdev))
+
+$(eval $(call gb_CppunitTest_use_components,vcl_outdev,\
+	configmgr/source/configmgr \
+	i18npool/util/i18npool \
+	ucb/source/core/ucb1 \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,vcl_outdev))
+
+# vim: set noet sw=4 ts=4:
diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk
index 01db2e7..329740a 100644
--- a/vcl/Module_vcl.mk
+++ b/vcl/Module_vcl.mk
@@ -101,6 +101,7 @@ $(eval $(call gb_Module_add_check_targets,vcl,\
 	CppunitTest_vcl_fontcharmap \
 	CppunitTest_vcl_complextext \
 	CppunitTest_vcl_filters_test \
+	CppunitTest_vcl_outdev \
 	CppunitTest_vcl_app_test \
 	CppunitTest_vcl_wmf_test \
 ))
diff --git a/vcl/qa/cppunit/outdev.cxx b/vcl/qa/cppunit/outdev.cxx
new file mode 100644
index 0000000..47e8dcf
--- /dev/null
+++ b/vcl/qa/cppunit/outdev.cxx
@@ -0,0 +1,67 @@
+/* -*- 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 <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+
+#include <vcl/virdev.hxx>
+#include <vcl/salbtype.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/wrkwin.hxx>
+
+class VclOutdevTest : public test::BootstrapFixture
+{
+public:
+    VclOutdevTest() : BootstrapFixture(true, false) {}
+
+    void testVirtualDevice();
+
+    CPPUNIT_TEST_SUITE(VclOutdevTest);
+    CPPUNIT_TEST(testVirtualDevice);
+    CPPUNIT_TEST_SUITE_END();
+};
+
+void VclOutdevTest::testVirtualDevice()
+{
+    VirtualDevice aVDev;
+    aVDev.SetOutputSizePixel(Size(32,32));
+    aVDev.SetBackground(Wallpaper(COL_WHITE));
+    aVDev.Erase();
+    aVDev.DrawPixel(Point(1,2),COL_GREEN);
+    aVDev.DrawPixel(Point(31,30),COL_RED);
+
+    CPPUNIT_ASSERT(aVDev.GetPixel(Point(0,0)) == COL_WHITE);
+    CPPUNIT_ASSERT(aVDev.GetPixel(Point(1,2)) == COL_GREEN);
+    CPPUNIT_ASSERT(aVDev.GetPixel(Point(31,30)) == COL_RED);
+    CPPUNIT_ASSERT(aVDev.GetPixel(Point(30,31)) == COL_WHITE);
+
+    Size aSize = aVDev.GetOutputSizePixel();
+    CPPUNIT_ASSERT(aSize == Size(32,32));
+
+    Bitmap aBmp = aVDev.GetBitmap(Point(),aSize);
+    Bitmap::ScopedReadAccess pAcc(aBmp);
+
+    // Gotcha: y and x swap for BitmapReadAccess: deep joy.
+    CPPUNIT_ASSERT(pAcc->GetPixel(0,0) == Color(COL_WHITE));
+    CPPUNIT_ASSERT(pAcc->GetPixel(2,1) == Color(COL_GREEN));
+    CPPUNIT_ASSERT(pAcc->GetPixel(30,31) == Color(COL_RED));
+    CPPUNIT_ASSERT(pAcc->GetPixel(31,30) == Color(COL_WHITE));
+
+#if 0
+    vcl::Window* pWin = new WorkWindow( (vcl::Window *)NULL );
+    CPPUNIT_ASSERT( pWin != NULL );
+    OutputDevice *pOutDev = static_cast< OutputDevice * >( pWin );
+#endif
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclOutdevTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit d6b51a87b482b69097100b9a2ce7ba85005e20ac
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Wed Nov 26 09:22:25 2014 -0500

    vcl: Use the current OpenGL context for VirtualDevice and Bitmap if possible
    
    Conflicts:
    	include/vcl/opengl/OpenGLContext.hxx
    	vcl/inc/openglgdiimpl.hxx
    	vcl/opengl/gdiimpl.cxx
    	vcl/opengl/x11/gdiimpl.cxx
    	vcl/source/opengl/OpenGLContext.cxx
    
    Change-Id: I17f6ce66fb8b5bc027d35b4016ae56c24ee0a738

diff --git a/include/vcl/opengl/OpenGLContext.hxx b/include/vcl/opengl/OpenGLContext.hxx
index 7931f4b..6d99488 100644
--- a/include/vcl/opengl/OpenGLContext.hxx
+++ b/include/vcl/opengl/OpenGLContext.hxx
@@ -55,6 +55,9 @@ class NSOpenGLView;
 #include <tools/gen.hxx>
 #include <vcl/syschild.hxx>
 
+class OpenGLFramebuffer;
+class OpenGLTexture;
+
 /// Holds the information of our new child window
 struct GLWindow
 {
@@ -175,6 +178,13 @@ public:
     bool init( HDC hDC, HWND hWnd );
 #endif
 
+    // use these methods right after setting a context to make sure drawing happens
+    // in the right FBO (default one is for onscreen painting)
+    bool               AcquireDefaultFramebuffer();
+    bool               AcquireFramebuffer( OpenGLFramebuffer* pFramebuffer );
+    OpenGLFramebuffer* AcquireFramebuffer( const OpenGLTexture& rTexture );
+    void               ReleaseFramebuffer( OpenGLFramebuffer* pFramebuffer );
+
     void makeCurrent();
     void resetCurrent();
     void swapBuffers();
@@ -226,6 +236,11 @@ private:
     bool mbPixmap; // is a pixmap instead of a window
 #endif
 
+    int mnFramebufferCount;
+    OpenGLFramebuffer* mpCurrentFramebuffer;
+    OpenGLFramebuffer* mpFirstFramebuffer;
+    OpenGLFramebuffer* mpLastFramebuffer;
+
 public:
     vcl::Region maClipRegion;
     int mnPainting;
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 3113497..737a031 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -126,6 +126,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
 	vcl/opengl/gdiimpl \
 	vcl/opengl/salbmp \
 	vcl/opengl/scale \
+	vcl/opengl/framebuffer \
 	vcl/opengl/texture \
     vcl/source/opengl/OpenGLContext \
     vcl/source/opengl/OpenGLHelper \
diff --git a/vcl/Library_vclplug_gen.mk b/vcl/Library_vclplug_gen.mk
index 76be2c1..29695e9 100644
--- a/vcl/Library_vclplug_gen.mk
+++ b/vcl/Library_vclplug_gen.mk
@@ -107,6 +107,7 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_gen,\
     vcl/unx/x11/x11sys \
     vcl/unx/x11/xlimits \
 	vcl/opengl/x11/gdiimpl \
+	vcl/opengl/x11/salvd \
 ))
 
 # ultimately we want to split the x11 dependencies out
diff --git a/vcl/inc/opengl/framebuffer.hxx b/vcl/inc/opengl/framebuffer.hxx
new file mode 100644
index 0000000..4ccc1c5
--- /dev/null
+++ b/vcl/inc/opengl/framebuffer.hxx
@@ -0,0 +1,45 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_VCL_INC_OPENGL_FRAMEBUFFER_H
+#define INCLUDED_VCL_INC_OPENGL_FRAMEBUFFER_H
+
+#include <GL/glew.h>
+#include <vcl/dllapi.h>
+
+#include <opengl/texture.hxx>
+
+class VCL_PLUGIN_PUBLIC OpenGLFramebuffer
+{
+private:
+    GLuint        mnId;
+    OpenGLTexture maAttachedTexture;
+
+public:
+    OpenGLFramebuffer();
+    virtual ~OpenGLFramebuffer();
+
+    GLuint  Id() const { return mnId; };
+
+    void    Bind();
+    void    Unbind();
+
+    bool    IsFree() const;
+    bool    IsAttached( const OpenGLTexture& rTexture ) const;
+    void    AttachTexture( const OpenGLTexture& rTexture );
+    void    DetachTexture();
+
+public:
+    OpenGLFramebuffer* mpPrevFramebuffer;
+    OpenGLFramebuffer* mpNextFramebuffer;
+};
+
+#endif // INCLUDED_VCL_INC_OPENGL_FRAMEBUFFER_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/opengl/salbmp.hxx b/vcl/inc/opengl/salbmp.hxx
index 20b0e61..bc232b1 100644
--- a/vcl/inc/opengl/salbmp.hxx
+++ b/vcl/inc/opengl/salbmp.hxx
@@ -39,6 +39,7 @@ class   BitmapPalette;
 class VCL_PLUGIN_PUBLIC OpenGLSalBitmap : public SalBitmap
 {
 private:
+    OpenGLContext*                      mpContext;
     OpenGLTexture                       maTexture;
     bool                                mbDirtyTexture;
     BitmapPalette                       maPalette;
diff --git a/vcl/inc/opengl/texture.hxx b/vcl/inc/opengl/texture.hxx
index eb003cf..ad4738a 100644
--- a/vcl/inc/opengl/texture.hxx
+++ b/vcl/inc/opengl/texture.hxx
@@ -22,6 +22,9 @@
 
 #include <GL/glew.h>
 #include <vcl/dllapi.h>
+#include <vcl/salgtype.hxx>
+
+#include <tools/gen.hxx>
 
 class ImplOpenGLTexture
 {
diff --git a/vcl/inc/opengl/win/gdiimpl.hxx b/vcl/inc/opengl/win/gdiimpl.hxx
index de25d23..da1a278 100644
--- a/vcl/inc/opengl/win/gdiimpl.hxx
+++ b/vcl/inc/opengl/win/gdiimpl.hxx
@@ -32,7 +32,7 @@ protected:
     virtual bool    IsOffscreen() const SAL_OVERRIDE;
 
     virtual OpenGLContext* CreateWinContext() SAL_OVERRIDE;
-    virtual bool CompareWinContext( OpenGLContext* pContext ) SAL_OVERRIDE;
+    virtual bool UseContext( OpenGLContext* pContext ) SAL_OVERRIDE;
     virtual OpenGLContext* CreatePixmapContext() SAL_OVERRIDE;
 
 public:
diff --git a/vcl/inc/opengl/x11/gdiimpl.hxx b/vcl/inc/opengl/x11/gdiimpl.hxx
index f5e5bfb..53ebe5b 100644
--- a/vcl/inc/opengl/x11/gdiimpl.hxx
+++ b/vcl/inc/opengl/x11/gdiimpl.hxx
@@ -31,8 +31,8 @@ protected:
     bool    IsOffscreen() const SAL_OVERRIDE;
 
     virtual OpenGLContext* CreateWinContext() SAL_OVERRIDE;
-    virtual bool CompareWinContext( OpenGLContext* pContext ) SAL_OVERRIDE;
     virtual OpenGLContext* CreatePixmapContext() SAL_OVERRIDE;
+    virtual bool UseContext( OpenGLContext* pContext ) SAL_OVERRIDE;
 
 public:
     // implementation of X11GraphicsImpl
diff --git a/vcl/inc/opengl/x11/salvd.hxx b/vcl/inc/opengl/x11/salvd.hxx
new file mode 100644
index 0000000..0d7143b
--- /dev/null
+++ b/vcl/inc/opengl/x11/salvd.hxx
@@ -0,0 +1,55 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_VCL_INC_OPENGL_X11_SALVD_H
+#define INCLUDED_VCL_INC_OPENGL_X11_SALVD_H
+
+#include <prex.h>
+#include <postx.h>
+
+#include <unx/saltype.h>
+#include <salvd.hxx>
+
+class SalDisplay;
+class X11OpenGLSalGraphics;
+
+class X11OpenGLSalVirtualDevice : public SalVirtualDevice
+{
+    SalDisplay       *mpDisplay;
+    X11SalGraphics   *mpGraphics;
+    bool              mbGraphics;         // is Graphics used
+    SalX11Screen      mnXScreen;
+    int               mnWidth;
+    int               mnHeight;
+    sal_uInt16        mnDepth;
+
+public:
+    X11OpenGLSalVirtualDevice( SalGraphics *pGraphics,
+                               long nDX, long nDY,
+                               sal_uInt16 nBitCount,
+                               const SystemGraphicsData *pData );
+    virtual ~X11OpenGLSalVirtualDevice();
+
+    SalDisplay *            GetDisplay() const { return mpDisplay; }
+    sal_uInt16              GetDepth() const { return mnDepth; }
+    int                     GetWidth() const { return mnWidth; }
+    int                     GetHeight() const { return mnHeight; }
+    SalX11Screen            GetXScreenNumber() const { return mnXScreen; }
+
+    virtual SalGraphics*    AcquireGraphics() SAL_OVERRIDE;
+    virtual void            ReleaseGraphics( SalGraphics* pGraphics ) SAL_OVERRIDE;
+
+                            // Set new size, without saving the old contents
+    virtual bool            SetSize( long nNewDX, long nNewDY ) SAL_OVERRIDE;
+    virtual void            GetSize( long& rWidth, long& rHeight ) SAL_OVERRIDE;
+};
+
+#endif // INCLUDED_VCL_INC_OPENGL_X11_SALVD_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index bc813f1..ac42527 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -23,6 +23,7 @@
 #include "salgdiimpl.hxx"
 #include <vcl/dllapi.h>
 
+#include "opengl/framebuffer.hxx"
 #include "opengl/texture.hxx"
 #include "regionband.hxx"
 
@@ -39,6 +40,7 @@ class VCL_PLUGIN_PUBLIC OpenGLSalGraphicsImpl : public SalGraphicsImpl
 protected:
 
     boost::shared_ptr<OpenGLContext> mpContext;
+    OpenGLFramebuffer* mpFramebuffer;
 
     // clipping
     vcl::Region maClipRegion;
@@ -46,7 +48,6 @@ protected:
     bool mbUseStencil;
 
     bool mbOffscreen;
-    GLuint mnFramebufferId;
     OpenGLTexture maOffscreenTex;
 
     SalColor mnLineColor;
@@ -158,23 +159,23 @@ public:
     virtual void PostDraw();
 
 protected:
-    bool AcquireContext( bool bOffscreen );
+    bool AcquireContext();
     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
+    // create a new context for offscreen rendering
     virtual OpenGLContext* CreatePixmapContext() = 0;
 
+    // check whether the given context can be used by this instance
+    virtual bool UseContext( OpenGLContext* pContext ) = 0;
+
 public:
     OpenGLSalGraphicsImpl();
     virtual ~OpenGLSalGraphicsImpl ();
 
-    OpenGLContext& GetOpenGLContext() { return *mpContext; }
+    OpenGLContext* GetOpenGLContext();
 
     virtual void Init() SAL_OVERRIDE;
 
diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx
index 2d86988..5fb496b 100644
--- a/vcl/inc/svdata.hxx
+++ b/vcl/inc/svdata.hxx
@@ -342,7 +342,7 @@ struct ImplSVData
 void        ImplInitSVData();
 void        ImplDeInitSVData();
 void        ImplDestroySVData();
-vcl::Window*     ImplGetDefaultWindow();
+VCL_PLUGIN_PUBLIC vcl::Window* ImplGetDefaultWindow();
 VCL_PLUGIN_PUBLIC ResMgr*     ImplGetResMgr();
 VCL_PLUGIN_PUBLIC ResId VclResId( sal_Int32 nId ); // throws std::bad_alloc if no res mgr
 DockingManager*     ImplGetDockingManager();
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index 8ef42ba..edf47b1 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -46,6 +46,7 @@ class X11Pixmap;
 class X11SalVirtualDevice;
 class X11SalGraphicsImpl;
 class X11OpenGLSalGraphicsImpl;
+class X11OpenGLSalVirtualDevice;
 class PspSalPrinter;
 class PspSalInfoPrinter;
 class ServerFont;
@@ -73,7 +74,7 @@ private:
 
 protected:
     SalFrame*               m_pFrame; // the SalFrame which created this Graphics or NULL
-    X11SalVirtualDevice*    m_pVDev;  // the SalVirtualDevice which created this Graphics or NULL
+    SalVirtualDevice*       m_pVDev;  // the SalVirtualDevice which created this Graphics or NULL
 
     const SalColormap*      m_pColormap;
     SalColormap    *m_pDeleteColormap;
@@ -123,6 +124,7 @@ public:
 
             void            Init( SalFrame *pFrame, Drawable aDrawable, SalX11Screen nXScreen );
             void            Init( X11SalVirtualDevice *pVirtualDevice, SalColormap* pColormap = NULL, bool bDeleteColormap = false );
+            void            Init( X11OpenGLSalVirtualDevice *pVirtualDevice );
             void            Init( class ImplSalPrinterData *pPrinter );
             void            DeInit();
 
diff --git a/vcl/inc/unx/salvd.h b/vcl/inc/unx/salvd.h
index dd84c35..b1caa68 100644
--- a/vcl/inc/unx/salvd.h
+++ b/vcl/inc/unx/salvd.h
@@ -44,19 +44,12 @@ class X11SalVirtualDevice : public SalVirtualDevice
     bool        bExternPixmap_;
 
 public:
-    X11SalVirtualDevice();
+    X11SalVirtualDevice( SalGraphics *pGraphics,
+                         long nDX, long nDY,
+                         sal_uInt16 nBitCount,
+                         const SystemGraphicsData *pData );
     virtual ~X11SalVirtualDevice();
 
-    bool            Init( SalDisplay *pDisplay,
-                              long nDX, long nDY,
-                              sal_uInt16 nBitCount,
-                              SalX11Screen nXScreen,
-                              Pixmap hDrawable = None,
-                              XRenderPictFormat* pXRenderFormat = NULL );
-    void InitGraphics( X11SalVirtualDevice *pVD )
-    {
-        pGraphics_->Init( pVD );
-    }
     Display *GetXDisplay() const
     {
         return pDisplay_->GetDisplay();
diff --git a/vcl/opengl/framebuffer.cxx b/vcl/opengl/framebuffer.cxx
new file mode 100644
index 0000000..29f9a78
--- /dev/null
+++ b/vcl/opengl/framebuffer.cxx
@@ -0,0 +1,70 @@
+/* -*- 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 <sal/log.hxx>
+
+#include <opengl/framebuffer.hxx>
+
+#include <vcl/opengl/OpenGLHelper.hxx>
+
+OpenGLFramebuffer::OpenGLFramebuffer() :
+    mnId( 0 ),
+    mpPrevFramebuffer( NULL ),
+    mpNextFramebuffer( NULL )
+{
+    glGenFramebuffers( 1, &mnId );
+    SAL_INFO( "vcl.opengl", "Created framebuffer " << (int)mnId );
+}
+
+OpenGLFramebuffer::~OpenGLFramebuffer()
+{
+    glDeleteFramebuffers( 1, &mnId );
+}
+
+void OpenGLFramebuffer::Bind()
+{
+    glBindFramebuffer( GL_FRAMEBUFFER, mnId );
+    SAL_INFO( "vcl.opengl", "Binding framebuffer " << (int)mnId );
+    CHECK_GL_ERROR();
+}
+
+void OpenGLFramebuffer::Unbind()
+{
+    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+    SAL_INFO( "vcl.opengl", "Binding default framebuffer" );
+    CHECK_GL_ERROR();
+}
+
+bool OpenGLFramebuffer::IsFree() const
+{
+    return (!maAttachedTexture);
+}
+
+bool OpenGLFramebuffer::IsAttached( const OpenGLTexture& rTexture ) const
+{
+    return ( maAttachedTexture == rTexture );
+}
+
+void OpenGLFramebuffer::AttachTexture( const OpenGLTexture& rTexture )
+{
+    SAL_INFO( "vcl.opengl", "Attaching texture " << rTexture.Id() << " to framebuffer " << (int)mnId );
+    maAttachedTexture = rTexture;
+    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                            maAttachedTexture.Id(), 0 );
+    CHECK_GL_ERROR();
+}
+
+void OpenGLFramebuffer::DetachTexture()
+{
+    maAttachedTexture = OpenGLTexture();
+    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0 );
+    CHECK_GL_ERROR();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index cff4a0b..beae9dd 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -65,10 +65,10 @@
 
 OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl()
     : mpContext(0)
+    , mpFramebuffer(NULL)
     , mbUseScissor(false)
     , mbUseStencil(false)
     , mbOffscreen(false)
-    , mnFramebufferId(0)
     , mnLineColor(SALCOLOR_NONE)
     , mnFillColor(SALCOLOR_NONE)
     , mnSolidProgram(0)
@@ -111,27 +111,30 @@ OpenGLSalGraphicsImpl::~OpenGLSalGraphicsImpl()
 {
 }
 
-bool OpenGLSalGraphicsImpl::AcquireContext( bool bOffscreen )
+OpenGLContext* OpenGLSalGraphicsImpl::GetOpenGLContext()
+{
+    if( !mpContext )
+        AcquireContext();
+    return mpContext.get();
+}
+
+bool OpenGLSalGraphicsImpl::AcquireContext( )
 {
     ImplSVData* pSVData = ImplGetSVData();
 
-    if( bOffscreen )
-    {
-        mpContext.reset(CreatePixmapContext());
-        return (mpContext.get() != NULL);
-    }
+    mpContext.reset();
 
     OpenGLContext* pContext = pSVData->maGDIData.mpLastContext;
     while( pContext )
     {
         // check if this context can be used by this SalGraphicsImpl instance
-        if( CompareWinContext( pContext )  )
+        if( UseContext( pContext )  )
             break;
         pContext = pContext->mpPrevContext;
     }
 
     if (!pContext)
-        pContext =CreateWinContext();
+        pContext = mbOffscreen ? CreatePixmapContext() : CreateWinContext();
 
     mpContext.reset(pContext);
     return (mpContext != nullptr);
@@ -145,68 +148,41 @@ bool OpenGLSalGraphicsImpl::ReleaseContext()
 
 void OpenGLSalGraphicsImpl::Init()
 {
-    const bool bOffscreen = IsOffscreen();
+    mbOffscreen = IsOffscreen();
 
     // check if we can simply re-use the same context
     if( mpContext )
     {
-        if( bOffscreen != mbOffscreen || ( !mbOffscreen && CompareWinContext( mpContext.get() ) ) )
+        if( !UseContext( mpContext.get() ) )
             ReleaseContext();
     }
 
-    if( !mpContext && !AcquireContext( bOffscreen ) )
+    // reset the offscreen texture
+    if( !mbOffscreen ||
+        maOffscreenTex.GetWidth()  != GetWidth() ||
+        maOffscreenTex.GetHeight() != GetHeight() )
     {
-        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();
+        maOffscreenTex = OpenGLTexture();
     }
 }
 
 void OpenGLSalGraphicsImpl::PreDraw()
 {
-    assert( mpContext && mpContext->isInitialized() );
+    if( !mpContext && !AcquireContext() )
+    {
+        SAL_WARN( "vcl.opengl", "Couldn't acquire context" );
+        return;
+    }
 
     mpContext->makeCurrent();
-    // TODO: lfrb: make sure the render target has the right size
-    if( mbOffscreen )
-        CheckOffscreenTexture();
+    CHECK_GL_ERROR();
+
+    if( !mbOffscreen )
+        mpContext->AcquireDefaultFramebuffer();
     else
-        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+        CheckOffscreenTexture();
     CHECK_GL_ERROR();
+
     glViewport( 0, 0, GetWidth(), GetHeight() );
     ImplInitClipRegion();
 
@@ -215,15 +191,16 @@ void OpenGLSalGraphicsImpl::PreDraw()
 
 void OpenGLSalGraphicsImpl::PostDraw()
 {
-    if( mbOffscreen )
-        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-    else if( mpContext->mnPainting == 0 )
+    if( !mbOffscreen && mpContext->mnPainting == 0 )
         glFlush();
     if( mbUseScissor )
         glDisable( GL_SCISSOR_TEST );
     if( mbUseStencil )
         glDisable( GL_STENCIL_TEST );
 
+    mpContext->ReleaseFramebuffer( mpFramebuffer );
+    mpFramebuffer = NULL;
+
     CHECK_GL_ERROR();
 }
 
@@ -279,6 +256,8 @@ void OpenGLSalGraphicsImpl::ImplInitClipRegion()
         glStencilFunc( GL_EQUAL, 1, 0x1 );
         glEnable( GL_STENCIL_TEST );
     }
+
+    CHECK_GL_ERROR();
 }
 
 bool OpenGLSalGraphicsImpl::setClipRegion( const vcl::Region& rClip )
@@ -371,26 +350,25 @@ void OpenGLSalGraphicsImpl::SetROPFillColor( SalROPColor /*nROPColor*/ )
 
 bool OpenGLSalGraphicsImpl::CheckOffscreenTexture()
 {
-    glBindFramebuffer( GL_FRAMEBUFFER, mnFramebufferId );
+    if( !maOffscreenTex )
+        maOffscreenTex = OpenGLTexture( GetWidth(), GetHeight() );
 
-    if( maOffscreenTex.IsUnique() )
+    if( !maOffscreenTex.IsUnique() )
     {
-        GLenum nStatus = glCheckFramebufferStatus( GL_FRAMEBUFFER );
-        if( nStatus != GL_FRAMEBUFFER_COMPLETE )
-            SAL_WARN( "vcl.opengl", "Incomplete framebuffer " << nStatus );
-        return true;
-    }
-
-    GLfloat fWidth = GetWidth();
-    GLfloat fHeight = GetHeight();
-    SalTwoRect aPosAry(0, 0, fWidth, fHeight, 0,0, fWidth, fHeight);
+        GLfloat fWidth = GetWidth();
+        GLfloat fHeight = GetHeight();
+        SalTwoRect aPosAry(0, 0, fWidth, fHeight, 0,0, fWidth, fHeight);
 
-    // TODO: improve performance: 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 );
-    maOffscreenTex = aNewTex;
+        // TODO: lfrb: User GL_ARB_copy_image?
+        OpenGLTexture aNewTex = OpenGLTexture( GetWidth(), GetHeight() );
+        mpFramebuffer = mpContext->AcquireFramebuffer( aNewTex );
+        DrawTexture( maOffscreenTex, aPosAry );
+        maOffscreenTex = aNewTex;
+    }
+    else
+    {
+        mpFramebuffer = mpContext->AcquireFramebuffer( maOffscreenTex );
+    }
 
     CHECK_GL_ERROR();
     return true;
@@ -1895,13 +1873,17 @@ bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly,
 
 void OpenGLSalGraphicsImpl::beginPaint()
 {
-    SAL_INFO( "vcl.opengl", "BEGIN PAINT " << this );
+    if( !mpContext && !AcquireContext() )
+        return;
+
     mpContext->mnPainting++;
 }
 
 void OpenGLSalGraphicsImpl::endPaint()
 {
-    SAL_INFO( "vcl.opengl", "END PAINT " << this );
+    if( !mpContext && !AcquireContext() )
+        return;
+
     mpContext->mnPainting--;
     assert( mpContext->mnPainting >= 0 );
     if( mpContext->mnPainting == 0 && !mbOffscreen )
diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx
index 7a1af0d..6fdb2af 100644
--- a/vcl/opengl/salbmp.cxx
+++ b/vcl/opengl/salbmp.cxx
@@ -35,7 +35,8 @@ static bool isValidBitCount( sal_uInt16 nBitCount )
 }
 
 OpenGLSalBitmap::OpenGLSalBitmap()
-: mbDirtyTexture(true)
+: mpContext(NULL)
+, mbDirtyTexture(true)
 , mnBits(0)
 , mnBytesPerRow(0)
 , mnWidth(0)
@@ -472,10 +473,14 @@ OpenGLContext* OpenGLSalBitmap::GetBitmapContext() const
 
 void OpenGLSalBitmap::makeCurrent()
 {
-    // Always use the default window's context for bitmap
-    OpenGLContext* pContext = GetBitmapContext();
-    assert(pContext && "Couldn't get default OpenGL context provider");
-    pContext->makeCurrent();
+    ImplSVData* pSVData = ImplGetSVData();
+
+    // TODO: make sure we can really use the last used context
+    mpContext = pSVData->maGDIData.mpLastContext;
+    if( !mpContext )
+        mpContext = GetBitmapContext();
+    assert(mpContext && "Couldn't get an OpenGL context");
+    mpContext->makeCurrent();
 }
 
 BitmapBuffer* OpenGLSalBitmap::AcquireBuffer( bool /*bReadOnly*/ )
@@ -490,8 +495,6 @@ BitmapBuffer* OpenGLSalBitmap::AcquireBuffer( bool /*bReadOnly*/ )
 
     if( !maPendingOps.empty() )
     {
-        makeCurrent();
-
         SAL_INFO( "vcl.opengl", "** Creating texture and reading it back immediatly" );
         if( !CreateTexture() || !AllocateUserData() || !ReadTexture() )
             return NULL;
diff --git a/vcl/opengl/scale.cxx b/vcl/opengl/scale.cxx
index 9c52cc2..d396652 100644
--- a/vcl/opengl/scale.cxx
+++ b/vcl/opengl/scale.cxx
@@ -86,8 +86,8 @@ bool OpenGLSalBitmap::ImplScaleFilter(
     const double& rScaleY,
     GLenum        nFilter )
 {
+    OpenGLFramebuffer* pFramebuffer;
     GLuint nProgram;
-    GLuint nFramebufferId;
     GLenum nOldFilter;
     int nNewWidth( mnWidth * rScaleX );
     int nNewHeight( mnHeight * rScaleY );
@@ -96,15 +96,13 @@ bool OpenGLSalBitmap::ImplScaleFilter(
     if( nProgram == 0 )
         return false;
 
-    glGenFramebuffers( 1, &nFramebufferId );
-    glBindFramebuffer( GL_FRAMEBUFFER, nFramebufferId );
-    glUseProgram( nProgram );
-    glUniform1i( mnTexSamplerUniform, 0 );
-
     OpenGLTexture aNewTex = OpenGLTexture( nNewWidth, nNewHeight );
-    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, aNewTex.Id(), 0 );
+    pFramebuffer = mpContext->AcquireFramebuffer( aNewTex );
 
-    glViewport( 0, 0, nNewWidth, nNewHeight );
+    glUseProgram( nProgram );
+    glUniform1i( mnTexSamplerUniform, 0 );
+    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
+    glClear( GL_COLOR_BUFFER_BIT );
     maTexture.Bind();
     nOldFilter = maTexture.GetFilter();
     maTexture.SetFilter( nFilter );
@@ -113,8 +111,7 @@ bool OpenGLSalBitmap::ImplScaleFilter(
     maTexture.Unbind();
 
     glUseProgram( 0 );
-    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-    glDeleteFramebuffers( 1, &nFramebufferId );
+    mpContext->ReleaseFramebuffer( pFramebuffer );
 
     mnWidth = nNewWidth;
     mnHeight = nNewHeight;
@@ -167,8 +164,8 @@ bool OpenGLSalBitmap::ImplScaleConvolution(
     const double& rScaleY,
     const Kernel& aKernel )
 {
+    OpenGLFramebuffer* pFramebuffer;
     GLfloat* pWeights( 0 );
-    GLuint nFramebufferId;
     GLuint nProgram;
     sal_uInt32 nKernelSize;
     GLfloat aOffsets[32];
@@ -181,8 +178,6 @@ bool OpenGLSalBitmap::ImplScaleConvolution(
     if( nProgram == 0 )
         return false;
 
-    glGenFramebuffers( 1, &nFramebufferId );
-    glBindFramebuffer( GL_FRAMEBUFFER, nFramebufferId );
     glUseProgram( nProgram );
     glUniform1i( mnConvSamplerUniform, 0 );
     CHECK_GL_ERROR();
@@ -191,8 +186,7 @@ bool OpenGLSalBitmap::ImplScaleConvolution(
     if( mnWidth != nNewWidth )
     {
         OpenGLTexture aScratchTex = OpenGLTexture( nNewWidth, mnHeight );
-        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, aScratchTex.Id(), 0 );
-        CHECK_GL_ERROR();
+        pFramebuffer = mpContext->AcquireFramebuffer( aScratchTex );
 
         for( sal_uInt32 i = 0; i < 16; i++ )
         {
@@ -205,19 +199,19 @@ bool OpenGLSalBitmap::ImplScaleConvolution(
         glUniform2fv( mnConvOffsetsUniform, 16, aOffsets );
         CHECK_GL_ERROR();
 
-        glViewport( 0, 0, nNewWidth, mnHeight );
         maTexture.Bind();
         maTexture.Draw();
         maTexture.Unbind();
 
         maTexture = aScratchTex;
+        mpContext->ReleaseFramebuffer( pFramebuffer );
     }
 
     // vertical scaling in final texture
     if( mnHeight != nNewHeight )
     {
         OpenGLTexture aScratchTex = OpenGLTexture( nNewWidth, nNewHeight );
-        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, aScratchTex.Id(), 0 );
+        pFramebuffer = mpContext->AcquireFramebuffer( aScratchTex );
 
         for( sal_uInt32 i = 0; i < 16; i++ )
         {
@@ -229,17 +223,15 @@ bool OpenGLSalBitmap::ImplScaleConvolution(
         glUniform2fv( mnConvOffsetsUniform, 16, aOffsets );
         CHECK_GL_ERROR();
 
-        glViewport( 0, 0, nNewWidth, nNewHeight );
         maTexture.Bind();
         maTexture.Draw();
         maTexture.Unbind();
 
         maTexture = aScratchTex;
+        mpContext->ReleaseFramebuffer( pFramebuffer );
     }
 
     glUseProgram( 0 );
-    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-    glDeleteFramebuffers( 1, &nFramebufferId );
 
     mnWidth = nNewWidth;
     mnHeight = nNewHeight;
@@ -314,7 +306,8 @@ bool OpenGLSalBitmap::Scale( const double& rScaleX, const double& rScaleY, sal_u
         nScaleFlag == BMP_SCALE_LANCZOS )
     {
         //TODO maUserBuffer.reset();
-        if( GetBitmapContext() == NULL )
+        makeCurrent();
+        if( mpContext == NULL )
         {
             SAL_INFO( "vcl.opengl", "Add ScaleOp to pending operations" );
             maPendingOps.push_back( new ScaleOp( this, rScaleX, rScaleY, nScaleFlag ) );
diff --git a/vcl/opengl/win/gdiimpl.cxx b/vcl/opengl/win/gdiimpl.cxx
index 0815927..2bd31bf 100644
--- a/vcl/opengl/win/gdiimpl.cxx
+++ b/vcl/opengl/win/gdiimpl.cxx
@@ -82,7 +82,7 @@ OpenGLContext* WinOpenGLSalGraphicsImpl::CreateWinContext()
     return pContext;
 }
 
-bool WinOpenGLSalGraphicsImpl::CompareWinContext( OpenGLContext* pContext )
+bool WinOpenGLSalGraphicsImpl::UseContext( OpenGLContext* pContext )
 {
     if( !pContext || !pContext->isInitialized() )
         return false;
diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx
index 80db3a9..07b8abf 100644
--- a/vcl/opengl/x11/gdiimpl.cxx
+++ b/vcl/opengl/x11/gdiimpl.cxx
@@ -7,16 +7,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#include "vcl/salbtype.hxx"
+#include <vcl/salbtype.hxx>
 
-#include "unx/pixmap.hxx"
-#include "unx/saldisp.hxx"
-#include "unx/salframe.h"
-#include "unx/salgdi.h"
-#include "unx/salvd.h"
+#include <svdata.hxx>
 
-#include "opengl/texture.hxx"
-#include "opengl/x11/gdiimpl.hxx"
+#include <unx/pixmap.hxx>
+#include <unx/saldisp.hxx>
+#include <unx/salframe.h>
+#include <unx/salgdi.h>
+#include <unx/salvd.h>
+#include <unx/x11/xlimits.hxx>
+
+#include <opengl/texture.hxx>
+#include <opengl/x11/gdiimpl.hxx>
+#include <opengl/x11/salvd.hxx>
 
 #include <vcl/opengl/OpenGLContext.hxx>
 #include <vcl/opengl/OpenGLHelper.hxx>
@@ -36,12 +40,7 @@ GLfloat X11OpenGLSalGraphicsImpl::GetWidth() const
     if( mrParent.m_pFrame )
         return mrParent.m_pFrame->maGeometry.nWidth;
     else if( mrParent.m_pVDev )
-    {
-        long nWidth = 0;
-        long nHeight = 0;
-        mrParent.m_pVDev->GetSize( nWidth, nHeight );
-        return nWidth;
-    }
+        return static_cast< X11OpenGLSalVirtualDevice* >(mrParent.m_pVDev)->GetWidth();
     return 1;
 }
 
@@ -50,12 +49,7 @@ GLfloat X11OpenGLSalGraphicsImpl::GetHeight() const
     if( mrParent.m_pFrame )
         return mrParent.m_pFrame->maGeometry.nHeight;
     else if( mrParent.m_pVDev )
-    {
-        long nWidth = 0;
-        long nHeight = 0;
-        mrParent.m_pVDev->GetSize( nWidth, nHeight );
-        return nHeight;
-    }
+        return static_cast< X11OpenGLSalVirtualDevice* >(mrParent.m_pVDev)->GetHeight();
     return 1;
 }
 
@@ -79,6 +73,7 @@ OpenGLContext* X11OpenGLSalGraphicsImpl::CreateWinContext()
 
     if( !pProvider )
         return NULL;
+
     Window aWin = pProvider->GetX11Window();
     OpenGLContext* pContext = new OpenGLContext();
     pContext->init( mrParent.GetXDisplay(), aWin,
@@ -86,24 +81,27 @@ OpenGLContext* X11OpenGLSalGraphicsImpl::CreateWinContext()
     return pContext;
 }
 
-bool X11OpenGLSalGraphicsImpl::CompareWinContext( OpenGLContext* pContext )
+OpenGLContext* X11OpenGLSalGraphicsImpl::CreatePixmapContext()
 {
-    X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame);
+    X11OpenGLSalVirtualDevice* pVDev = dynamic_cast<X11OpenGLSalVirtualDevice*>(mrParent.m_pVDev);
 
-    if( !pProvider || !pContext->isInitialized() )
-        return false;
-    return ( pContext->getOpenGLWindow().win == pProvider->GetX11Window() );
+    if( pVDev == NULL )
+        return NULL;
+
+    return ImplGetDefaultWindow()->GetGraphics()->GetOpenGLContext();
 }
 
-OpenGLContext* X11OpenGLSalGraphicsImpl::CreatePixmapContext()
+bool X11OpenGLSalGraphicsImpl::UseContext( OpenGLContext* pContext )
 {
-    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;
+    X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame);
+
+    if( !pContext->isInitialized() )
+        return false;
+
+    if( !pProvider )
+        return ( pContext->getOpenGLWindow().win != None );
+    else
+        return ( pContext->getOpenGLWindow().win == pProvider->GetX11Window() );
 }
 
 void X11OpenGLSalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics )
diff --git a/vcl/opengl/x11/salvd.cxx b/vcl/opengl/x11/salvd.cxx
new file mode 100644
index 0000000..b7c4eea
--- /dev/null
+++ b/vcl/opengl/x11/salvd.cxx
@@ -0,0 +1,102 @@
+/* -*- 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 <vcl/sysdata.hxx>
+
+#include <unx/salunx.h>
+#include <unx/saldata.hxx>
+#include <unx/saldisp.hxx>
+#include <unx/salgdi.h>
+#include <unx/salvd.h>
+
+#include <opengl/x11/salvd.hxx>
+
+void X11SalGraphics::Init( X11OpenGLSalVirtualDevice *pDevice )
+{
+    SalDisplay *pDisplay  = pDevice->GetDisplay();
+
+    m_nXScreen = pDevice->GetXScreenNumber();
+    m_pColormap = &pDisplay->GetColormap( m_nXScreen );
+
+    m_pVDev      = pDevice;
+    m_pFrame     = NULL;
+
+    bWindow_     = pDisplay->IsDisplay();
+    bVirDev_     = true;
+
+    mpImpl->Init();
+}
+
+X11OpenGLSalVirtualDevice::X11OpenGLSalVirtualDevice( SalGraphics* pGraphics,
+                                                      long nDX, long nDY,
+                                                      sal_uInt16 nBitCount,
+                                                      const SystemGraphicsData *pData ) :
+    mbGraphics( false ),
+    mnXScreen( 0 )
+{
+    // TODO Do we really need the requested bit count?
+    if( !nBitCount && pGraphics )
+        nBitCount = pGraphics->GetBitCount();
+
+    // TODO Check where a VirtualDevice is created from SystemGraphicsData
+    assert( pData == NULL ); (void)pData;
+
+    mpDisplay  = GetGenericData()->GetSalDisplay();
+    mnDepth    = nBitCount;
+    mnXScreen  = pGraphics ? static_cast<X11SalGraphics*>(pGraphics)->GetScreenNumber() :
+                             GetGenericData()->GetSalDisplay()->GetDefaultXScreen();
+    mnWidth    = nDX;
+    mnHeight   = nDY;
+    mpGraphics = new X11SalGraphics();
+    mpGraphics->SetLayout( 0 );
+    mpGraphics->Init( this );
+}
+
+X11OpenGLSalVirtualDevice::~X11OpenGLSalVirtualDevice()
+{
+    if( mpGraphics )
+        delete mpGraphics;
+}
+
+SalGraphics* X11OpenGLSalVirtualDevice::AcquireGraphics()
+{
+    if( mbGraphics )
+        return NULL;
+
+    if( mpGraphics )
+        mbGraphics = true;
+
+    return mpGraphics;
+}
+
+void X11OpenGLSalVirtualDevice::ReleaseGraphics( SalGraphics* )
+{
+    mbGraphics = false;
+}
+
+bool X11OpenGLSalVirtualDevice::SetSize( long nDX, long nDY )
+{
+    if( !nDX ) nDX = 1;
+    if( !nDY ) nDY = 1;
+
+    mnWidth = nDX;
+    mnHeight = nDY;
+    if( mpGraphics )
+        mpGraphics->Init( this );
+
+    return true;
+}
+
+void X11OpenGLSalVirtualDevice::GetSize( long& rWidth, long& rHeight )
+{
+    rWidth  = mnWidth;
+    rHeight = mnHeight;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/salgdilayout.cxx b/vcl/source/gdi/salgdilayout.cxx
index dc419a0..88a0abc 100644
--- a/vcl/source/gdi/salgdilayout.cxx
+++ b/vcl/source/gdi/salgdilayout.cxx
@@ -81,7 +81,7 @@ OpenGLContext* SalGraphics::GetOpenGLContext() const
 {
     OpenGLSalGraphicsImpl *pImpl = dynamic_cast<OpenGLSalGraphicsImpl*>(GetImpl());
     if (pImpl)
-        return &pImpl->GetOpenGLContext();
+        return pImpl->GetOpenGLContext();
 
     return NULL;
 }
diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx
index 4c64f63..84d6bbe 100644
--- a/vcl/source/opengl/OpenGLContext.cxx
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -29,6 +29,9 @@
 
 #include "svdata.hxx"
 
+#include <opengl/framebuffer.hxx>
+#include <opengl/texture.hxx>
+
 using namespace com::sun::star;
 
 // TODO use rtl::Static instead of 'static'
@@ -52,6 +55,9 @@ OpenGLContext::OpenGLContext():
     mbRequestLegacyContext(false),
     mbUseDoubleBufferedRendering(true),
     mbRequestVirtualDevice(false),
+    mpCurrentFramebuffer(NULL),
+    mpFirstFramebuffer(NULL),
+    mpLastFramebuffer(NULL),
     mnPainting(0),
     mpPrevContext(NULL),
     mpNextContext(NULL)
@@ -73,6 +79,15 @@ OpenGLContext::OpenGLContext():
 
 OpenGLContext::~OpenGLContext()
 {
+    ImplSVData* pSVData = ImplGetSVData();
+    if( mpPrevContext )
+        mpPrevContext->mpNextContext = mpNextContext;
+    else
+        pSVData->maGDIData.mpFirstContext = mpNextContext;
+    if( mpNextContext )
+        mpNextContext->mpPrevContext = mpPrevContext;
+    else
+        pSVData->maGDIData.mpLastContext = mpPrevContext;
 #if defined( WNT )
     if (m_aGLWin.hRC)
     {
@@ -102,16 +117,6 @@ OpenGLContext::~OpenGLContext()
             glXDestroyPixmap(m_aGLWin.dpy, m_aGLWin.glPix);
     }
 #endif
-
-    ImplSVData* pSVData = ImplGetSVData();
-    if( mpPrevContext )
-        mpPrevContext->mpNextContext = mpNextContext;
-    else
-        pSVData->maGDIData.mpFirstContext = mpNextContext;
-    if( mpNextContext )
-        mpNextContext->mpPrevContext = mpPrevContext;
-    else
-        pSVData->maGDIData.mpLastContext = mpPrevContext;
 }
 
 void OpenGLContext::requestLegacyContext()
@@ -565,6 +570,7 @@ void initOpenGLFunctionPointers()
     glXGetVisualFromFBConfig = (XVisualInfo*(*)(Display *dpy, GLXFBConfig config))glXGetProcAddressARB((GLubyte*)"glXGetVisualFromFBConfig");    // try to find a visual for the current set of attributes
     glXGetFBConfigAttrib = (int(*)(Display *dpy, GLXFBConfig config, int attribute, int* value))glXGetProcAddressARB((GLubyte*)"glXGetFBConfigAttrib");
     glXCreateContextAttribsARB = (GLXContext(*) (Display*, GLXFBConfig, GLXContext, Bool, const int*)) glXGetProcAddressARB((const GLubyte *) "glXCreateContextAttribsARB");;
+    glXCreatePixmap = (GLXPixmap(*) (Display*, GLXFBConfig, Pixmap, const int*)) glXGetProcAddressARB((const GLubyte *) "glXCreatePixmap");;
 }
 
 Visual* getVisual(Display* dpy, Window win)
@@ -655,6 +661,8 @@ bool OpenGLContext::init(Display* dpy, Pixmap pix, unsigned int width, unsigned
     if (!dpy)
         return false;
 
+    initOpenGLFunctionPointers();
+
     SAL_INFO("vcl.opengl", "init with pixmap");
     m_aGLWin.dpy = dpy;
     m_aGLWin.Width = width;
@@ -673,8 +681,6 @@ bool OpenGLContext::init(Display* dpy, Pixmap pix, unsigned int width, unsigned
 
     mbPixmap = true;
 
-    initOpenGLFunctionPointers();
-
     return ImplInit();
 }
 
@@ -873,7 +879,7 @@ bool OpenGLContext::ImplInit()
     }
 
     HGLRC hTempRC = wglCreateContext(m_aGLWin.hDC);
-    if (m_aGLWin.hRC == NULL)
+    if (hTempRC == NULL)
     {
         ImplWriteLastError(GetLastError(), "wglCreateContext in OpenGLContext::ImplInit");
         SAL_WARN("vcl.opengl", "wglCreateContext failed");
@@ -1213,13 +1219,32 @@ void OpenGLContext::makeCurrent()
     // nothing
 #elif defined( UNX )
     GLXDrawable nDrawable = mbPixmap ? m_aGLWin.glPix : m_aGLWin.win;
+    static int nSwitch = 0;
     if (glXGetCurrentContext() == m_aGLWin.ctx &&
         glXGetCurrentDrawable() == nDrawable)
     {
-        SAL_INFO("vcl.opengl", "OpenGLContext::makeCurrent(): Avoid setting the same context");
+        ; // no-op
     }
     else if (!glXMakeCurrent( m_aGLWin.dpy, nDrawable, m_aGLWin.ctx ))
         SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent failed on drawable " << nDrawable << " pixmap? " << mbPixmap);
+    else
+    {
+        SAL_INFO("vcl.opengl", "******* CONTEXT SWITCH " << ++nSwitch << " *********");
+        ImplSVData* pSVData = ImplGetSVData();
+        if( mpNextContext )
+        {
+            if( mpPrevContext )
+                mpPrevContext->mpNextContext = mpNextContext;
+            else
+                pSVData->maGDIData.mpFirstContext = mpNextContext;
+            mpNextContext->mpPrevContext = mpPrevContext;
+
+            mpPrevContext = pSVData->maGDIData.mpLastContext;
+            mpNextContext = NULL;
+            pSVData->maGDIData.mpLastContext->mpNextContext = this;
+            pSVData->maGDIData.mpLastContext = this;
+        }
+    }
 #endif
 }
 
@@ -1292,4 +1317,78 @@ NSOpenGLView* OpenGLContext::getOpenGLView()
 }
 #endif
 
+bool OpenGLContext::AcquireFramebuffer( OpenGLFramebuffer* pFramebuffer )
+{
+    if( pFramebuffer != mpCurrentFramebuffer )
+    {
+        // release the attached texture so it's available from the other contexts
+        //if( mpCurrentFramebuffer )
+        //    mpCurrentFramebuffer->DetachTexture();
+
+        if( pFramebuffer )
+            pFramebuffer->Bind();
+        else
+            mpCurrentFramebuffer->Unbind();
+        mpCurrentFramebuffer = pFramebuffer;
+    }
+
+    return true;
+}
+
+bool OpenGLContext::AcquireDefaultFramebuffer()
+{
+    return AcquireFramebuffer( NULL );
+}
+
+OpenGLFramebuffer* OpenGLContext::AcquireFramebuffer( const OpenGLTexture& rTexture )
+{
+    OpenGLFramebuffer* pFramebuffer = NULL;
+    OpenGLFramebuffer* pFreeFramebuffer = NULL;
+
+    // check if there is already a framebuffer attached to that texture
+    pFramebuffer = mpLastFramebuffer;
+    while( pFramebuffer )
+    {
+        if( pFramebuffer->IsAttached( rTexture ) )
+            break;
+        if( !pFreeFramebuffer && pFramebuffer->IsFree() )
+            pFreeFramebuffer = pFramebuffer;
+        pFramebuffer = pFramebuffer->mpPrevFramebuffer;
+    }
+
+    // else use the first free framebuffer
+    if( !pFramebuffer && pFreeFramebuffer )
+        pFramebuffer = pFreeFramebuffer;
+
+    // if there isn't any free one, create a new one
+    if( !pFramebuffer )
+    {
+        pFramebuffer = new OpenGLFramebuffer();
+        if( mpLastFramebuffer )
+        {
+            pFramebuffer->mpPrevFramebuffer = mpLastFramebuffer;
+            mpLastFramebuffer->mpNextFramebuffer = pFramebuffer;
+            mpLastFramebuffer = pFramebuffer;
+        }
+        else
+        {
+            mpFirstFramebuffer = pFramebuffer;
+            mpLastFramebuffer = pFramebuffer;
+        }
+    }
+
+    AcquireFramebuffer( pFramebuffer );
+    if( pFramebuffer->IsFree() )
+        pFramebuffer->AttachTexture( rTexture );
+    glViewport( 0, 0, rTexture.GetWidth(), rTexture.GetHeight() );
+
+    return pFramebuffer;
+}
+
+void OpenGLContext::ReleaseFramebuffer( OpenGLFramebuffer* pFramebuffer )
+{
+    if( pFramebuffer )
+        pFramebuffer->DetachTexture();
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/generic/gdi/gdiimpl.cxx b/vcl/unx/generic/gdi/gdiimpl.cxx
index 46865d0..f2f909c 100644
--- a/vcl/unx/generic/gdi/gdiimpl.cxx
+++ b/vcl/unx/generic/gdi/gdiimpl.cxx
@@ -728,7 +728,7 @@ void X11SalGraphicsImpl::drawMaskedBitmap( const SalTwoRect& rPosAry,
     // bitdepth to create pixmaps for, otherwise, XCopyArea will
     // refuse to work.
     const sal_uInt16    nDepth( mrParent.m_pVDev ?
-                            mrParent.m_pVDev->GetDepth() :
+                            static_cast< X11SalVirtualDevice* >(mrParent.m_pVDev)->GetDepth() :
                             pSalDisp->GetVisual( mrParent.m_nXScreen ).GetDepth() );
     Pixmap          aFG( limitXCreatePixmap( pXDisp, aDrawable, rPosAry.mnDestWidth,
                                         rPosAry.mnDestHeight, nDepth ) );
@@ -850,7 +850,7 @@ bool X11SalGraphicsImpl::drawAlphaBitmap( const SalTwoRect& rTR,
     Display* pXDisplay = pSalDisp->GetDisplay();
 
     // create source Picture
-    int nDepth = mrParent.m_pVDev ? mrParent.m_pVDev->GetDepth() : rSalVis.GetDepth();
+    int nDepth = mrParent.m_pVDev ? static_cast< X11SalVirtualDevice* >(mrParent.m_pVDev)->GetDepth() : rSalVis.GetDepth();
     const X11SalBitmap& rSrcX11Bmp = static_cast<const X11SalBitmap&>( rSrcBitmap );
     ImplSalDDB* pSrcDDB = rSrcX11Bmp.ImplGetDDB( mrParent.hDrawable_, mrParent.m_nXScreen, nDepth, rTR );
     if( !pSrcDDB )
@@ -977,7 +977,7 @@ bool X11SalGraphicsImpl::drawAlphaRect( long nX, long nY, long nWidth,
     if( mbPenGC || !mbBrushGC || mbXORMode )
         return false; // can only perform solid fills without XOR.
 
-    if( mrParent.m_pVDev && mrParent.m_pVDev->GetDepth() < 8 )
+    if( mrParent.m_pVDev && static_cast< X11SalVirtualDevice* >(mrParent.m_pVDev)->GetDepth() < 8 )
         return false;
 
     Picture aDstPic = GetXRenderPicture();
@@ -1564,7 +1564,7 @@ long X11SalGraphicsImpl::GetGraphicsHeight() const
     if( mrParent.m_pFrame )
         return mrParent.m_pFrame->maGeometry.nHeight;
     else if( mrParent.m_pVDev )
-        return mrParent.m_pVDev->GetHeight();
+        return static_cast< X11SalVirtualDevice* >(mrParent.m_pVDev)->GetHeight();
     else
         return 0;
 }
@@ -1838,7 +1838,7 @@ long X11SalGraphicsImpl::GetGraphicsWidth() const
     if( mrParent.m_pFrame )
         return mrParent.m_pFrame->maGeometry.nWidth;
     else if( mrParent.m_pVDev )
-        return mrParent.m_pVDev->GetWidth();
+        return static_cast< X11SalVirtualDevice* >(mrParent.m_pVDev)->GetWidth();
     else
         return 0;
 }
diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx
index 80f24f0..38aa7a3 100644
--- a/vcl/unx/generic/gdi/salgdi.cxx
+++ b/vcl/unx/generic/gdi/salgdi.cxx
@@ -149,11 +149,7 @@ void X11SalGraphics::SetDrawable( Drawable aDrawable, SalX11Screen nXScreen )
         m_aXRenderPicture = 0;
     }
 
-    if( hDrawable_ )
-    {
-        mpImpl->Init();
-        // TODO: moggi: FIXME nTextPixel_     = GetPixel( nTextColor_ );
-    }
+    // TODO: moggi: FIXME nTextPixel_     = GetPixel( nTextColor_ );
 }
 
 void X11SalGraphics::Init( SalFrame *pFrame, Drawable aTarget,
@@ -161,11 +157,15 @@ void X11SalGraphics::Init( SalFrame *pFrame, Drawable aTarget,
 {
     m_pColormap = &GetGenericData()->GetSalDisplay()->GetColormap(nXScreen);
     m_nXScreen  = nXScreen;
+
     m_pFrame    = pFrame;
-    SetDrawable( aTarget, nXScreen );
+    m_pVDev     = NULL;
 
     bWindow_    = true;
-    m_pVDev     = NULL;
+    bVirDev_    = false;
+
+    SetDrawable( aTarget, nXScreen );
+    mpImpl->Init();
 }
 
 void X11SalGraphics::DeInit()
diff --git a/vcl/unx/generic/gdi/salvd.cxx b/vcl/unx/generic/gdi/salvd.cxx
index 71ec509..7967a4d 100644
--- a/vcl/unx/generic/gdi/salvd.cxx
+++ b/vcl/unx/generic/gdi/salvd.cxx
@@ -32,49 +32,17 @@
 
 #include <salinst.hxx>
 
+#include <vcl/opengl/OpenGLHelper.hxx>
+#include <opengl/x11/salvd.hxx>
+
 SalVirtualDevice* X11SalInstance::CreateVirtualDevice( SalGraphics* pGraphics,
                                                        long nDX, long nDY,
                                                        sal_uInt16 nBitCount, const SystemGraphicsData *pData )
 {
-    X11SalVirtualDevice *pVDev = new X11SalVirtualDevice();
-    if( !nBitCount && pGraphics )
-        nBitCount = pGraphics->GetBitCount();
-
-    if( pData && pData->hDrawable != None )
-    {
-        ::Window aRoot;
-        int x, y;
-        unsigned int w = 0, h = 0, bw, d;
-        Display* pDisp = GetGenericData()->GetSalDisplay()->GetDisplay();
-        XGetGeometry( pDisp, pData->hDrawable,
-                      &aRoot, &x, &y, &w, &h, &bw, &d );
-        int nScreen = 0;
-        while( nScreen < ScreenCount( pDisp ) )
-        {
-            if( RootWindow( pDisp, nScreen ) == aRoot )
-                break;
-            nScreen++;
-        }
-        nDX = (long)w;
-        nDY = (long)h;
-        if( !pVDev->Init( GetGenericData()->GetSalDisplay(), nDX, nDY, nBitCount,
-                          SalX11Screen( nScreen ), pData->hDrawable,
-                static_cast< XRenderPictFormat* >( pData->pXRenderFormat )) )
-        {
-            delete pVDev;
-            return NULL;
-        }
-    }
-    else if( !pVDev->Init( GetGenericData()->GetSalDisplay(), nDX, nDY, nBitCount,
-                           pGraphics ? static_cast<X11SalGraphics*>(pGraphics)->GetScreenNumber() :
-                                       GetGenericData()->GetSalDisplay()->GetDefaultXScreen() ) )
-    {
-        delete pVDev;
-        return NULL;
-    }
-
-    pVDev->InitGraphics( pVDev );
-    return pVDev;
+    if (OpenGLHelper::isVCLOpenGLEnabled())
+        return new X11OpenGLSalVirtualDevice( pGraphics, nDX, nDY, nBitCount, pData );
+    else
+        return new X11SalVirtualDevice( pGraphics, nDX, nDY, nBitCount, pData );
 }
 
 void X11SalGraphics::Init( X11SalVirtualDevice *pDevice, SalColormap* pColormap,
@@ -110,66 +78,78 @@ void X11SalGraphics::Init( X11SalVirtualDevice *pDevice, SalColormap* pColormap,
 
     const Drawable aVdevDrawable = pDevice->GetDrawable();
     SetDrawable( aVdevDrawable, m_nXScreen );
+    mpImpl->Init();
 }
 
-bool X11SalVirtualDevice::Init( SalDisplay *pDisplay,
-                                    long nDX, long nDY,
-                                    sal_uInt16 nBitCount,
-                                    SalX11Screen nXScreen,
-                                    Pixmap hDrawable,
-                                    XRenderPictFormat* pXRenderFormat )
+X11SalVirtualDevice::X11SalVirtualDevice( SalGraphics* pGraphics,
+                                          long nDX, long nDY,
+                                          sal_uInt16 nBitCount,
+                                          const SystemGraphicsData *pData ) :
+    m_nXScreen( 0 ),
+    bGraphics_( false )
 {
     SalColormap* pColormap = NULL;
     bool bDeleteColormap = false;
 
-    pDisplay_               = pDisplay;
+    if( !nBitCount && pGraphics )
+        nBitCount = pGraphics->GetBitCount();
+
+    pDisplay_               = GetGenericData()->GetSalDisplay();
     pGraphics_              = new X11SalGraphics();
-    m_nXScreen              = nXScreen;
-    if( pXRenderFormat ) {
+    nDepth_                 = nBitCount;
+
+    if( pData && pData->hDrawable != None )
+    {
+        ::Window aRoot;
+        int x, y;
+        unsigned int w = 0, h = 0, bw, d;
+        Display* pDisp = pDisplay_->GetDisplay();
+        XGetGeometry( pDisp, pData->hDrawable,
+                      &aRoot, &x, &y, &w, &h, &bw, &d );
+        int nScreen = 0;
+        while( nScreen < ScreenCount( pDisp ) )
+        {
+            if( RootWindow( pDisp, nScreen ) == aRoot )
+                break;
+            nScreen++;
+        }
+        nDX_ = (long)w;
+        nDY_ = (long)h;
+        m_nXScreen = SalX11Screen( nScreen );
+        hDrawable_ = pData->hDrawable;
+        bExternPixmap_ = true;
+    }
+    else
+    {
+        nDX_ = nDX;
+        nDY_ = nDY;
+        m_nXScreen = pGraphics ? static_cast<X11SalGraphics*>(pGraphics)->GetScreenNumber() :
+                                 GetGenericData()->GetSalDisplay()->GetDefaultXScreen();
+        hDrawable_ = limitXCreatePixmap( GetXDisplay(),
+                                         pDisplay_->GetDrawable( m_nXScreen ),
+                                         nDX_, nDY_,
+                                         GetDepth() );
+        bExternPixmap_ = false;
+    }
+
+    XRenderPictFormat* pXRenderFormat = pData ? static_cast<XRenderPictFormat*>(pData->pXRenderFormat) : NULL;
+    if( pXRenderFormat )
+    {
         pGraphics_->SetXRenderFormat( pXRenderFormat );
         if( pXRenderFormat->colormap )
-            pColormap = new SalColormap( pDisplay, pXRenderFormat->colormap, m_nXScreen );
+            pColormap = new SalColormap( pDisplay_, pXRenderFormat->colormap, m_nXScreen );
         else
             pColormap = new SalColormap( nBitCount );
          bDeleteColormap = true;
     }
-    else if( nBitCount != pDisplay->GetVisual( m_nXScreen ).GetDepth() )
+    else if( nBitCount != pDisplay_->GetVisual( m_nXScreen ).GetDepth() )
     {
         pColormap = new SalColormap( nBitCount );
         bDeleteColormap = true;
     }
-    pGraphics_->SetLayout( 0 ); // by default no! mirroring for VirtualDevices, can be enabled with EnableRTL()
-    nDX_                    = nDX;
-    nDY_                    = nDY;
-    nDepth_                 = nBitCount;
-
-    if( hDrawable == None )
-        hDrawable_          = limitXCreatePixmap( GetXDisplay(),
-                                             pDisplay_->GetDrawable( m_nXScreen ),
-                                             nDX_, nDY_,
-                                             GetDepth() );
-    else
-    {
-        hDrawable_ = hDrawable;
-        bExternPixmap_ = true;
-    }
 
+    pGraphics_->SetLayout( 0 ); // by default no! mirroring for VirtualDevices, can be enabled with EnableRTL()
     pGraphics_->Init( this, pColormap, bDeleteColormap );
-
-    return hDrawable_ != None;
-}
-
-X11SalVirtualDevice::X11SalVirtualDevice() :
-    m_nXScreen( 0 )
-{
-    pDisplay_               = NULL;
-    pGraphics_              = NULL;
-    hDrawable_              = None;
-    nDX_                    = 0;
-    nDY_                    = 0;
-    nDepth_                 = 0;
-    bGraphics_              = false;
-    bExternPixmap_          = false;
 }
 
 X11SalVirtualDevice::~X11SalVirtualDevice()
@@ -196,8 +176,6 @@ SalGraphics* X11SalVirtualDevice::AcquireGraphics()
 void X11SalVirtualDevice::ReleaseGraphics( SalGraphics* )
 { bGraphics_ = false; }
 
-#include "opengl/x11/gdiimpl.hxx"
-
 bool X11SalVirtualDevice::SetSize( long nDX, long nDY )
 {
     if( bExternPixmap_ )
@@ -231,14 +209,7 @@ bool X11SalVirtualDevice::SetSize( long nDX, long nDY )
     nDY_ = nDY;
 
     if( pGraphics_ )
-    {
-        InitGraphics( this );
-
-        // re-initialize OpenGLContext [!] having freed it's underlying pixmap above
-        X11OpenGLSalGraphicsImpl *pImpl = dynamic_cast< X11OpenGLSalGraphicsImpl* >(pGraphics_->GetImpl());
-        if( pImpl )
-            pImpl->Init();
-    }
+        pGraphics_->Init( this );
 
     return true;
 }


More information about the Libreoffice-commits mailing list