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

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Thu Nov 27 04:57:04 PST 2014


 include/vcl/opengl/OpenGLContext.hxx |   15 +++
 vcl/Library_vcl.mk                   |    1 
 vcl/Library_vclplug_gen.mk           |    1 
 vcl/inc/opengl/framebuffer.hxx       |   45 ++++++++++
 vcl/inc/opengl/salbmp.hxx            |    1 
 vcl/inc/opengl/texture.hxx           |    3 
 vcl/inc/opengl/win/gdiimpl.hxx       |    2 
 vcl/inc/opengl/x11/gdiimpl.hxx       |    2 
 vcl/inc/opengl/x11/salvd.hxx         |   55 ++++++++++++
 vcl/inc/openglgdiimpl.hxx            |   15 +--
 vcl/inc/svdata.hxx                   |    2 
 vcl/inc/unx/salgdi.h                 |    4 
 vcl/inc/unx/salvd.h                  |   15 ---
 vcl/opengl/framebuffer.cxx           |   70 ++++++++++++++++
 vcl/opengl/gdiimpl.cxx               |  138 +++++++++++++------------------
 vcl/opengl/salbmp.cxx                |   17 ++-
 vcl/opengl/scale.cxx                 |   35 +++-----
 vcl/opengl/win/gdiimpl.cxx           |    2 
 vcl/opengl/x11/gdiimpl.cxx           |   66 +++++++--------
 vcl/opengl/x11/salvd.cxx             |  102 +++++++++++++++++++++++
 vcl/source/gdi/salgdilayout.cxx      |    2 
 vcl/source/opengl/OpenGLContext.cxx  |  126 ++++++++++++++++++++++++++---
 vcl/unx/generic/gdi/gdiimpl.cxx      |   10 +-
 vcl/unx/generic/gdi/salgdi.cxx       |   14 +--
 vcl/unx/generic/gdi/salvd.cxx        |  151 ++++++++++++++---------------------
 25 files changed, 614 insertions(+), 280 deletions(-)

New commits:
commit db003eb66fbae558b09218190f12498ecfb67e1d
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
    
    Change-Id: I17f6ce66fb8b5bc027d35b4016ae56c24ee0a738

diff --git a/include/vcl/opengl/OpenGLContext.hxx b/include/vcl/opengl/OpenGLContext.hxx
index 9be9c59..1b21851 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
 {
@@ -177,6 +180,13 @@ public:
     void AddRef();
     void DeRef();
 
+    // 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();
@@ -229,6 +239,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 81f774a..a231dae 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -125,6 +125,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 449c1b6..6a812d0 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 ee7889e..043bd95 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"
 
@@ -37,6 +38,7 @@ class VCL_PLUGIN_PUBLIC OpenGLSalGraphicsImpl : public SalGraphicsImpl
 protected:
 
     OpenGLContext* mpContext;
+    OpenGLFramebuffer* mpFramebuffer;
 
     // clipping
     vcl::Region maClipRegion;
@@ -44,7 +46,6 @@ protected:
     bool mbUseStencil;
 
     bool mbOffscreen;
-    GLuint mnFramebufferId;
     OpenGLTexture maOffscreenTex;
 
     SalColor mnLineColor;
@@ -156,23 +157,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 212e036..be40afc 100644
--- a/vcl/inc/svdata.hxx
+++ b/vcl/inc/svdata.hxx
@@ -345,7 +345,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 8f4c6c4..28f7959 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)
@@ -112,24 +112,25 @@ OpenGLSalGraphicsImpl::~OpenGLSalGraphicsImpl()
     ReleaseContext();
 }
 
-bool OpenGLSalGraphicsImpl::AcquireContext( bool bOffscreen )
+OpenGLContext* OpenGLSalGraphicsImpl::GetOpenGLContext()
+{
+    if( !mpContext )
+        AcquireContext();
+    return mpContext;
+}
+
+bool OpenGLSalGraphicsImpl::AcquireContext( )
 {
     ImplSVData* pSVData = ImplGetSVData();
 
     if( mpContext )
         mpContext->DeRef();
 
-    if( bOffscreen )
-    {
-        mpContext = CreatePixmapContext();
-        return (mpContext != NULL);
-    }
-
     OpenGLContext* pContext = pSVData->maGDIData.mpLastContext;
     while( pContext )
     {
         // check if this context can be used by this SalGraphicsImpl instance
-        if( CompareWinContext( pContext )  )
+        if( UseContext( pContext )  )
             break;
         pContext = pContext->mpPrevContext;
     }
@@ -137,7 +138,7 @@ bool OpenGLSalGraphicsImpl::AcquireContext( bool bOffscreen )
     if( pContext )
         pContext->AddRef();
     else
-        pContext = CreateWinContext();
+        pContext = mbOffscreen ? CreatePixmapContext() : CreateWinContext();
 
     mpContext = pContext;
     return (mpContext != NULL);
@@ -153,68 +154,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 ) ) )
+        if( !UseContext( mpContext ) )
             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();
 
