diff options
author | Miklos Vajna <vmiklos@collabora.co.uk> | 2015-07-30 15:51:34 +0200 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2015-07-31 10:03:00 +0000 |
commit | a0f68343d1c0ae39de39194647e014555e3ed237 (patch) | |
tree | df4d52b8540c24b110483da663f36cbefc736e98 | |
parent | c618e888ca92afa2a301eebc5ce8de77f318d00a (diff) |
tdf#92982 vcl: stop creating/disposing the paint buffer in PaintHelper
Instead:
- create it early in Window::ImplInit(), except for the default window
(that one is a chicken-and-egg problem, as creating a VirtualDevice
invokes ImplGetDefaultWindow(), but creating the default window then
would create a VirtualDevice)
- only erase the painted area of the buffer, don't create it
- use a separate bool in the frame state to track if we're in the middle
of a (possibly recursive) buffered paint
And with that, rename CreateBuffer() to StartBufferedPaint(), as it does
not create the buffer anymore.
Change-Id: Ib33e8afa36977aa809f0ea2158a369f288cba8c7
(cherry picked from commit ea5e83abcfa1406c401b8a1ec91efda65373b74b)
Reviewed-on: https://gerrit.libreoffice.org/17445
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r-- | vcl/inc/window.h | 1 | ||||
-rw-r--r-- | vcl/source/window/paint.cxx | 33 | ||||
-rw-r--r-- | vcl/source/window/window.cxx | 3 |
3 files changed, 23 insertions, 14 deletions
diff --git a/vcl/inc/window.h b/vcl/inc/window.h index 5d39fc48ed77..60f9b1ae52ad 100644 --- a/vcl/inc/window.h +++ b/vcl/inc/window.h @@ -176,6 +176,7 @@ struct ImplFrameData bool mbInternalDragGestureRecognizer; VclPtr<VirtualDevice> mpBuffer; ///< Buffer for the double-buffering + bool mbInBufferedPaint; ///< PaintHelper is in the process of painting into this buffer. }; struct ImplAccessibleInfos diff --git a/vcl/source/window/paint.cxx b/vcl/source/window/paint.cxx index 8c6e6873f045..406c14110477 100644 --- a/vcl/source/window/paint.cxx +++ b/vcl/source/window/paint.cxx @@ -85,8 +85,8 @@ public: } void DoPaint(const vcl::Region* pRegion); - /// Create the buffer, and set it up to have the same settings as m_pWindow. - void CreateBuffer(); + /// Start buffered paint: set it up to have the same settings as m_pWindow. + void StartBufferedPaint(); /// Setup the buffer according to the settings of the current m_pWindow. void SetupBuffer(); @@ -107,12 +107,17 @@ PaintHelper::PaintHelper(vcl::Window *pWindow, sal_uInt16 nPaintFlags) { } -void PaintHelper::CreateBuffer() +void PaintHelper::StartBufferedPaint() { ImplFrameData* pFrameData = m_pWindow->mpWindowImpl->mpFrameData; - assert(!pFrameData->mpBuffer); + assert(!pFrameData->mbInBufferedPaint); - pFrameData->mpBuffer = VclPtrInstance<VirtualDevice>(); + // Instead of creating a new VirtualDevice, just erase the area we'll be + // painting over, as VirtualDevice::ImplInitVirDev() would do. + pFrameData->mpBuffer->SetBackground(Wallpaper(Color(COL_WHITE))); + pFrameData->mpBuffer->Erase(m_aPaintRect); + + pFrameData->mbInBufferedPaint = true; m_bCreatedBuffer = true; SetupBuffer(); @@ -164,7 +169,7 @@ void PaintHelper::SetupBuffer() void PaintHelper::PaintBuffer() { ImplFrameData* pFrameData = m_pWindow->mpWindowImpl->mpFrameData; - assert(pFrameData->mpBuffer); + assert(pFrameData->mbInBufferedPaint); assert(m_bCreatedBuffer); pFrameData->mpBuffer->mnOutOffX = 0; @@ -178,7 +183,7 @@ void PaintHelper::PaintBuffer() if (!getenv("VCL_DOUBLEBUFFERING_AVOID_PAINT")) { // The map mode of m_pWindow and/or the buffer may have changed since - // CreateBuffer(), set it back to what it was, otherwise unwanted + // StartBufferedPaint(), set it back to what it was, otherwise unwanted // scaling or translating may happen. m_pWindow->SetMapMode(m_aPaintRectMapMode); pFrameData->mpBuffer->SetMapMode(m_aPaintRectMapMode); @@ -204,7 +209,7 @@ void PaintHelper::DoPaint(const vcl::Region* pRegion) WindowImpl* pWindowImpl = m_pWindow->ImplGetWindowImpl(); vcl::Region* pWinChildClipRegion = m_pWindow->ImplGetWinChildClipRegion(); ImplFrameData* pFrameData = m_pWindow->mpWindowImpl->mpFrameData; - if (pWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL || pFrameData->mpBuffer) + if (pWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL || pFrameData->mbInBufferedPaint) { pWindowImpl->maInvalidateRegion = *pWinChildClipRegion; } @@ -231,16 +236,16 @@ void PaintHelper::DoPaint(const vcl::Region* pRegion) m_pWindow->BeginPaint(); // double-buffering: setup the buffer if it does not exist - if (!pFrameData->mpBuffer && m_pWindow->SupportsDoubleBuffering()) - CreateBuffer(); + if (!pFrameData->mbInBufferedPaint && m_pWindow->SupportsDoubleBuffering()) + StartBufferedPaint(); // double-buffering: if this window does not support double-buffering, // but we are in the middle of double-buffered paint, we might be // losing information - if (pFrameData->mpBuffer && !m_pWindow->SupportsDoubleBuffering()) + if (pFrameData->mbInBufferedPaint && !m_pWindow->SupportsDoubleBuffering()) SAL_WARN("vcl.doublebuffering", "non-double buffered window in the double-buffered hierarchy, painting directly: " << typeid(*m_pWindow.get()).name()); - if (pFrameData->mpBuffer && m_pWindow->SupportsDoubleBuffering()) + if (pFrameData->mbInBufferedPaint && m_pWindow->SupportsDoubleBuffering()) { // double-buffering SetupBuffer(); @@ -518,10 +523,10 @@ PaintHelper::~PaintHelper() // double-buffering: paint in case we created the buffer, the children are // already painted inside - if (m_bCreatedBuffer && pFrameData->mpBuffer) + if (m_bCreatedBuffer && pFrameData->mbInBufferedPaint) { PaintBuffer(); - pFrameData->mpBuffer.disposeAndClear(); + pFrameData->mbInBufferedPaint = false; } // #98943# draw toolbox selection diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index 6e3e60e6eabf..f24e4bb2c52d 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -1072,6 +1072,9 @@ void Window::ImplInit( vcl::Window* pParent, WinBits nStyle, SystemParentData* p mpWindowImpl->mpFrameData->maResizeIdle.SetIdleHdl( LINK( this, Window, ImplHandleResizeTimerHdl ) ); mpWindowImpl->mpFrameData->maResizeIdle.SetDebugName( "vcl::Window maResizeIdle" ); mpWindowImpl->mpFrameData->mbInternalDragGestureRecognizer = false; + if (!(nStyle & WB_DEFAULTWIN) && SupportsDoubleBuffering()) + mpWindowImpl->mpFrameData->mpBuffer = VclPtrInstance<VirtualDevice>(); + mpWindowImpl->mpFrameData->mbInBufferedPaint = false; if ( pRealParent && IsTopWindow() ) { |