Kaydet (Commit) a0f68343 authored tarafından Miklos Vajna's avatar Miklos Vajna Kaydeden (comit) Tomaž Vajngerl

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 ea5e83ab)
Reviewed-on: https://gerrit.libreoffice.org/17445Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarTomaž Vajngerl <quikee@gmail.com>
üst c618e888
......@@ -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
......
......@@ -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
......
......@@ -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() )
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment