include/vcl/opengl/OpenGLContext.hxx | 11 include/vcl/outdev.hxx | 4 officecfg/registry/data/org/openoffice/Office/Views.xcu | 12 sfx2/source/appl/childwin.cxx | 1 sfx2/source/sidebar/SidebarChildWindow.cxx | 30 sfx2/source/sidebar/SidebarController.cxx | 78 - unotools/source/config/viewoptions.cxx | 10 vcl/Package_opengl.mk | 3 vcl/generic/print/genpspgraphics.cxx | 10 vcl/headless/svpgdi.cxx | 10 vcl/inc/generic/genpspgraphics.h | 6 vcl/inc/headless/svpgdi.hxx | 5 vcl/inc/opengl/win/gdiimpl.hxx | 9 vcl/inc/opengl/x11/gdiimpl.hxx | 8 vcl/inc/openglgdiimpl.hxx | 51 + vcl/inc/quartz/salgdi.h | 8 vcl/inc/regionband.hxx | 2 vcl/inc/salgdi.hxx | 24 vcl/inc/salgdiimpl.hxx | 12 vcl/inc/svdata.hxx | 3 vcl/inc/unx/gtk/gtkgdi.hxx | 14 vcl/inc/unx/salgdi.h | 10 vcl/inc/unx/x11/x11gdiimpl.h | 3 vcl/inc/win/salgdi.h | 9 vcl/opengl/blendedTextureFragmentShader.glsl | 27 vcl/opengl/blendedTextureVertexShader.glsl | 22 vcl/opengl/diffTextureFragmentShader.glsl | 26 vcl/opengl/gdiimpl.cxx | 431 ++++++++-- vcl/opengl/scale.cxx | 2 vcl/opengl/texture.cxx | 1 vcl/opengl/win/gdiimpl.cxx | 30 vcl/opengl/x11/gdiimpl.cxx | 94 +- vcl/quartz/salgdicommon.cxx | 14 vcl/source/gdi/regionband.cxx | 2 vcl/source/gdi/salgdilayout.cxx | 30 vcl/source/opengl/OpenGLContext.cxx | 39 vcl/source/outdev/bitmap.cxx | 27 vcl/source/outdev/gradient.cxx | 19 vcl/unx/generic/gdi/gdiimpl.cxx | 15 vcl/unx/generic/gdi/gdiimpl.hxx | 14 vcl/unx/generic/gdi/salgdi.cxx | 2 vcl/unx/generic/gdi/salgdi2.cxx | 18 vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx | 685 +++++++++------- vcl/unx/kde/salnativewidgets-kde.cxx | 2 vcl/win/source/gdi/gdiimpl.cxx | 20 vcl/win/source/gdi/gdiimpl.hxx | 12 vcl/win/source/gdi/salgdi.cxx | 10 vcl/win/source/gdi/salgdi_gdiplus.cxx | 16 48 files changed, 1364 insertions(+), 527 deletions(-)
New commits: commit 357011b5baef0b9b0b966e84ea2494aa81845e45 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 d4e0917..1c420e7 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 bee1ac1305eb9299545b6a6c85ea4e9212065543 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 0a8bf68..0818c59 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 7a64d1e1ccc190c145c298cb74b3b5ee9bf338e2 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 85ec262..83c5bdb 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 65c11ca..d4e0917 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 fa77801f3e57ad94f077230a95bded1067f528e9 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 e7c129a..ebfa6ff 100644 --- a/include/vcl/opengl/OpenGLContext.hxx +++ b/include/vcl/opengl/OpenGLContext.hxx @@ -231,6 +231,7 @@ private: #endif public: + vcl::Region maClipRegion; int mnPainting; OpenGLContext* mpPrevContext; diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx index cb06707..85ec262 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 06b7e6b..65c11ca 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 5f86a6165bdedec4fbac2cf22a958245f52168be 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 01ce323..e7c129a 100644 --- a/include/vcl/opengl/OpenGLContext.hxx +++ b/include/vcl/opengl/OpenGLContext.hxx @@ -231,6 +231,8 @@ private: #endif public: + int mnPainting; + OpenGLContext* mpPrevContext; OpenGLContext* mpNextContext; }; diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx index e84aa7b..cb06707 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 f049f91..06b7e6b 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 ); @@ -1867,15 +1867,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 ad1a52c..7df7970 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 e26237f6cbc0d499c91aa32c3bea1f9daee6578e 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 471e6ce..01ce323 100644 --- a/include/vcl/opengl/OpenGLContext.hxx +++ b/include/vcl/opengl/OpenGLContext.hxx @@ -175,6 +175,9 @@ public: bool init( HDC hDC, HWND hWnd ); #endif + void AddRef(); + void DeRef(); + void makeCurrent(); void resetCurrent(); void swapBuffers(); @@ -219,12 +222,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 2031c91..e84aa7b 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 e5b181b..f049f91 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; @@ -1811,7 +1877,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 18e0da8..0815927 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 afaea92..0a8bf68 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 ? static_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 6595709..ad1a52c 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 e07b56e..80f24f0 100644 --- a/vcl/unx/generic/gdi/salgdi.cxx +++ b/vcl/unx/generic/gdi/salgdi.cxx @@ -151,7 +151,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 90af2a6c403e7f6e5192d54f69b38b85a9e6fbc8 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 3149cc341b1866d215110f0783227549a99b5920 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 b26e10c..2031c91 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 ); void DrawTextureWithMask( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry ); void DrawBlendedTexture( OpenGLTexture& rTexture, OpenGLTexture& rMask, OpenGLTexture& rAlpha, const SalTwoRect& rPosAry ); void DrawMask( OpenGLTexture& rTexture, SalColor nMaskColor, const SalTwoRect& rPosAry ); diff --git a/vcl/inc/unx/gtk/gtkgdi.hxx b/vcl/inc/unx/gtk/gtkgdi.hxx index 05d763c..9ce374d 100644 --- a/vcl/inc/unx/gtk/gtkgdi.hxx +++ b/vcl/inc/unx/gtk/gtkgdi.hxx @@ -163,8 +163,17 @@ public: protected: typedef std::list< Rectangle > clipList; - GdkX11Pixmap* NWGetPixmapFromScreen( Rectangle srcRect ); - bool NWRenderPixmapToScreen( GdkX11Pixmap* pPixmap, Rectangle dstRect ); + GdkX11Pixmap* NWGetPixmapFromScreen( Rectangle srcRect, int nBgColor = 0 ); + bool NWRenderPixmapToScreen( GdkX11Pixmap* pPixmap, GdkX11Pixmap* pMask, Rectangle dstRect ); + + bool DoDrawNativeControl( GdkDrawable* pDrawable, + ControlType nType, + ControlPart nPart, + const Rectangle& aCtrlRect, + const clipList& aClip, + ControlState nState, + const ImplControlValue& aValue, + const OUString& rCaption ); bool NWPaintGTKArrow( GdkDrawable* gdkDrawable, ControlType nType, ControlPart nPart, const Rectangle& rControlRectangle, diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h index 97f9d60..8ef42ba 100644 --- a/vcl/inc/unx/salgdi.h +++ b/vcl/inc/unx/salgdi.h @@ -284,7 +284,7 @@ public: bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ); // render a pixmap to the screen - bool RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ); + bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ); /* use to handle GraphicsExpose/NoExpose after XCopyArea & friends diff --git a/vcl/inc/unx/x11/x11gdiimpl.h b/vcl/inc/unx/x11/x11gdiimpl.h index 8cd130d..239d217 100644 --- a/vcl/inc/unx/x11/x11gdiimpl.h +++ b/vcl/inc/unx/x11/x11gdiimpl.h @@ -19,7 +19,7 @@ public: virtual void Init() = 0; virtual bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) = 0; - virtual bool RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) = 0; + virtual bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) = 0; }; #endif // INCLUDED_VCL_INC_UNX_X11_X11GDIIMPL_HXX diff --git a/vcl/opengl/diffTextureFragmentShader.glsl b/vcl/opengl/diffTextureFragmentShader.glsl new file mode 100644 index 0000000..c0a982d --- /dev/null +++ b/vcl/opengl/diffTextureFragmentShader.glsl @@ -0,0 +1,26 @@ +/* -*- 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/. + */ + +/*precision mediump float;*/ +varying vec2 tex_coord; +uniform sampler2D texture; /* white background */ +uniform sampler2D mask; /* black background */ + +void main() { + float alpha; + vec4 texel0, texel1; + texel0 = texture2D(texture, tex_coord); + texel1 = texture2D(mask, tex_coord); + alpha = 1.0 - abs(texel0.r - texel1.r); + if(alpha > 0.0) + gl_FragColor = texel1 / alpha; + gl_FragColor.a = alpha; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx index 13f3e6e..e5b181b 100644 --- a/vcl/opengl/gdiimpl.cxx +++ b/vcl/opengl/gdiimpl.cxx @@ -84,6 +84,9 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl() , mnTransformedMaskedTransformUniform(0) , mnTransformedMaskedSamplerUniform(0) , mnTransformedMaskedMaskUniform(0) + , mnDiffTextureProgram(0) + , mnDiffTextureUniform(0) + , mnDiffMaskUniform(0) , mnMaskedTextureProgram(0) , mnMaskedSamplerUniform(0) , mnMaskSamplerUniform(0) @@ -373,6 +376,21 @@ bool OpenGLSalGraphicsImpl::CreateTransformedTextureProgram( void ) return true; } +bool OpenGLSalGraphicsImpl::CreateDiffTextureProgram( void ) +{ + mnDiffTextureProgram = OpenGLHelper::LoadShaders( "textureVertexShader", "diffTextureFragmentShader" ); + if( mnDiffTextureProgram == 0 ) + return false; + + glBindAttribLocation( mnDiffTextureProgram, GL_ATTRIB_POS, "position" ); + glBindAttribLocation( mnDiffTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" ); + mnDiffTextureUniform = glGetUniformLocation( mnDiffTextureProgram, "texture" ); + mnDiffMaskUniform = glGetUniformLocation( mnDiffTextureProgram, "mask" ); + + CHECK_GL_ERROR(); + return true; +} + bool OpenGLSalGraphicsImpl::CreateMaskedTextureProgram( void ) { mnMaskedTextureProgram = OpenGLHelper::LoadShaders( "maskedTextureVertexShader", "maskedTextureFragmentShader" ); @@ -838,6 +856,35 @@ void OpenGLSalGraphicsImpl::DrawAlphaTexture( OpenGLTexture& rTexture, const Sal glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); DrawTexture( rTexture, rPosAry, bInverted ); glDisable( GL_BLEND ); + CHECK_GL_ERROR(); +} + +void OpenGLSalGraphicsImpl::DrawTextureDiff( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry, bool bInverted ) +{ + if( mnDiffTextureProgram == 0 ) + { + if( !CreateDiffTextureProgram() ) + return; + } + + glUseProgram( mnDiffTextureProgram ); + glUniform1i( mnDiffTextureUniform, 0 ); + glUniform1i( mnDiffMaskUniform, 1 ); + glActiveTexture( GL_TEXTURE0 ); + rTexture.Bind(); + glActiveTexture( GL_TEXTURE1 ); + rMask.Bind(); + + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + DrawTextureRect( rTexture, rPosAry, bInverted ); + glDisable( GL_BLEND ); + + glActiveTexture( GL_TEXTURE1 ); + rMask.Unbind(); + glActiveTexture( GL_TEXTURE0 ); + rTexture.Unbind(); + glUseProgram( 0 ); CHECK_GL_ERROR(); } diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx index bfc1bbb..afaea92 100644 --- a/vcl/opengl/x11/gdiimpl.cxx +++ b/vcl/opengl/x11/gdiimpl.cxx @@ -126,16 +126,17 @@ bool X11OpenGLSalGraphicsImpl::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, return true; } -bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) +bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) { const int aAttribs[] = { GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, - GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT, + GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT, None }; Display* pDisplay = mrParent.GetXDisplay(); GLXFBConfig pFbConfig; GLXPixmap pGlxPixmap; + GLXPixmap pGlxMask; SalTwoRect aPosAry; bool bInverted; @@ -148,25 +149,48 @@ bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, aPosAry.mnSrcWidth = aPosAry.mnDestWidth = pPixmap->GetWidth(); aPosAry.mnSrcHeight = aPosAry.mnDestHeight = pPixmap->GetHeight(); + PreDraw(); + //glClear( GL_COLOR_BUFFER_BIT ); + XSync( pDisplay, 0 ); pFbConfig = OpenGLHelper::GetPixmapFBConfig( pDisplay, bInverted ); pGlxPixmap = glXCreatePixmap( pDisplay, pFbConfig, pPixmap->GetPixmap(), aAttribs); + if( pMask != NULL ) + pGlxMask = glXCreatePixmap( pDisplay, pFbConfig, pMask->GetPixmap(), aAttribs); XSync( pDisplay, 0 ); - PreDraw(); + if( !pGlxPixmap ) + SAL_WARN( "vcl.opengl", "Couldn't create GLXPixmap" ); + + //TODO: lfrb: glXGetProc to get the functions OpenGLTexture aTexture( pPixmap->GetWidth(), pPixmap->GetHeight(), false ); glActiveTexture( GL_TEXTURE0 ); aTexture.Bind(); - - //TODO: lfrb: glXGetProc to get the functions glXBindTexImageEXT( pDisplay, pGlxPixmap, GLX_FRONT_LEFT_EXT, NULL ); + aTexture.Unbind(); + + if( pMask != NULL && pGlxMask ) + { + OpenGLTexture aMaskTexture( pMask->GetWidth(), pMask->GetHeight(), false ); + aMaskTexture.Bind(); + glXBindTexImageEXT( pDisplay, pGlxMask, GLX_FRONT_LEFT_EXT, NULL ); + aMaskTexture.Unbind(); - DrawTexture( aTexture, aPosAry, bInverted ); + DrawTextureDiff( aTexture, aMaskTexture, aPosAry, !bInverted ); + + glXReleaseTexImageEXT( pDisplay, pGlxMask, GLX_FRONT_LEFT_EXT ); + glXDestroyPixmap( pDisplay, pGlxMask ); + } + else + { + DrawTexture( aTexture, aPosAry, !bInverted ); + } + + CHECK_GL_ERROR(); glXReleaseTexImageEXT( pDisplay, pGlxPixmap, GLX_FRONT_LEFT_EXT ); glXDestroyPixmap( pDisplay, pGlxPixmap ); - aTexture.Unbind(); PostDraw(); diff --git a/vcl/unx/generic/gdi/gdiimpl.cxx b/vcl/unx/generic/gdi/gdiimpl.cxx index bcf8d05..91c4db7 100644 --- a/vcl/unx/generic/gdi/gdiimpl.cxx +++ b/vcl/unx/generic/gdi/gdiimpl.cxx @@ -185,8 +185,9 @@ bool X11SalGraphicsImpl::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int n return true; } -bool X11SalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) +bool X11SalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* /*Mask*/, int nX, int nY ) { + // TODO: lfrb: Use the mask GC aFontGC = mrParent.GetFontGC(); // The GC can't be null, otherwise we'd have no clip region diff --git a/vcl/unx/generic/gdi/gdiimpl.hxx b/vcl/unx/generic/gdi/gdiimpl.hxx index 20c995f..675e2cd 100644 --- a/vcl/unx/generic/gdi/gdiimpl.hxx +++ b/vcl/unx/generic/gdi/gdiimpl.hxx @@ -287,7 +287,7 @@ public: 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 diff --git a/vcl/unx/generic/gdi/salgdi2.cxx b/vcl/unx/generic/gdi/salgdi2.cxx index b848d660..f1911b6 100644 --- a/vcl/unx/generic/gdi/salgdi2.cxx +++ b/vcl/unx/generic/gdi/salgdi2.cxx @@ -89,11 +89,11 @@ bool X11SalGraphics::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) return rImpl.FillPixmapFromScreen( pPixmap, nX, nY ); } -bool X11SalGraphics::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) +bool X11SalGraphics::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) { SAL_INFO( "vcl", "RenderPixmapToScreen" ); X11GraphicsImpl& rImpl = dynamic_cast<X11GraphicsImpl&>(*mpImpl.get()); - return rImpl.RenderPixmapToScreen( pPixmap, nX, nY ); + return rImpl.RenderPixmapToScreen( pPixmap, pMask, nX, nY ); } extern "C" diff --git a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx index 10cff10..46ec7b4 100644 --- a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx +++ b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx @@ -50,6 +50,13 @@ const char* const tabPrelitDataName="libreoffice-tab-is-prelit"; bool GtkSalGraphics::bThemeChanged = true; bool GtkSalGraphics::bNeedPixmapPaint = false; +enum +{ + BG_NONE = 0, + BG_WHITE, + BG_BLACK +}; + GtkSalGraphics::GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow ) : X11SalGraphics(), m_pWindow( pWindow ), @@ -284,9 +291,12 @@ protected: GdkX11Pixmap::GdkX11Pixmap( int nWidth, int nHeight, int nDepth ) : X11Pixmap( nWidth, nHeight ) -, mnDepth( nDepth ) { mpGdkPixmap = gdk_pixmap_new( NULL, nWidth, nHeight, nDepth ); + mnDepth = gdk_drawable_get_depth( GDK_DRAWABLE( mpGdkPixmap ) ); + + GdkScreen *pScreen = gdk_drawable_get_screen( GDK_DRAWABLE( mpGdkPixmap ) ); + gdk_drawable_set_colormap( GDK_DRAWABLE( mpGdkPixmap ), gdk_screen_get_default_colormap( pScreen ) ); } GdkX11Pixmap::~GdkX11Pixmap() @@ -336,11 +346,12 @@ public: ControlState m_nState; Rectangle m_pixmapRect; GdkX11Pixmap* m_pixmap; + GdkX11Pixmap* m_mask; - NWPixmapCacheData() : m_nType(0), m_nState(0), m_pixmap(0) {} + NWPixmapCacheData() : m_nType(0), m_nState(0), m_pixmap(0), m_mask(0) {} ~NWPixmapCacheData() - { SetPixmap( NULL ); }; - void SetPixmap( GdkX11Pixmap* pPixmap ); + { SetPixmap( NULL, NULL ); }; + void SetPixmap( GdkX11Pixmap* pPixmap, GdkX11Pixmap* pMask ); }; class NWPixmapCache @@ -357,8 +368,8 @@ public: { delete [] pData; m_idx = 0; m_size = n; pData = new NWPixmapCacheData[m_size]; } int GetSize() const { return m_size; } - bool Find( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap** pPixmap ); - void Fill( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap* pPixmap ); + bool Find( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap** pPixmap, GdkX11Pixmap** pMask ); + void Fill( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap* pPixmap, GdkX11Pixmap* pMask ); void ThemeChanged(); }; @@ -375,12 +386,15 @@ public: // --- implementation --- -void NWPixmapCacheData::SetPixmap( GdkX11Pixmap* pPixmap ) +void NWPixmapCacheData::SetPixmap( GdkX11Pixmap* pPixmap, GdkX11Pixmap* pMask ) { if( m_pixmap ) delete m_pixmap; + if( m_mask ) + delete m_mask; m_pixmap = pPixmap; + m_mask = pMask; } NWPixmapCache::NWPixmapCache( SalX11Screen nScreen ) @@ -403,10 +417,10 @@ void NWPixmapCache::ThemeChanged() // throw away cached pixmaps int i; for(i=0; i<m_size; i++) - pData[i].SetPixmap( NULL ); + pData[i].SetPixmap( NULL, NULL ); } -bool NWPixmapCache::Find( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap** pPixmap ) +bool NWPixmapCache::Find( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap** pPixmap, GdkX11Pixmap** pMask ) { aState &= ~CTRL_CACHING_ALLOWED; // mask clipping flag int i; @@ -419,13 +433,14 @@ bool NWPixmapCache::Find( ControlType aType, ControlState aState, const Rectang pData[i].m_pixmap != NULL ) { *pPixmap = pData[i].m_pixmap; + *pMask = pData[i].m_mask; return true; } } return false; } -void NWPixmapCache::Fill( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap* pPixmap ) +void NWPixmapCache::Fill( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap* pPixmap, GdkX11Pixmap* pMask ) { if( !(aState & CTRL_CACHING_ALLOWED) ) return; @@ -435,7 +450,7 @@ void NWPixmapCache::Fill( ControlType aType, ControlState aState, const Rectangl pData[m_idx].m_nType = aType; pData[m_idx].m_nState = aState; pData[m_idx].m_pixmapRect = r_pixmapRect; - pData[m_idx].SetPixmap( pPixmap ); + pData[m_idx].SetPixmap( pPixmap, pMask ); } void NWPixmapCacheList::AddCache( NWPixmapCache* pCache ) @@ -494,6 +509,10 @@ void GtkData::initNWF( void ) pSVData->maNWFData.mbDDListBoxNoTextArea = true; + // use offscreen rendering when using OpenGL backend + if( OpenGLHelper::isVCLOpenGLEnabled() ) + GtkSalGraphics::bNeedPixmapPaint = true; + int nScreens = GetGtkSalData()->GetGtkDisplay()->GetXScreenCount(); gWidgetData = WidgetDataVector( nScreens ); for( int i = 0; i < nScreens; i++ ) @@ -530,10 +549,6 @@ void GtkData::initNWF( void ) if( pEnv && *pEnv ) GtkSalGraphics::bNeedPixmapPaint = true; - // use offscreen rendering when using OpenGL backend - if( OpenGLHelper::isVCLOpenGLEnabled() ) - GtkSalGraphics::bNeedPixmapPaint = true; - #if OSL_DEBUG_LEVEL > 1 std::fprintf( stderr, "GtkPlugin: using %s NWF\n", GtkSalGraphics::bNeedPixmapPaint ? "offscreen" : "direct" ); @@ -864,8 +879,10 @@ bool GtkSalGraphics::drawNativeControl( ControlType nType, aClipRegion = aCtrlRect; clipList aClip; - GdkDrawable* gdkDrawable = GDK_DRAWABLE( GetGdkWindow() ); + int nPasses = 0; + GdkDrawable* gdkDrawable[2]; std::unique_ptr<GdkX11Pixmap> xPixmap; + std::unique_ptr<GdkX11Pixmap> xMask; Rectangle aPixmapRect; if( ( bNeedPixmapPaint ) && nType != CTRL_SCROLLBAR @@ -880,15 +897,22 @@ bool GtkSalGraphics::drawNativeControl( ControlType nType, // outside the rectangle, see e.g. checkbox aPixmapRect = Rectangle( Point( aCtrlRect.Left()-1, aCtrlRect.Top()-1 ), Size( aCtrlRect.GetWidth()+2, aCtrlRect.GetHeight()+2) ); - xPixmap.reset(NWGetPixmapFromScreen(aPixmapRect)); - if (!xPixmap) + + xPixmap.reset( NWGetPixmapFromScreen( aPixmapRect, BG_WHITE ) ); + xMask.reset( NWGetPixmapFromScreen( aPixmapRect, BG_BLACK ) ); + if( !xPixmap || !xMask ) return false; - gdkDrawable = xPixmap->GetGdkDrawable(); + nPasses = 2; + gdkDrawable[0] = xPixmap->GetGdkDrawable(); + gdkDrawable[1] = xMask->GetGdkDrawable(); + aCtrlRect = Rectangle( Point(1,1), aCtrlRect.GetSize() ); aClip.push_back( aCtrlRect ); } else { + nPasses = 1; + gdkDrawable[0] = GDK_DRAWABLE( GetGdkWindow() ); RectangleVector aRectangles; aClipRegion.GetRegionRectangles(aRectangles); @@ -901,68 +925,95 @@ bool GtkSalGraphics::drawNativeControl( ControlType nType, } } - assert(gdkDrawable && "rhbz#1050162"); - if (gdkDrawable == 0) - return false; + bool returnVal = false; + SAL_INFO( "vcl.opengl", "Rendering with " << nPasses << " passe(s)" ); + + for( int i = 0; i < nPasses; ++i ) + { + assert(gdkDrawable[i] && "rhbz#1050162"); + if( gdkDrawable[i] == 0 ) + return false; - bool returnVal = false; + returnVal = DoDrawNativeControl( gdkDrawable[i], nType, nPart, aCtrlRect, aClip, + nState, aValue, rCaption ); + if( !returnVal ) + break; + } + + if( xPixmap ) + returnVal = NWRenderPixmapToScreen( xPixmap.get(), xMask.get(), aPixmapRect) && returnVal; + + return( returnVal ); +} + + +bool GtkSalGraphics::DoDrawNativeControl( + GdkDrawable* pDrawable, + ControlType nType, + ControlPart nPart, + const Rectangle& aCtrlRect, + const clipList& aClip, + ControlState nState, + const ImplControlValue& aValue, + const OUString& rCaption ) +{ if ( (nType==CTRL_PUSHBUTTON) && (nPart==PART_ENTIRE_CONTROL) ) { - returnVal = NWPaintGTKButton( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKButton( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( (nType==CTRL_RADIOBUTTON) && (nPart==PART_ENTIRE_CONTROL) ) { - returnVal = NWPaintGTKRadio( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKRadio( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( (nType==CTRL_CHECKBOX) && (nPart==PART_ENTIRE_CONTROL) ) { - returnVal = NWPaintGTKCheck( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKCheck( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( (nType==CTRL_SCROLLBAR) && ((nPart==PART_DRAW_BACKGROUND_HORZ) || (nPart==PART_DRAW_BACKGROUND_VERT)) ) { - returnVal = NWPaintGTKScrollbar( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKScrollbar( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( ((nType==CTRL_EDITBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==HAS_BACKGROUND_TEXTURE)) ) || ((nType==CTRL_SPINBOX) && (nPart==HAS_BACKGROUND_TEXTURE)) || ((nType==CTRL_COMBOBOX) && (nPart==HAS_BACKGROUND_TEXTURE)) || ((nType==CTRL_LISTBOX) && (nPart==HAS_BACKGROUND_TEXTURE)) ) { - returnVal = NWPaintGTKEditBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKEditBox( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( ((nType==CTRL_MULTILINE_EDITBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==HAS_BACKGROUND_TEXTURE)) ) ) { - returnVal = NWPaintGTKEditBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKEditBox( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( ((nType==CTRL_SPINBOX) || (nType==CTRL_SPINBUTTONS)) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==PART_ALL_BUTTONS)) ) { - returnVal = NWPaintGTKSpinBox( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKSpinBox( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( (nType == CTRL_COMBOBOX) && ( (nPart==PART_ENTIRE_CONTROL) ||(nPart==PART_BUTTON_DOWN) ) ) { - returnVal = NWPaintGTKComboBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKComboBox( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( (nType==CTRL_TAB_ITEM) || (nType==CTRL_TAB_PANE) || (nType==CTRL_TAB_BODY) ) { if ( nType == CTRL_TAB_BODY ) - returnVal = true; + return true; else - returnVal = NWPaintGTKTabItem( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption); + return NWPaintGTKTabItem( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption); } else if ( (nType==CTRL_LISTBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==PART_WINDOW)) ) { - returnVal = NWPaintGTKListBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKListBox( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( nType== CTRL_TOOLBAR ) { - returnVal = NWPaintGTKToolbar( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKToolbar( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( nType== CTRL_MENUBAR ) { - returnVal = NWPaintGTKMenubar( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKMenubar( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if( (nType == CTRL_MENU_POPUP) && ( (nPart == PART_ENTIRE_CONTROL) @@ -974,55 +1025,50 @@ bool GtkSalGraphics::drawNativeControl( ControlType nType, ) ) { - returnVal = NWPaintGTKPopupMenu( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKPopupMenu( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if( (nType == CTRL_TOOLTIP) && (nPart == PART_ENTIRE_CONTROL) ) { - returnVal = NWPaintGTKTooltip( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKTooltip( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if( (nType == CTRL_PROGRESS) && (nPart == PART_ENTIRE_CONTROL) ) { - returnVal = NWPaintGTKProgress( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKProgress( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if( (nType == CTRL_LISTNODE) && (nPart == PART_ENTIRE_CONTROL) ) { - returnVal = NWPaintGTKListNode( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKListNode( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if( (nType == CTRL_LISTNET) && (nPart == PART_ENTIRE_CONTROL) ) { // don't actually draw anything; gtk treeviews do not draw lines - returnVal = TRUE; + return TRUE; } else if( nType == CTRL_SLIDER ) { - returnVal = NWPaintGTKSlider( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKSlider( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if( nType == CTRL_WINDOW_BACKGROUND ) { - returnVal = NWPaintGTKWindowBackground( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKWindowBackground( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if( nType == CTRL_FIXEDLINE ) { - returnVal = NWPaintGTKFixedLine( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKFixedLine( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if(nType==CTRL_FRAME) { - returnVal = NWPaintGTKFrame( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption); + return NWPaintGTKFrame( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption); } else if(nType==CTRL_LISTHEADER) { if(nPart == PART_BUTTON) - returnVal = NWPaintGTKListHeader( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKListHeader( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); else if(nPart == PART_ARROW) - returnVal = NWPaintGTKArrow( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKArrow( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } - if( xPixmap ) - { - returnVal = NWRenderPixmapToScreen(xPixmap.get(), aPixmapRect) && returnVal; - } - - return( returnVal ); + return false; } /* @@ -2114,7 +2160,7 @@ bool GtkSalGraphics::NWPaintGTKScrollbar( ControlType, ControlPart nPart, arrowRect.GetWidth(), arrowRect.GetHeight() ); } - bool bRet = NWRenderPixmapToScreen( pixmap, pixmapRect ); + bool bRet = NWRenderPixmapToScreen( pixmap, NULL, pixmapRect ); delete pixmap; return bRet; @@ -2341,8 +2387,6 @@ bool GtkSalGraphics::NWPaintGTKSpinBox( ControlType nType, ControlPart nPart, const ImplControlValue& aValue, const OUString& rCaption ) { - GdkX11Pixmap * pixmap; - GdkPixmap * gdkPixmap; Rectangle pixmapRect; GtkStateType stateType; GtkShadowType shadowType; @@ -2383,56 +2427,59 @@ bool GtkSalGraphics::NWPaintGTKSpinBox( ControlType nType, ControlPart nPart, else pixmapRect = rControlRectangle; - pixmap = NWGetPixmapFromScreen( pixmapRect ); - if ( !pixmap ) + std::unique_ptr<GdkX11Pixmap> pixmap( NWGetPixmapFromScreen( pixmapRect, BG_WHITE ) ); + std::unique_ptr<GdkX11Pixmap> mask( NWGetPixmapFromScreen( pixmapRect, BG_BLACK ) ); + if( !pixmap || !mask ) return false; - gdkPixmap = pixmap->GetGdkPixmap(); - // First render background - gtk_paint_flat_box(m_pWindow->style,gdkPixmap,GTK_STATE_NORMAL,GTK_SHADOW_NONE,NULL,m_pWindow,"base", - -pixmapRect.Left(), - -pixmapRect.Top(), - pixmapRect.Right(), - pixmapRect.Bottom() ); + for( int i = 0; i < 2; ++i ) + { + GdkPixmap* gdkPixmap = (i == 0) ? pixmap->GetGdkPixmap() + : mask->GetGdkPixmap(); - upBtnRect = NWGetSpinButtonRect( m_nXScreen, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption ); - downBtnRect = NWGetSpinButtonRect( m_nXScreen, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption ); + // First render background + gtk_paint_flat_box(m_pWindow->style,gdkPixmap,GTK_STATE_NORMAL,GTK_SHADOW_NONE,NULL,m_pWindow,"base", + -pixmapRect.Left(), + -pixmapRect.Top(), + pixmapRect.Right(), + pixmapRect.Bottom() ); - if ( (nType==CTRL_SPINBOX) && (nPart!=PART_ALL_BUTTONS) ) - { - // Draw an edit field for SpinBoxes and ComboBoxes - Rectangle aEditBoxRect( pixmapRect ); - aEditBoxRect.SetSize( Size( pixmapRect.GetWidth() - upBtnRect.GetWidth(), aEditBoxRect.GetHeight() ) ); - if( Application::GetSettings().GetLayoutRTL() ) - aEditBoxRect.setX( upBtnRect.GetWidth() ); - else - aEditBoxRect.setX( 0 ); - aEditBoxRect.setY( 0 ); + upBtnRect = NWGetSpinButtonRect( m_nXScreen, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption ); + downBtnRect = NWGetSpinButtonRect( m_nXScreen, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption ); - NWPaintOneEditBox( m_nXScreen, gdkPixmap, NULL, nType, nPart, aEditBoxRect, nState, aValue, rCaption ); - } + if ( (nType==CTRL_SPINBOX) && (nPart!=PART_ALL_BUTTONS) ) + { + // Draw an edit field for SpinBoxes and ComboBoxes + Rectangle aEditBoxRect( pixmapRect ); + aEditBoxRect.SetSize( Size( pixmapRect.GetWidth() - upBtnRect.GetWidth(), aEditBoxRect.GetHeight() ) ); + if( Application::GetSettings().GetLayoutRTL() ) + aEditBoxRect.setX( upBtnRect.GetWidth() ); + else + aEditBoxRect.setX( 0 ); + aEditBoxRect.setY( 0 ); - NWSetWidgetState( gWidgetData[m_nXScreen].gSpinButtonWidget, nState, stateType ); - gtk_widget_style_get( gWidgetData[m_nXScreen].gSpinButtonWidget, "shadow_type", &shadowType, (char *)NULL ); + NWPaintOneEditBox( m_nXScreen, gdkPixmap, NULL, nType, nPart, aEditBoxRect, nState, aValue, rCaption ); + } - if ( shadowType != GTK_SHADOW_NONE ) - { - Rectangle shadowRect( upBtnRect ); + NWSetWidgetState( gWidgetData[m_nXScreen].gSpinButtonWidget, nState, stateType ); + gtk_widget_style_get( gWidgetData[m_nXScreen].gSpinButtonWidget, "shadow_type", &shadowType, (char *)NULL ); - shadowRect.Union( downBtnRect ); - gtk_paint_box( gWidgetData[m_nXScreen].gSpinButtonWidget->style, gdkPixmap, GTK_STATE_NORMAL, shadowType, NULL, - gWidgetData[m_nXScreen].gSpinButtonWidget, "spinbutton", - (shadowRect.Left() - pixmapRect.Left()), (shadowRect.Top() - pixmapRect.Top()), - shadowRect.GetWidth(), shadowRect.GetHeight() ); - } + if ( shadowType != GTK_SHADOW_NONE ) + { + Rectangle shadowRect( upBtnRect ); - NWPaintOneSpinButton( m_nXScreen, gdkPixmap, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption ); - NWPaintOneSpinButton( m_nXScreen, gdkPixmap, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption ); + shadowRect.Union( downBtnRect ); + gtk_paint_box( gWidgetData[m_nXScreen].gSpinButtonWidget->style, gdkPixmap, GTK_STATE_NORMAL, shadowType, NULL, + gWidgetData[m_nXScreen].gSpinButtonWidget, "spinbutton", + (shadowRect.Left() - pixmapRect.Left()), (shadowRect.Top() - pixmapRect.Top()), + shadowRect.GetWidth(), shadowRect.GetHeight() ); + } - bool bRet = NWRenderPixmapToScreen( pixmap, pixmapRect ); - delete pixmap; + NWPaintOneSpinButton( m_nXScreen, gdkPixmap, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption ); + NWPaintOneSpinButton( m_nXScreen, gdkPixmap, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption ); + } - return bRet; + return NWRenderPixmapToScreen( pixmap.get(), mask.get(), pixmapRect ); } static Rectangle NWGetSpinButtonRect( SalX11Screen nScreen, @@ -2667,7 +2714,7 @@ bool GtkSalGraphics::NWPaintGTKTabItem( ControlType nType, ControlPart, { OSL_ASSERT( nType != CTRL_TAB_ITEM || aValue.getType() == CTRL_TAB_ITEM ); GdkX11Pixmap * pixmap; - GdkPixmap * gdkPixmap; + GdkX11Pixmap * mask; Rectangle pixmapRect; Rectangle tabRect; GtkStateType stateType; @@ -2730,83 +2777,88 @@ bool GtkSalGraphics::NWPaintGTKTabItem( ControlType nType, ControlPart, if( nType == CTRL_TAB_ITEM ) { - if( aCacheItems.Find( nType, nState, pixmapRect, &pixmap ) ) - return NWRenderPixmapToScreen( pixmap, pixmapRect ); + if( aCacheItems.Find( nType, nState, pixmapRect, &pixmap, &mask ) ) + return NWRenderPixmapToScreen( pixmap, mask, pixmapRect ); } else { - if( aCachePage.Find( nType, nState, pixmapRect, &pixmap ) ) - return NWRenderPixmapToScreen( pixmap, pixmapRect ); + if( aCachePage.Find( nType, nState, pixmapRect, &pixmap, &mask ) ) + return NWRenderPixmapToScreen( pixmap, mask, pixmapRect ); } - pixmap = new GdkX11Pixmap( pixmapRect.GetWidth(), pixmapRect.GetHeight(), - GetGenericData()->GetSalDisplay()->GetVisual( m_nXScreen ).GetDepth() ); - gdkPixmap = pixmap->GetGdkPixmap(); + 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(); - gtk_paint_flat_box( m_pWindow->style, gdkPixmap, GTK_STATE_NORMAL, - GTK_SHADOW_NONE, &paintRect, m_pWindow, "base", - -rControlRectangle.Left(), - -rControlRectangle.Top(), - pixmapRect.GetWidth()+rControlRectangle.Left(), - pixmapRect.GetHeight()+rControlRectangle.Top()); - - NWSetWidgetState( gWidgetData[m_nXScreen].gNotebookWidget, nState, stateType ); - - switch( nType ) + for( int i = 0; i < 2; ++i ) { - case CTRL_TAB_BODY: - break; + GdkPixmap* gdkPixmap = (i == 0) ? pixmap->GetGdkPixmap() : mask->GetGdkPixmap(); - case CTRL_TAB_PANE: - gtk_paint_box_gap( gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, gWidgetData[m_nXScreen].gNotebookWidget, - (char *)"notebook", 0, 0, pixmapRect.GetWidth(), pixmapRect.GetHeight(), GTK_POS_TOP, 0, 0 ); - break; + gtk_paint_flat_box( m_pWindow->style, gdkPixmap, GTK_STATE_NORMAL, + GTK_SHADOW_NONE, &paintRect, m_pWindow, "base", + -rControlRectangle.Left(), + -rControlRectangle.Top(), + pixmapRect.GetWidth()+rControlRectangle.Left(), + pixmapRect.GetHeight()+rControlRectangle.Top()); - case CTRL_TAB_ITEM: + NWSetWidgetState( gWidgetData[m_nXScreen].gNotebookWidget, nState, stateType ); + + switch( nType ) { - stateType = ( nState & CTRL_STATE_SELECTED ) ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE; + case CTRL_TAB_BODY: + break; - // First draw the background - gtk_paint_flat_box(gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, - GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, m_pWindow, "base", - -rControlRectangle.Left(), - -rControlRectangle.Top(), - pixmapRect.GetWidth()+rControlRectangle.Left(), - pixmapRect.GetHeight()+rControlRectangle.Top()); + case CTRL_TAB_PANE: + gtk_paint_box_gap( gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, gWidgetData[m_nXScreen].gNotebookWidget, + (char *)"notebook", 0, 0, pixmapRect.GetWidth(), pixmapRect.GetHeight(), GTK_POS_TOP, 0, 0 ); + break; - // Now the tab itself - if( nState & CTRL_STATE_ROLLOVER ) - g_object_set_data(G_OBJECT(gdkPixmap),tabPrelitDataName,reinterpret_cast<gpointer>(TRUE)); + case CTRL_TAB_ITEM: + { + stateType = ( nState & CTRL_STATE_SELECTED ) ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE; - gtk_paint_extension( gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, stateType, GTK_SHADOW_OUT, NULL, gWidgetData[m_nXScreen].gNotebookWidget, - (char *)"tab", (tabRect.Left() - pixmapRect.Left()), (tabRect.Top() - pixmapRect.Top()), - tabRect.GetWidth(), tabRect.GetHeight(), GTK_POS_BOTTOM ); + // First draw the background + gtk_paint_flat_box(gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, + GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, m_pWindow, "base", + -rControlRectangle.Left(), + -rControlRectangle.Top(), + pixmapRect.GetWidth()+rControlRectangle.Left(), + pixmapRect.GetHeight()+rControlRectangle.Top()); - g_object_steal_data(G_OBJECT(gdkPixmap),tabPrelitDataName); + // Now the tab itself + if( nState & CTRL_STATE_ROLLOVER ) + g_object_set_data(G_OBJECT(gdkPixmap),tabPrelitDataName,reinterpret_cast<gpointer>(TRUE)); - if ( nState & CTRL_STATE_SELECTED ) - { - gtk_paint_flat_box( m_pWindow->style, gdkPixmap, stateType, GTK_SHADOW_NONE, NULL, m_pWindow, - "base", 0, (pixmapRect.GetHeight() - 1), pixmapRect.GetWidth(), 1 ); + gtk_paint_extension( gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, stateType, GTK_SHADOW_OUT, NULL, gWidgetData[m_nXScreen].gNotebookWidget, + (char *)"tab", (tabRect.Left() - pixmapRect.Left()), (tabRect.Top() - pixmapRect.Top()), + tabRect.GetWidth(), tabRect.GetHeight(), GTK_POS_BOTTOM ); + + g_object_steal_data(G_OBJECT(gdkPixmap),tabPrelitDataName); + + if ( nState & CTRL_STATE_SELECTED ) + { + gtk_paint_flat_box( m_pWindow->style, gdkPixmap, stateType, GTK_SHADOW_NONE, NULL, m_pWindow, + "base", 0, (pixmapRect.GetHeight() - 1), pixmapRect.GetWidth(), 1 ); + } + break; } - break; - } - default: - break; + default: + break; + } } // cache data if( nType == CTRL_TAB_ITEM ) - aCacheItems.Fill( nType, nState, pixmapRect, pixmap ); + aCacheItems.Fill( nType, nState, pixmapRect, pixmap, mask ); else - aCachePage.Fill( nType, nState, pixmapRect, pixmap ); + aCachePage.Fill( nType, nState, pixmapRect, pixmap, mask ); - bool bSuccess = NWRenderPixmapToScreen( pixmap, pixmapRect ); + bool bSuccess = NWRenderPixmapToScreen( pixmap, mask, pixmapRect ); return bSuccess; } @@ -3382,24 +3434,26 @@ bool GtkSalGraphics::NWPaintGTKListNode( break; } - GdkX11Pixmap* pixmap = NWGetPixmapFromScreen( aRect ); - if( ! pixmap ) + std::unique_ptr<GdkX11Pixmap> pixmap( NWGetPixmapFromScreen( aRect, BG_WHITE ) ); + std::unique_ptr<GdkX11Pixmap> mask( NWGetPixmapFromScreen( aRect, BG_BLACK ) ); + if( !pixmap || !mask ) return false; - GdkDrawable* const &pixDrawable = pixmap->GetGdkDrawable(); - gtk_paint_expander( gWidgetData[m_nXScreen].gTreeView->style, - pixDrawable, - stateType, - NULL, - gWidgetData[m_nXScreen].gTreeView, - "treeview", - w/2, h/2, - eStyle ); - - bool bRet = NWRenderPixmapToScreen( pixmap, aRect ); - delete pixmap; + for( int i = 0; i < 2; ++i ) + { + GdkDrawable* const &pixDrawable = (i == 0) ? pixmap->GetGdkDrawable() + : mask->GetGdkDrawable(); + gtk_paint_expander( gWidgetData[m_nXScreen].gTreeView->style, + pixDrawable, + stateType, + NULL, + gWidgetData[m_nXScreen].gTreeView, + "treeview", + w/2, h/2, + eStyle ); + } - return bRet; + return NWRenderPixmapToScreen( pixmap.get(), mask.get(), aRect ); } bool GtkSalGraphics::NWPaintGTKProgress( @@ -3418,57 +3472,60 @@ bool GtkSalGraphics::NWPaintGTKProgress( long nProgressWidth = rValue.getNumericVal(); - GdkX11Pixmap* pixmap = NWGetPixmapFromScreen( Rectangle( Point( 0, 0 ), Size( w, h ) ) ); - if( ! pixmap ) + 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; - GdkDrawable* const &pixDrawable = pixmap->GetGdkDrawable(); - - // paint background - gtk_paint_flat_box(gWidgetData[m_nXScreen].gProgressBar->style, pixDrawable, - GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, m_pWindow, "base", - -rControlRectangle.Left(),-rControlRectangle.Top(), - rControlRectangle.Left()+w,rControlRectangle.Top()+h); - - gtk_paint_flat_box( gWidgetData[m_nXScreen].gProgressBar->style, - pixDrawable, - GTK_STATE_NORMAL, - GTK_SHADOW_NONE, - NULL, - gWidgetData[m_nXScreen].gProgressBar, - "trough", - 0, 0, w, h ); - if( nProgressWidth > 0 ) - { - // paint progress - if( Application::GetSettings().GetLayoutRTL() ) - { - gtk_paint_box( gWidgetData[m_nXScreen].gProgressBar->style, - pixDrawable, - GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, - NULL, - gWidgetData[m_nXScreen].gProgressBar, - "bar", - w-nProgressWidth, 0, nProgressWidth, h - ); - } - else + for( int i = 0; i < 2; ++i ) + { + 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", + -rControlRectangle.Left(),-rControlRectangle.Top(), + rControlRectangle.Left()+w,rControlRectangle.Top()+h); + + gtk_paint_flat_box( gWidgetData[m_nXScreen].gProgressBar->style, + pixDrawable, + GTK_STATE_NORMAL, + GTK_SHADOW_NONE, + NULL, + gWidgetData[m_nXScreen].gProgressBar, + "trough", + 0, 0, w, h ); + if( nProgressWidth > 0 ) { - gtk_paint_box( gWidgetData[m_nXScreen].gProgressBar->style, - pixDrawable, - GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, - NULL, - gWidgetData[m_nXScreen].gProgressBar, - "bar", - 0, 0, nProgressWidth, h - ); + // paint progress + if( Application::GetSettings().GetLayoutRTL() ) + { + gtk_paint_box( gWidgetData[m_nXScreen].gProgressBar->style, + pixDrawable, + GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, + NULL, + gWidgetData[m_nXScreen].gProgressBar, + "bar", + w-nProgressWidth, 0, nProgressWidth, h + ); + } + else + { + gtk_paint_box( gWidgetData[m_nXScreen].gProgressBar->style, + pixDrawable, + GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, + NULL, + gWidgetData[m_nXScreen].gProgressBar, + "bar", + 0, 0, nProgressWidth, h + ); + } } } - bool bRet = NWRenderPixmapToScreen( pixmap, rControlRectangle ); - delete pixmap; - - return bRet; + return NWRenderPixmapToScreen( pixmap.get(), mask.get(), rControlRectangle ); } bool GtkSalGraphics::NWPaintGTKSlider( @@ -3488,75 +3545,78 @@ bool GtkSalGraphics::NWPaintGTKSlider( const SliderValue* pVal = static_cast<const SliderValue*>(&rValue); - GdkX11Pixmap* pixmap = NWGetPixmapFromScreen( rControlRectangle ); - if( ! pixmap ) + std::unique_ptr<GdkX11Pixmap> pixmap( NWGetPixmapFromScreen( rControlRectangle, BG_WHITE ) ); + std::unique_ptr<GdkX11Pixmap> mask( NWGetPixmapFromScreen( rControlRectangle, BG_BLACK ) ); + if( !pixmap || !mask ) return false; - GdkDrawable* const &pixDrawable = pixmap->GetGdkDrawable(); - GtkWidget* pWidget = (nPart == PART_TRACK_HORZ_AREA) - ? GTK_WIDGET(gWidgetData[m_nXScreen].gHScale) - : GTK_WIDGET(gWidgetData[m_nXScreen].gVScale); - const gchar* pDetail = (nPart == PART_TRACK_HORZ_AREA) ? "hscale" : "vscale"; - GtkOrientation eOri = (nPart == PART_TRACK_HORZ_AREA) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; - gint slider_width = 10; - gint slider_length = 10; - gint trough_border = 0; - gtk_widget_style_get( pWidget, - "slider-width", &slider_width, - "slider-length", &slider_length, - "trough-border", &trough_border, - NULL); - - GtkStateType eState = (nState & CTRL_STATE_ENABLED) ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE; - if( nPart == PART_TRACK_HORZ_AREA ) - { - gtk_paint_box( pWidget->style, - pixDrawable, - eState, - GTK_SHADOW_IN, - NULL, - pWidget, - "trough", - 0, (h-slider_width-2*trough_border)/2, w, slider_width + 2*trough_border); - gint x = (w - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin); - gtk_paint_slider( pWidget->style, - pixDrawable, - eState, - GTK_SHADOW_OUT, - NULL, - pWidget, - pDetail, - x, (h-slider_width)/2, - slider_length, slider_width, - eOri ); - } - else + for( int i = 0; i < 2; ++i ) { - gtk_paint_box( pWidget->style, - pixDrawable, - eState, - GTK_SHADOW_IN, - NULL, - pWidget, - "trough", - (w-slider_width-2*trough_border)/2, 0, slider_width + 2*trough_border, h); - gint y = (h - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin); - gtk_paint_slider( pWidget->style, - pixDrawable, - eState, - GTK_SHADOW_OUT, - NULL, - pWidget, - pDetail, - (w-slider_width)/2, y, - slider_width, slider_length, - eOri ); - } - - bool bRet = NWRenderPixmapToScreen( pixmap, rControlRectangle ); - delete pixmap; + GdkDrawable* const &pixDrawable = (i == 0) ? pixmap->GetGdkDrawable() + : mask->GetGdkDrawable(); - return bRet; + GtkWidget* pWidget = (nPart == PART_TRACK_HORZ_AREA) + ? GTK_WIDGET(gWidgetData[m_nXScreen].gHScale) + : GTK_WIDGET(gWidgetData[m_nXScreen].gVScale); + const gchar* pDetail = (nPart == PART_TRACK_HORZ_AREA) ? "hscale" : "vscale"; + GtkOrientation eOri = (nPart == PART_TRACK_HORZ_AREA) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; + gint slider_width = 10; + gint slider_length = 10; + gint trough_border = 0; + gtk_widget_style_get( pWidget, + "slider-width", &slider_width, + "slider-length", &slider_length, + "trough-border", &trough_border, + NULL); + + GtkStateType eState = (nState & CTRL_STATE_ENABLED) ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE; + if( nPart == PART_TRACK_HORZ_AREA ) + { + gtk_paint_box( pWidget->style, + pixDrawable, + eState, + GTK_SHADOW_IN, + NULL, + pWidget, + "trough", + 0, (h-slider_width-2*trough_border)/2, w, slider_width + 2*trough_border); + gint x = (w - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin); + gtk_paint_slider( pWidget->style, + pixDrawable, + eState, + GTK_SHADOW_OUT, + NULL, + pWidget, + pDetail, + x, (h-slider_width)/2, + slider_length, slider_width, + eOri ); + } + else + { + gtk_paint_box( pWidget->style, + pixDrawable, + eState, + GTK_SHADOW_IN, + NULL, + pWidget, + "trough", + (w-slider_width-2*trough_border)/2, 0, slider_width + 2*trough_border, h); + gint y = (h - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin); + gtk_paint_slider( pWidget->style, + pixDrawable, + eState, ... etc. - the rest is truncated
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits