diff options
author | Caolán McNamara <caolanm@redhat.com> | 2015-11-27 16:10:10 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2015-11-27 16:29:26 +0000 |
commit | aab8bed7c0c0cf4d72af7d8a9d84316280887417 (patch) | |
tree | 8cedab00a4080c1284ff944d245fb53fd3c9b299 | |
parent | ff2bdd52f54db24f867957a3293fae08e6a431a3 (diff) |
Resolves: rhbz#1283426 using vdevs based on now dead physical devs is unsafe
This is the same problem that
commit 133e04fc1a870c0aad207e82eefeeeceaba5dc6d
Author: Caolán McNamara <caolanm@redhat.com>
Date: Wed Jun 17 09:23:32 2015 +0100
Resolves: tdf#91880 Invalidate graphics when the gtk window is destroyed
not just when the GtkSalFrame is dtored
tried to fix, but that just made it more unlikely to fail
Change-Id: Icba750c787adb6cd5c5ed0874ef07e6201c4cf25
(cherry picked from commit 26c32cfee9fc9a769adba19f455e4d6c13b6d89d)
-rw-r--r-- | drawinglayer/source/processor2d/vclhelperbufferdevice.cxx | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx index e7ff5a1b0daa..fde5ba9a1de6 100644 --- a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx +++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx @@ -43,6 +43,11 @@ namespace // allocated/used buffers (remembered to allow deleting them in destructor) aBuffers maUsedBuffers; + // remember what outputdevice was the template passed to VirtualDevice::Create + // so we can test if that OutputDevice was disposed before reusing a + // virtualdevice because that isn't safe to do at least for Gtk2 + std::map< VclPtr<VirtualDevice>, VclPtr<OutputDevice> > maDeviceTemplates; + public: VDevBuffer(); virtual ~VDevBuffer(); @@ -87,14 +92,14 @@ namespace sal_Int32 nBits = bMonoChrome ? 1 : rOutDev.GetBitCount(); + bool bOkay(false); if(!maFreeBuffers.empty()) { - bool bOkay(false); aBuffers::iterator aFound(maFreeBuffers.end()); for(aBuffers::iterator a(maFreeBuffers.begin()); a != maFreeBuffers.end(); ++a) { - OSL_ENSURE(*a, "Empty pointer in VDevBuffer (!)"); + assert(*a && "Empty pointer in VDevBuffer (!)"); if (nBits == (*a)->GetBitCount()) { @@ -144,10 +149,25 @@ namespace { pRetval = *aFound; maFreeBuffers.erase(aFound); + } + } - if(bOkay) + if (pRetval) + { + // found a suitable cached virtual device, but the + // outputdevice it was based on has been disposed, + // drop it and create a new one instead as reusing + // such devices is unsafe under at least Gtk2 + if (maDeviceTemplates[pRetval]->isDisposed()) + { + maDeviceTemplates.erase(pRetval); + pRetval = nullptr; + } + else + { + if (bOkay) { - if(bClear) + if (bClear) { pRetval->Erase(Rectangle(0, 0, rSizePixel.getWidth(), rSizePixel.getHeight())); } @@ -163,6 +183,7 @@ namespace if(!pRetval) { pRetval = VclPtr<VirtualDevice>::Create(rOutDev, bMonoChrome ? DeviceFormat::BITMASK : DeviceFormat::DEFAULT); + maDeviceTemplates[pRetval] = &rOutDev; pRetval->SetOutputSizePixel(rSizePixel, bClear); } else @@ -196,7 +217,9 @@ namespace while(!maFreeBuffers.empty()) { - (*(maFreeBuffers.end() - 1)).disposeAndClear(); + aBuffers::iterator aLastOne(maFreeBuffers.end() - 1); + maDeviceTemplates.erase(*aLastOne); + aLastOne->disposeAndClear(); maFreeBuffers.pop_back(); } } |