diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2022-01-11 19:08:50 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2022-01-26 12:59:39 +0100 |
commit | 7c29b13ac67e3796b5998789371fa68acb01a260 (patch) | |
tree | c563254986e85a2c5433aed59a3be45ea8999077 /vcl/headless | |
parent | d243e9dbfb8497bed03601a04f168bc1832ce263 (diff) |
avoid Xlib cairo surfaces for small virtual devices (bsc#1183308)
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 <l.lunak@collabora.com>
(cherry picked from commit cf9be3417bc2be5f772c03180b7cbd248b82cad5)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128815
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl/headless')
-rw-r--r-- | vcl/headless/svpvd.cxx | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/vcl/headless/svpvd.cxx b/vcl/headless/svpvd.cxx index f8e9cb5e6874..21d231b229e9 100644 --- a/vcl/headless/svpvd.cxx +++ b/vcl/headless/svpvd.cxx @@ -76,29 +76,42 @@ void SvpSalVirtualDevice::CreateSurface(tools::Long nNewDX, tools::Long nNewDY, cairo_surface_destroy(m_pSurface); } + double fXScale, fYScale; + if (comphelper::LibreOfficeKit::isActive()) + { + // Force scaling of the painting + fXScale = fYScale = comphelper::LibreOfficeKit::getDPIScale(); + } + else + { + dl_cairo_surface_get_device_scale(m_pRefSurface, &fXScale, &fYScale); + } + if (pBuffer) { - double fXScale, fYScale; - if (comphelper::LibreOfficeKit::isActive()) - { - // Force scaling of the painting - fXScale = fYScale = comphelper::LibreOfficeKit::getDPIScale(); - } - else - { - dl_cairo_surface_get_device_scale(m_pRefSurface, &fXScale, &fYScale); - nNewDX *= fXScale; - nNewDY *= fYScale; - } + nNewDX *= fXScale; + nNewDY *= fYScale; m_pSurface = cairo_image_surface_create_for_data(pBuffer, CAIRO_FORMAT_ARGB32, nNewDX, nNewDY, cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, nNewDX)); - + dl_cairo_surface_set_device_scale(m_pSurface, fXScale, fYScale); + } + else if(nNewDX <= 32 && nNewDY <= 32) + { + nNewDX *= fXScale; + nNewDY *= fYScale; + + // Force image-based surface if small. Small VirtualDevice instances are often used for small + // temporary bitmaps that will eventually have GetBitmap() called on them, which would cause + // X Server roundtrip with Xlib-based surface, which may be way more costly than doing the drawing + // in software (which should be fairly cheap for small surfaces anyway). + m_pSurface = cairo_surface_create_similar_image(m_pRefSurface, CAIRO_FORMAT_ARGB32, nNewDX, nNewDY); dl_cairo_surface_set_device_scale(m_pSurface, fXScale, fYScale); } else { m_pSurface = cairo_surface_create_similar(m_pRefSurface, CAIRO_CONTENT_COLOR_ALPHA, nNewDX, nNewDY); + // Device scale is inherited in this case. } } |