Rebased ref, commits from common ancestor: commit 88001441d3c3e7182caad3b557992371ca1dffe1 Author: Louis-Francis Ratté-Boulianne <l...@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 <l...@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 <l...@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 <l...@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 <l...@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 <l...@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 <l...@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 <l...@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 <l...@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
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits