From cf9be3417bc2be5f772c03180b7cbd248b82cad5 Mon Sep 17 00:00:00 2001 From: Luboš Luňák Date: Tue, 11 Jan 2022 19:08:50 +0100 Subject: avoid Xlib cairo surfaces for small virtual devices (bsc#1183308) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The (private :( ) document contains a large number of small shapes for which VclProcessor2D::RenderTransparencePrimitive2D() gets called, which results in GetBitmapEx() on the VirtualDevice. And Cairo normally needs to do a roundtrip to the XServer to fetch the content, which makes the rendering pretty slow. Forcing image-based surface for small sizes of VirtualDevice actually has better performance for the document, and the lack of possible HW acceleration generally shouldn't matter for a surface this small. Additionally drawinglayer's VirtualDevice reusing tries to reuse even a large one when a small one is needed, so a hack is needed to avoid that in this case, I couldn't find a better way. Change-Id: I0f58659ab88165a6bd915f100fc3b1d4802a0fa9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128309 Tested-by: Jenkins Reviewed-by: Luboš Luňák --- .../source/processor2d/vclhelperbufferdevice.cxx | 34 +++++++++++++++++----- 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'drawinglayer') diff --git a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx index 9129271bcb6b..7f20d094b446 100644 --- a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx +++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx @@ -63,6 +63,8 @@ private: // virtualdevice because that isn't safe to do at least for Gtk2 std::map, VclPtr> maDeviceTemplates; + static bool isSizeSuitable(const VclPtr& device, const Size& size); + public: VDevBuffer(); virtual ~VDevBuffer() override; @@ -98,6 +100,28 @@ VDevBuffer::~VDevBuffer() } } +bool VDevBuffer::isSizeSuitable(const VclPtr& device, const Size& rSizePixel) +{ + if (device->GetOutputWidthPixel() >= rSizePixel.getWidth() + && device->GetOutputHeightPixel() >= rSizePixel.getHeight()) + { +#if defined(UNX) + // HACK: See the small size handling in SvpSalVirtualDevice::CreateSurface(). + // Make sure to not reuse a larger device when a small one should be preferred. + if (device->GetRenderBackendName() == "svp") + { + if (rSizePixel.getWidth() <= 32 && rSizePixel.getHeight() <= 32 + && (device->GetOutputWidthPixel() > 32 || device->GetOutputHeightPixel() > 32)) + { + return false; + } + } +#endif + return true; + } + return false; +} + VclPtr VDevBuffer::alloc(OutputDevice& rOutDev, const Size& rSizePixel, bool bTransparent) { @@ -124,9 +148,7 @@ VclPtr VDevBuffer::alloc(OutputDevice& rOutDev, const Size& rSize if (bOkay) { // found is valid - const bool bCandidateOkay( - a->buf->GetOutputWidthPixel() >= rSizePixel.getWidth() - && a->buf->GetOutputHeightPixel() >= rSizePixel.getHeight()); + const bool bCandidateOkay = isSizeSuitable(a->buf, rSizePixel); if (bCandidateOkay) { @@ -151,16 +173,14 @@ VclPtr VDevBuffer::alloc(OutputDevice& rOutDev, const Size& rSize { // found is invalid, use candidate aFound = a; - bOkay = aFound->buf->GetOutputWidthPixel() >= rSizePixel.getWidth() - && aFound->buf->GetOutputHeightPixel() >= rSizePixel.getHeight(); + bOkay = isSizeSuitable(aFound->buf, rSizePixel); } } else { // none yet, use candidate aFound = a; - bOkay = aFound->buf->GetOutputWidthPixel() >= rSizePixel.getWidth() - && aFound->buf->GetOutputHeightPixel() >= rSizePixel.getHeight(); + bOkay = isSizeSuitable(aFound->buf, rSizePixel); } } } -- cgit