[Libreoffice-commits] core.git: Branch 'feature/lfrb-vcl-opengl' - 1874 commits - accessibility/source android/experimental animations/source apple_remote/source autogen.sh avmedia/Library_avmediagst.mk avmedia/Library_avmedia.mk avmedia/Library_avmediaogl.mk avmedia/Module_avmedia.mk avmedia/source basctl/Module_basctl.mk basctl/source basegfx/source basic/inc basic/Library_sb.mk basic/Module_basic.mk basic/qa basic/source bean/com binaryurp/source bin/check-merged.sh bin/findunusedcode bin/lo-all-static-libs bin/lolcat bin/parse-perfcheck.py bin/refcount_leak.py bin/run bridges/source bridges/test canvas/Library_oglcanvas.mk canvas/source chart2/CppunitTest_chart2_export.mk chart2/CppunitTest_chart2_import.mk chart2/CppunitTest_chart2_xshape.mk chart2/inc chart2/Library_chartcontroller.mk chart2/Library_chartcore.mk chart2/Library_chartopengl.mk chart2/opengl chart2/qa chart2/source chart2/uiconfig cli_ure/source codemaker/source comphelper/Library_comphelper.mk comphelper/qa comphelper/source compilerplugins/clang config_host/config_features.h.in config_host.mk.in configmgr/CppunitTest_configmgr_unit.mk configmgr/qa configmgr/source configure.ac connectivity/com connectivity/CppunitTest_connectivity_commontools.mk connectivity/inc connectivity/qa connectivity/source cppcanvas/CppunitTest_cppcanvas_emfplus.mk cppcanvas/qa cppcanvas/source cppuhelper/qa cppuhelper/source cppuhelper/test cppu/qa cppu/source cpputools/source crashrep/source cui/Library_cui.mk cui/source cui/uiconfig dbaccess/qa dbaccess/source dbaccess/uiconfig desktop/Module_desktop.mk desktop/Package_sbase_sh.mk desktop/Package_scalc_sh.mk desktop/Package_scripts.mk desktop/Package_sdraw_sh.mk desktop/Package_simpress_sh.mk desktop/Package_smath_sh.mk desktop/Package_swriter_sh.mk desktop/source desktop/test desktop/uiconfig desktop/unx desktop/win32 distro-configs/LibreOfficeAndroidAarch64.conf distro-configs/LibreOfficeAndroid.conf distro-configs/LibreOfficeAndroidX86.conf distro-configs/LibreOfficeLinux .conf drawinglayer/source dtrans/source dtrans/test editeng/CppunitTest_editeng_core.mk editeng/CustomTarget_generated.mk editeng/Library_editeng.mk editeng/Module_editeng.mk editeng/source embeddedobj/source embeddedobj/test embedserv/source eventattacher/source extensions/Executable_pluginapp.bin.mk extensions/Library_scn.mk extensions/qa extensions/source extensions/test extensions/uiconfig extensions/workben external/apache-commons external/boost external/cppunit external/firebird external/glm external/icu external/languagetool external/lcms2 external/libabw external/libcdr external/libebook external/libetonyek external/libexttextcat external/libfreehand external/libgltf external/liblangtag external/libmspub external/libmwaw external/libodfgen external/liborcus external/libpagemaker external/librevenge external/libvisio external/libwpd external/libwpg external/libwps external/lpsolve external/Module_external.mk external/mysqlcppconn external/nss external/poppler external/python3 filter/Configuration_filter.mk filter/CppunitTest_filter_eps_test.mk filter/CppunitTest_filter_pcd_test.mk filter/Module_filter.mk filter/qa filter/source filter/uiconfig forms/qa forms/source formula/source fpicker/source framework/inc framework/qa framework/source .gitignore helpcontent2 hwpfilter/source i18nlangtag/source i18npool/source icon-themes/crystal icon-themes/galaxy icon-themes/hicontrast icon-themes/human icon-themes/industrial icon-themes/oxygen icon-themes/sifr icon-themes/tango icon-themes/tango_testing idlc/source idl/inc idl/source include/basebmp include/basic include/canvas include/com include/comphelper include/cppuhelper include/drawinglayer include/editeng include/filter include/formula include/jvmfwk include/LibreOfficeKit include/o3tl include/oox include/osl include/package include/rsc include/rtl include/sal include/sax include/sfx2 include/svl include/svtools include/svx include/test include/toolkit include/tools include/ucbhelper include/unotools includ e/vbahelper include/vcl include/xmloff include/xmlreader instsetoo_native/inc_ooohelppack instsetoo_native/inc_openoffice instsetoo_native/inc_sdkoo ios/Executable_LibreOffice.mk ios/experimental io/source io/test javaunohelper/com javaunohelper/source jurt/com jurt/test jvmfwk/plugins jvmfwk/source l10ntools/source librelogo/CustomTarget_librelogo.mk librelogo/Module_librelogo.mk libreofficekit/qa lingucomponent/source linguistic/source linguistic/workben lotuswordpro/source Makefile.fetch Makefile.in mysqlc/source nlpsolver/src nlpsolver/ThirdParty o3tl/qa odk/examples odk/qa offapi/com offapi/UnoApi_offapi.mk officecfg/Configuration_officecfg.mk officecfg/registry oox/source package/inc package/Library_package2.mk package/source postprocess/CustomTarget_registry.mk postprocess/Rdb_services.mk pyuno/CustomTarget_python_shell.mk pyuno/demo pyuno/inc pyuno/source pyuno/zipcore qadevOOo/runner qadevOOo/tests readlicense_oo/docs readlicense_oo/license README.cross registry/source regi stry/tools remotebridges/examples reportbuilder/java reportdesign/inc reportdesign/qa reportdesign/source reportdesign/uiconfig RepositoryExternal.mk Repository.mk RepositoryModule_host.mk ridljar/com rsc/inc rsc/source sal/cppunittester sal/Library_sal.mk sal/osl sal/qa sal/rtl sal/test sal/workben sax/Library_expwrap.mk sax/source sax/test scaddins/source sc/CppunitTest_sc_annotationobj.mk sc/CppunitTest_sc_annotationshapeobj.mk sc/CppunitTest_sc_annotationsobj.mk sc/CppunitTest_sc_cellrangeobj.mk sc/CppunitTest_sc_chart_regression_test.mk sc/CppunitTest_sc_datapilotfieldobj.mk sc/CppunitTest_sc_datapilottableobj.mk sc/CppunitTest_sc_editfieldobj_cell.mk sc/CppunitTest_sc_editfieldobj_header.mk sc/CppunitTest_sc_html_export_test.mk sc/CppunitTest_sc_macros_test.mk sc/CppunitTest_sc_modelobj.mk sc/CppunitTest_sc_namedrangeobj.mk sc/CppunitTest_sc_namedrangesobj.mk sc/CppunitTest_sc_opencl_test.mk sc/CppunitTest_sc_outlineobj.mk sc/CppunitTest_sc_perfobj.mk sc/CppunitTest_sc_rangels t_test.mk sc/CppunitTest_sc_styleloaderobj.mk sc/CppunitTest_sc_subsequent_export_test.mk sc/CppunitTest_sc_tablesheetobj.mk sc/CppunitTest_sc_tablesheetsobj.mk sc/CppunitTest_sc_ucalc.mk sc/inc sc/Library_scfilt.mk sc/Library_sc.mk sc/Library_scopencl.mk sc/Module_sc.mk scp2/AutoInstall.mk scp2/inc scp2/InstallModule_base.mk scp2/InstallModule_calc.mk scp2/InstallModule_crashrep.mk scp2/InstallModule_draw.mk scp2/InstallModule_impress.mk scp2/InstallModule_math.mk scp2/InstallModule_ooo.mk scp2/InstallModule_quickstart.mk scp2/InstallModule_writer.mk scp2/source sc/qa scripting/examples scripting/java scripting/Module_scripting.mk scripting/source sc/source sc/uiconfig sc/workben sd/CppunitTest_sd_export_tests.mk sdext/source sd/inc sd/qa sd/README_REMOTE sd/source sd/uiconfig setup_native/scripts sfx2/inc sfx2/qa sfx2/sdi sfx2/source sfx2/uiconfig shell/Module_shell.mk shell/source slideshow/Library_OGLTrans.mk slideshow/Library_slideshow.mk slideshow/source slideshow/test smokete st/data smoketest/libtest.cxx solenv/bin solenv/doc solenv/gbuild solenv/gcc-wrappers solenv/gdb solenv/inc soltools/cpp soltools/mkdepend sot/source starmath/inc starmath/source starmath/uiconfig stoc/source stoc/test store/source svgio/CppunitTest_svgio.mk svgio/inc svgio/source svl/Library_svl.mk svl/source svtools/langsupport svtools/README svtools/source svtools/uiconfig svx/inc svx/Library_svxcore.mk svx/Library_svx.mk svx/sdi svx/source svx/uiconfig svx/UIConfig_svx.mk svx/util svx/workben sw/AllLangResTarget_sw.mk sw/CppunitTest_sw_filters_test.mk sw/CppunitTest_sw_globalfilter.mk sw/CppunitTest_sw_rtfexport.mk sw/CppunitTest_sw_tox.mk sw/CppunitTest_sw_uiwriter.mk sw/CppunitTest_sw_uwriter.mk swext/mediawiki sw/inc sw/Library_sw.mk sw/Module_sw.mk sw/qa sw/README sw/sdi sw/source sw/uiconfig sysui/CustomTarget_solaris.mk test/Library_test.mk test/source toolkit/qa toolkit/source toolkit/test tools/CppunitTest_tools_test.mk tools/Library_tl.mk tools/qa tools/source touch/Lib rary_libotouch.mk touch/source translations tubes/source ucbhelper/source ucb/source udkapi/com UnoControls/source unodevtools/source unoidl/source unotest/source unotools/CppunitTest_unotools_fontdefs.mk unotools/qa unotools/source unoxml/Library_unoxml.mk unoxml/source unusedcode.easy uui/source vbahelper/Module_vbahelper.mk vbahelper/source vcl/android vcl/Executable_icontest.mk vcl/Executable_outdevgrind.mk vcl/Executable_vcldemo.mk vcl/generic vcl/headless vcl/inc vcl/ios vcl/Library_vcl.mk vcl/Library_vclopengl.mk vcl/Library_vclplug_gen.mk vcl/Library_vclplug_gtk3.mk vcl/Library_vclplug_gtk.mk vcl/Library_vclplug_kde4.mk vcl/Library_vclplug_kde.mk vcl/Module_vcl.mk vcl/opengl vcl/osx vcl/Package_fontunxppds.mk vcl/Package_opengl.mk vcl/qa vcl/quartz vcl/source vcl/unx vcl/win vcl/workben winaccessibility/source wizards/com wizards/source writerfilter/inc writerfilter/qa writerfilter/source writerperfect/Library_wpftdraw.mk writerperfect/Library_wpftimpress.mk writerperfect/Li brary_wpftwriter.mk writerperfect/qa writerperfect/source xmerge/source xmlhelp/source xmloff/dtd xmloff/inc xmloff/source xmlscript/source xmlscript/test xmlsecurity/source xmlsecurity/test_docs

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Wed Nov 26 06:28:05 PST 2014


Rebased ref, commits from common ancestor:
commit 88001441d3c3e7182caad3b557992371ca1dffe1
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 972fee0..7efa94b 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/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..90edf5f 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;
@@ -156,23 +158,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/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 155757a..127df89 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/salvd.cxx b/vcl/opengl/salvd.cxx
new file mode 100644
index 0000000..5e55f35
--- /dev/null
+++ b/vcl/opengl/salvd.cxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+void X11SalGraphics::Init( X11OpenGLSalVirtualDevice *pDevice )
+{
+    SalColormap *pOrigDeleteColormap = m_pDeleteColormap;
+
+    SalDisplay *pDisplay  = pDevice->GetDisplay();
+    m_nXScreen = pDevice->GetXScreenNumber();
+
+    int nVisualDepth = pDisplay->GetVisual( m_nXScreen ).GetDepth();
+    int nDeviceDepth = pDevice->GetDepth();
+
+    if( pColormap )
+    {
+        m_pColormap = pColormap;
+        if( bDeleteColormap )
+            m_pDeleteColormap = pColormap;
+    }
+    else if( nDeviceDepth == nVisualDepth )
+        m_pColormap = &pDisplay->GetColormap( m_nXScreen );
+    else if( nDeviceDepth == 1 )
+        m_pColormap = m_pDeleteColormap = new SalColormap();
+
+    if (m_pDeleteColormap != pOrigDeleteColormap)
+        delete pOrigDeleteColormap;
+
+    m_pVDev      = pDevice;
+    m_pFrame     = NULL;
+
+    bWindow_     = pDisplay->IsDisplay();
+    bVirDev_     = true;
+
+    const Drawable aVdevDrawable = pDevice->GetDrawable();
+    SetDrawable( aVdevDrawable, m_nXScreen );
+    mpImpl->Init();
+}
+
+bool X11OpenGLSalVirtualDevice::Init( SalGraphics* pGraphics,
+                                      long nDX, long nDY,
+                                      sal_uInt16 nBitCount,
+                                      const SystemGraphicsData *pData )
+{
+    if( !nBitCount && pGraphics )
+        nBitCount = pGraphics->GetBitCount();
+
+    // TODO Check where a VirtualDevice is created from SystemGraphicsData
+    assert( pData == NULL );
+
+    mpDisplay  = GetGenericData()->GetSalDisplay();
+    nDepth_    = nBitCount;
+    mnXScreen  = pGraphics ? static_cast<X11SalGraphics*>(pGraphics)->GetScreenNumber() :
+                                 GetGenericData()->GetSalDisplay()->GetDefaultXScreen();
+    mnWidth    = nDX;
+    mnHeight   = nDY;
+    mpGraphics = new X11SalGraphics();
+    mpGraphics->SetLayout( 0 );
+    mpGraphics->Init( this );
+
+    return true;
+}
+
+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 )
+{
+    mnWidth = nDX;
+    mnHeigth = nDY;
+    mpGraphics->Init( this );
+}
+
+long X11OpenGLSalVirtualDevice::GetWidth() const
+{
+    return mnWidth;
+}
+
+long X11OpenGLSalVirtualDevice::GetHeight() const
+{
+    return mnHeight;
+}
+
+void X11OpenGLSalVirtualDevice::GetSize( long& rWidth, long& rHeight )
+{
+    rWidth  = mnWidth;
+    rHeight = mnHeight;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx
index 605cbd5..73d0943 100644
--- a/vcl/opengl/x11/gdiimpl.cxx
+++ b/vcl/opengl/x11/gdiimpl.cxx
@@ -17,6 +17,7 @@
 
 #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 +37,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 +46,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;
 }
 
@@ -86,24 +77,29 @@ OpenGLContext* X11OpenGLSalGraphicsImpl::CreateWinContext()
     return pContext;
 }
 
-bool X11OpenGLSalGraphicsImpl::CompareWinContext( OpenGLContext* pContext )
-{
-    X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame);
-
-    if( !pProvider || !pContext->isInitialized() )
-        return false;
-    return ( pContext->getOpenGLWindow().win == pProvider->GetX11Window() );
-}
-
 OpenGLContext* X11OpenGLSalGraphicsImpl::CreatePixmapContext()
 {
     if( mrParent.m_pVDev == NULL )
         return NULL;
-    OpenGLContext* pContext = new OpenGLContext();
+    /*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;
+                    mrParent.m_nXScreen.getXScreen() );*/
+    // TODO Create a X11 Pixmap and create a context from it
+    return NULL;
+}
+
+bool X11OpenGLSalGraphicsImpl::UseContext( OpenGLContext* pContext )
+{
+    X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame);
+
+    if( !pContext->isInitialized() )
+        return false;
+
+    if( !pProvider )
+        return true;
+    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..0ea5a75
--- /dev/null
+++ b/vcl/opengl/x11/salvd.cxx
@@ -0,0 +1,96 @@
+/* -*- 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 ) :
+    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 );
+
+    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 )
+{
+    mnWidth = nDX;
+    mnHeight = nDY;
+    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..a0fca30 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 )
@@ -1203,13 +1209,30 @@ 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;
+            pSVData->maGDIData.mpLastContext = this;
+        }
+    }
 #endif
 }
 
@@ -1282,4 +1305,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..e527d6d 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,
@@ -162,6 +158,7 @@ void X11SalGraphics::Init( SalFrame *pFrame, Drawable aTarget,
     m_nXScreen  = nXScreen;
     m_pFrame    = pFrame;
     SetDrawable( aTarget, nXScreen );
+    mpImpl->Init();
 
     bWindow_    = true;
     m_pVDev     = NULL;
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;
 }
commit 07eea5d1b0eb0265f43c6d8d63d775a316f9b42a
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Sat Nov 22 08:11:33 2014 -0500

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

diff --git a/vcl/Package_opengl.mk b/vcl/Package_opengl.mk
index 4a4f30f..d81c0ec 100644
--- a/vcl/Package_opengl.mk
+++ b/vcl/Package_opengl.mk
@@ -12,6 +12,7 @@ $(eval $(call gb_Package_Package,vcl_opengl_shader,$(SRCDIR)/vcl/opengl))
 $(eval $(call gb_Package_add_files,vcl_opengl_shader,$(LIBO_ETC_FOLDER)/opengl,\
 	blendedTextureFragmentShader.glsl \
 	blendedTextureVertexShader.glsl \
+	diffTextureFragmentShader.glsl \
 	convolutionFragmentShader.glsl \
 	linearGradientFragmentShader.glsl \
 	maskFragmentShader.glsl \
diff --git a/vcl/inc/opengl/x11/gdiimpl.hxx b/vcl/inc/opengl/x11/gdiimpl.hxx
index a2b863e..d25d5d0 100644
--- a/vcl/inc/opengl/x11/gdiimpl.hxx
+++ b/vcl/inc/opengl/x11/gdiimpl.hxx
@@ -35,7 +35,7 @@ public:
     virtual void copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ) SAL_OVERRIDE;
     void Init() SAL_OVERRIDE;
     bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE;
-    bool RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE;
+    bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) SAL_OVERRIDE;
 };
 
 #endif // INCLUDED_VCL_INC_OPENGL_X11_GDIIMPL_HXX
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index 761b405..5a7382b 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -67,6 +67,10 @@ protected:
     GLuint mnTransformedMaskedSamplerUniform;
     GLuint mnTransformedMaskedMaskUniform;
 
+    GLuint mnDiffTextureProgram;
+    GLuint mnDiffTextureUniform;
+    GLuint mnDiffMaskUniform;
+
     GLuint mnMaskedTextureProgram;
     GLuint mnMaskedSamplerUniform;
     GLuint mnMaskSamplerUniform;
@@ -96,6 +100,7 @@ protected:
     bool CreateSolidProgram( void );
     bool CreateTextureProgram( void );
     bool CreateTransformedTextureProgram( void );
+    bool CreateDiffTextureProgram( void );
     bool CreateMaskedTextureProgram( void );
     bool CreateBlendedTextureProgram( void );
     bool CreateTransformedMaskedTextureProgram( void );
@@ -124,6 +129,7 @@ public:
     void DrawTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted = false );
     void DrawTransformedTexture( OpenGLTexture& rTexture, OpenGLTexture& rMask, const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX, const basegfx::B2DPoint& rY );
     void DrawAlphaTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted = false, bool pPremultiplied = false );
+    void DrawTextureDiff( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry, bool bInverted = false );

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list