include/vcl/opengl/OpenGLContext.hxx | 11 + vcl/inc/opengl/win/gdiimpl.hxx | 9 + vcl/inc/opengl/x11/gdiimpl.hxx | 6 vcl/inc/openglgdiimpl.hxx | 28 +++ vcl/inc/salgdiimpl.hxx | 2 vcl/inc/svdata.hxx | 3 vcl/inc/unx/x11/x11gdiimpl.h | 1 vcl/inc/win/salgdi.h | 1 vcl/opengl/gdiimpl.cxx | 253 +++++++++++++++++++++++++---------- vcl/opengl/win/gdiimpl.cxx | 30 ++++ vcl/opengl/x11/gdiimpl.cxx | 60 +++++--- vcl/source/opengl/OpenGLContext.cxx | 39 +++++ vcl/unx/generic/gdi/salgdi.cxx | 2 vcl/win/source/gdi/gdiimpl.cxx | 4 vcl/win/source/gdi/gdiimpl.hxx | 2 vcl/win/source/gdi/salgdi.cxx | 10 - 16 files changed, 352 insertions(+), 109 deletions(-)
New commits: 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()
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits