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:03 +0000 |
commit | 26c32cfee9fc9a769adba19f455e4d6c13b6d89d (patch) | |
tree | a043c4170d92d25924cf7dc7ab22ca3ca2d24414 /drawinglayer | |
parent | 22a35a56b385b1a08d20eb609f35ab506cc8333e (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
Diffstat (limited to 'drawinglayer')
-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(); } } |