diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2020-01-20 12:10:00 +0100 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2020-01-20 16:02:46 +0100 |
commit | ad3580df085b3a3d66eb73cae997ea5ca178ccc1 (patch) | |
tree | dd2d4508ed1f1cf37805ae9a2cfca6d831fcfac7 /vcl | |
parent | e0e0f634987c52a040e1514825d239013b05e7b2 (diff) |
workaround for Skia+Cairo text drawing exhausting GPU memory
See the description in SkiaSalGraphicsImpl::postDraw().
Change-Id: Ia6b38741fcfe3f6b5f0a21051886c55ed5324c61
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/87062
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/skia/gdiimpl.hxx | 1 | ||||
-rw-r--r-- | vcl/skia/gdiimpl.cxx | 16 | ||||
-rw-r--r-- | vcl/skia/win/gdiimpl.cxx | 1 | ||||
-rw-r--r-- | vcl/skia/x11/gdiimpl.cxx | 1 |
4 files changed, 19 insertions, 0 deletions
diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index f1ddc20bdf01..10b6371b4dcd 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -277,6 +277,7 @@ protected: std::unique_ptr<SkCanvas> mXorCanvas; SkRect mXorExtents; // the area that needs updating for the xor operation (or empty for all) std::unique_ptr<SkiaFlushIdle> mFlush; + int mPendingPixelsToFlush; }; #endif diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index a88f78823382..66086c9af82b 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -177,6 +177,7 @@ SkiaSalGraphicsImpl::SkiaSalGraphicsImpl(SalGraphics& rParent, SalGeometryProvid , mFillColor(SALCOLOR_NONE) , mXorMode(false) , mFlush(new SkiaFlushIdle(this)) + , mPendingPixelsToFlush(0) { } @@ -375,6 +376,20 @@ void SkiaSalGraphicsImpl::postDraw() else if (!mFlush->IsActive()) mFlush->Start(); } + // Skia (at least when using Vulkan) queues drawing commands and executes them only later. + // But some operations may queue way too much data to draw, leading to Vulkan getting out of memory, + // which at least on Linux leads to driver problems affecting even the whole X11 session. + // One such problematic operation may be drawBitmap(SkBitmap), which is used by SkiaX11CairoTextRender + // to draw text, which is internally done by creating the SkBitmap from cairo surface data. Apparently + // the cairo surface's size matches the size of the destination (window), which may be large, + // and each text drawing allocates a new surface (and thus SkBitmap). So we may end up queueing up + // millions of pixels of bitmap data. So force a flush if such a possibly problematic operation + // has queued up too much data. + if (mPendingPixelsToFlush > 10 * 1024 * 1024) + { + mSurface->flush(); + mPendingPixelsToFlush = 0; + } } // VCL can sometimes resize us without telling us, update the surface if needed. @@ -1125,6 +1140,7 @@ void SkiaSalGraphicsImpl::drawBitmap(const SalTwoRect& rPosAry, const SkBitmap& getDrawCanvas()->drawBitmapRect(aBitmap, aSourceRect, aDestinationRect, &aPaint); if (mXorMode) // limit xor area update mXorExtents = aDestinationRect; + mPendingPixelsToFlush += aBitmap.width() * aBitmap.height(); postDraw(); } diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index deace0072630..e9889415cc5e 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -57,6 +57,7 @@ void WinSkiaSalGraphicsImpl::freeResources() {} void WinSkiaSalGraphicsImpl::performFlush() { + mPendingPixelsToFlush = 0; if (mWindowContext) mWindowContext->swapBuffers(); } diff --git a/vcl/skia/x11/gdiimpl.cxx b/vcl/skia/x11/gdiimpl.cxx index 04e2586e7f7a..a139a336c7b7 100644 --- a/vcl/skia/x11/gdiimpl.cxx +++ b/vcl/skia/x11/gdiimpl.cxx @@ -107,6 +107,7 @@ void X11SkiaSalGraphicsImpl::freeResources() {} void X11SkiaSalGraphicsImpl::performFlush() { + mPendingPixelsToFlush = 0; // TODO XPutImage() is somewhat inefficient, XShmPutImage() should be preferred. mWindowContext->swapBuffers(); } |