[Libreoffice-commits] core.git: vcl/inc vcl/skia

Luboš Luňák (via logerrit) logerrit at kemper.freedesktop.org
Mon Jan 20 15:03:16 UTC 2020


 vcl/inc/skia/gdiimpl.hxx |    1 +
 vcl/skia/gdiimpl.cxx     |   16 ++++++++++++++++
 vcl/skia/win/gdiimpl.cxx |    1 +
 vcl/skia/x11/gdiimpl.cxx |    1 +
 4 files changed, 19 insertions(+)

New commits:
commit ad3580df085b3a3d66eb73cae997ea5ca178ccc1
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Mon Jan 20 12:10:00 2020 +0100
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Mon Jan 20 16:02:46 2020 +0100

    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 at collabora.com>

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();
 }


More information about the Libreoffice-commits mailing list