@@ -223,15 +197,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();
 }
 
@@ -287,6 +262,8 @@ void OpenGLSalGraphicsImpl::ImplInitClipRegion()
         glStencilFunc( GL_EQUAL, 1, 0x1 );
         glEnable( GL_STENCIL_TEST );
     }
+
+    CHECK_GL_ERROR();
 }
 
 bool OpenGLSalGraphicsImpl::setClipRegion( const vcl::Region& rClip )
@@ -379,28 +356,27 @@ 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;
-    }
+        SalTwoRect aPosAry;
+        aPosAry.mnSrcX = aPosAry.mnDestX = 0;
+        aPosAry.mnSrcY = aPosAry.mnDestY = 0;
+        aPosAry.mnSrcWidth = aPosAry.mnDestWidth = GetWidth();
+        aPosAry.mnSrcHeight = aPosAry.mnDestHeight = GetHeight();
 
-    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 );
-    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;
@@ -1916,13 +1892,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 8cd7561..ce566b0 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 55b3c5a..fb05005 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 605cbd5..d4115fa 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 )
@@ -158,7 +156,7 @@ bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixm
     Display* pDisplay = mrParent.GetXDisplay();
     GLXFBConfig pFbConfig;
     GLXPixmap pGlxPixmap;
-    GLXPixmap pGlxMask;
+    GLXPixmap pGlxMask = 0;
     SalTwoRect aPosAry;
     bool bInverted;
 
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 a075b4d..6a85e59 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 caf3d30..424d2dc 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'
@@ -53,6 +56,9 @@ OpenGLContext::OpenGLContext():
     mbRequestLegacyContext(false),
     mbUseDoubleBufferedRendering(true),
     mbRequestVirtualDevice(false),
+    mpCurrentFramebuffer(NULL),
+    mpFirstFramebuffer(NULL),
+    mpLastFramebuffer(NULL),
     mnPainting(0),
     mpPrevContext(NULL),
     mpNextContext(NULL)
@@ -74,15 +80,6 @@ OpenGLContext::OpenGLContext():
 
 OpenGLContext::~OpenGLContext()
 {
-#if defined( WNT )
-    if (m_aGLWin.hRC)
-    {
-        vShareList.erase(std::remove(vShareList.begin(), vShareList.end(), m_aGLWin.hRC));
-
-        wglMakeCurrent( m_aGLWin.hDC, 0 );
-        wglDeleteContext( m_aGLWin.hRC );
-        ReleaseDC( m_aGLWin.hWnd, m_aGLWin.hDC );
-    }
     ImplSVData* pSVData = ImplGetSVData();
     if( mpPrevContext )
         mpPrevContext->mpNextContext = mpNextContext;
@@ -93,6 +90,15 @@ OpenGLContext::~OpenGLContext()
     else
         pSVData->maGDIData.mpLastContext = mpPrevContext;
 
+#if defined( WNT )
+    if (m_aGLWin.hRC)
+    {
+        vShareList.erase(std::remove(vShareList.begin(), vShareList.end(), m_aGLWin.hRC));
+
+        wglMakeCurrent( m_aGLWin.hDC, 0 );
+        wglDeleteContext( m_aGLWin.hRC );
+        ReleaseDC( m_aGLWin.hWnd, m_aGLWin.hDC );
+    }
 #elif defined( MACOSX )
     OpenGLWrapper::resetCurrent();
 #elif defined( IOS ) || defined( ANDROID )
@@ -579,6 +585,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)
@@ -663,6 +670,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;
@@ -681,8 +690,6 @@ bool OpenGLContext::init(Display* dpy, Pixmap pix, unsigned int width, unsigned
 
     mbPixmap = true;
 
-    initOpenGLFunctionPointers();
-
     return ImplInit();
 }
 
@@ -881,7 +888,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");
@@ -1203,13 +1210,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
 }
 
@@ -1282,4 +1308,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 91c4db7..28beaf4 100644
--- a/vcl/unx/generic/gdi/gdiimpl.cxx
+++ b/vcl/unx/generic/gdi/gdiimpl.cxx
@@ -739,7 +739,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 ) );
@@ -861,7 +861,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 )
@@ -988,7 +988,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();
@@ -1575,7 +1575,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;
 }
@@ -1849,7 +1849,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 3c1a727..d9eb7df 100644
--- a/vcl/unx/generic/gdi/salgdi.cxx
+++ b/vcl/unx/generic/gdi/salgdi.cxx
@@ -148,11 +148,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,
@@ -160,11 +156,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