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

Luboš Luňák (via logerrit) logerrit at kemper.freedesktop.org
Wed Sep 23 06:46:33 UTC 2020


 vcl/inc/skia/gdiimpl.hxx     |    4 ++--
 vcl/inc/skia/win/gdiimpl.hxx |    2 +-
 vcl/inc/skia/x11/gdiimpl.hxx |    2 +-
 vcl/skia/SkiaHelper.cxx      |   25 +++++++++++++++++--------
 vcl/skia/gdiimpl.cxx         |   35 ++++++++++++++++++-----------------
 vcl/skia/win/gdiimpl.cxx     |    6 ++----
 vcl/skia/x11/gdiimpl.cxx     |   13 +++++--------
 7 files changed, 46 insertions(+), 41 deletions(-)

New commits:
commit 19365e6e2b3311bacb2ae2abb70be5cfaf843776
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Tue Sep 22 12:48:10 2020 +0200
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Wed Sep 23 08:45:47 2020 +0200

    if allocating Vulkan surface fails, fall back to Skia raster surface
    
    Occassionally there may be very large surfaces, such as
    in tdf#135952. Try to fall back to raster, which is more likely to
    succeed, given that it uses system RAM instead of video RAM.
    
    Change-Id: I81994b174e5e52066eacc5f8778e9469b042f9c8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103170
    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 9405bc39ade2..2d8086639a08 100644
--- a/vcl/inc/skia/gdiimpl.hxx
+++ b/vcl/inc/skia/gdiimpl.hxx
@@ -235,8 +235,8 @@ protected:
     void destroySurface();
     // Reimplemented for X11.
     virtual bool avoidRecreateByResize() const { return false; }
-    void createWindowSurface();
-    virtual void createWindowContext() = 0;
+    void createWindowSurface(bool forceRaster = false);
+    virtual void createWindowContext(bool forceRaster = false) = 0;
     void createOffscreenSurface();
 
     void privateDrawAlphaRect(long nX, long nY, long nWidth, long nHeight, double nTransparency,
diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx
index cdb6977e5bd2..564fcd7e9614 100644
--- a/vcl/inc/skia/win/gdiimpl.hxx
+++ b/vcl/inc/skia/win/gdiimpl.hxx
@@ -71,7 +71,7 @@ public:
     static void prepareSkia();
 
 protected:
-    virtual void createWindowContext() override;
+    virtual void createWindowContext(bool forceRaster = false) override;
     virtual void performFlush() override;
     sk_sp<SkTypeface> createDirectWriteTypeface(const LOGFONTW& logFont);
     SkFont::Edging getFontEdging();
diff --git a/vcl/inc/skia/x11/gdiimpl.hxx b/vcl/inc/skia/x11/gdiimpl.hxx
index 0f86f0907dcd..d131d54bfe8e 100644
--- a/vcl/inc/skia/x11/gdiimpl.hxx
+++ b/vcl/inc/skia/x11/gdiimpl.hxx
@@ -34,7 +34,7 @@ public:
     static void prepareSkia();
 
 private:
-    virtual void createWindowContext() override;
+    virtual void createWindowContext(bool forceRaster = false) override;
     virtual void performFlush() override;
     virtual bool avoidRecreateByResize() const override;
     static std::unique_ptr<sk_app::WindowContext>
diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx
index 72944a946c71..e029a9137429 100644
--- a/vcl/skia/SkiaHelper.cxx
+++ b/vcl/skia/SkiaHelper.cxx
@@ -395,11 +395,15 @@ sk_sp<SkSurface> createSkSurface(int width, int height, SkColorType type)
                 surface = SkSurface::MakeRenderTarget(
                     grDirectContext, SkBudgeted::kNo,
                     SkImageInfo::Make(width, height, type, kPremul_SkAlphaType));
-                assert(surface);
+                if (surface)
+                {
 #ifdef DBG_UTIL
-                prefillSurface(surface);
+                    prefillSurface(surface);
 #endif
-                return surface;
+                    return surface;
+                }
+                SAL_WARN("vcl.skia",
+                         "cannot create Vulkan GPU offscreen surface, falling back to Raster");
             }
             break;
         }
@@ -428,11 +432,16 @@ sk_sp<SkImage> createSkImage(const SkBitmap& bitmap)
                 sk_sp<SkSurface> surface
                     = SkSurface::MakeRenderTarget(grDirectContext, SkBudgeted::kNo,
                                                   bitmap.info().makeAlphaType(kPremul_SkAlphaType));
-                assert(surface);
-                SkPaint paint;
-                paint.setBlendMode(SkBlendMode::kSrc); // set as is, including alpha
-                surface->getCanvas()->drawBitmap(bitmap, 0, 0, &paint);
-                return surface->makeImageSnapshot();
+                if (surface)
+                {
+                    SkPaint paint;
+                    paint.setBlendMode(SkBlendMode::kSrc); // set as is, including alpha
+                    surface->getCanvas()->drawBitmap(bitmap, 0, 0, &paint);
+                    return surface->makeImageSnapshot();
+                }
+                // Try to fall back in non-debug builds.
+                SAL_WARN("vcl.skia",
+                         "cannot create Vulkan GPU offscreen surface, falling back to Raster");
             }
             break;
         }
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index 8f73db8411fa..1821f48a7cce 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -289,13 +289,13 @@ void SkiaSalGraphicsImpl::createSurface()
     mFlush->SetPriority(TaskPriority::POST_PAINT);
 }
 
-void SkiaSalGraphicsImpl::createWindowSurface()
+void SkiaSalGraphicsImpl::createWindowSurface(bool forceRaster)
 {
     SkiaZone zone;
     assert(!isOffscreen());
     assert(!mSurface);
     assert(!mWindowContext);
-    createWindowContext();
+    createWindowContext(forceRaster);
     if (mWindowContext)
         mSurface = mWindowContext->getBackbufferSurface();
     if (!mSurface)
@@ -303,16 +303,15 @@ void SkiaSalGraphicsImpl::createWindowSurface()
         switch (SkiaHelper::renderMethodToUse())
         {
             case SkiaHelper::RenderVulkan:
-                SAL_WARN("vcl.skia", "cannot create Vulkan GPU window surface, disabling Vulkan");
-                // fall back to raster
-                SkiaHelper::disableRenderMethod(SkiaHelper::RenderVulkan);
+                SAL_WARN("vcl.skia",
+                         "cannot create Vulkan GPU window surface, falling back to Raster");
                 destroySurface(); // destroys also WindowContext
-                return createWindowSurface(); // try again
+                return createWindowSurface(true); // try again
             case SkiaHelper::RenderRaster:
                 abort(); // this should not really happen
         }
     }
-    assert((mSurface->getCanvas()->getGrContext() != nullptr) == mIsGPU);
+    mIsGPU = mSurface->getCanvas()->getGrContext() != nullptr;
 #ifdef DBG_UTIL
     SkiaHelper::prefillSurface(mSurface);
 #endif
@@ -335,13 +334,12 @@ void SkiaSalGraphicsImpl::createOffscreenSurface()
             if (SkiaHelper::getSharedGrDirectContext())
             {
                 mSurface = SkiaHelper::createSkSurface(width, height);
-                assert(mSurface);
-                assert(mSurface->getCanvas()->getGrContext()); // is GPU-backed
-                mIsGPU = true;
-                return;
+                if (mSurface)
+                {
+                    mIsGPU = mSurface->getCanvas()->getGrContext() != nullptr;
+                    return;
+                }
             }
-            SAL_WARN("vcl.skia", "cannot create Vulkan offscreen GPU surface, disabling Vulkan");
-            SkiaHelper::disableRenderMethod(SkiaHelper::RenderVulkan);
             break;
         }
         default:
@@ -1098,7 +1096,8 @@ bool SkiaSalGraphicsImpl::drawPolyPolygonBezier(sal_uInt32, const sal_uInt32*,
 }
 
 static void copyArea(SkCanvas* canvas, sk_sp<SkSurface> surface, long nDestX, long nDestY,
-                     long nSrcX, long nSrcY, long nSrcWidth, long nSrcHeight, bool srcIsRaster)
+                     long nSrcX, long nSrcY, long nSrcWidth, long nSrcHeight, bool srcIsRaster,
+                     bool destIsRaster)
 {
     // Using SkSurface::draw() should be more efficient than SkSurface::makeImageSnapshot(),
     // because it may detect copying to itself and avoid some needless copies.
@@ -1106,7 +1105,8 @@ static void copyArea(SkCanvas* canvas, sk_sp<SkSurface> surface, long nDestX, lo
     // (https://groups.google.com/forum/#!topic/skia-discuss/6yiuw24jv0I) and also
     // raster surfaces do not avoid a copy of the source
     // (https://groups.google.com/forum/#!topic/skia-discuss/S3FMpCi82k0).
-    if (canvas == surface->getCanvas() || srcIsRaster)
+    // Finally, there's not much point if one of them is raster and the other is not (chrome/m86 even crashes).
+    if (canvas == surface->getCanvas() || srcIsRaster || (srcIsRaster != destIsRaster))
     {
         SkPaint paint;
         paint.setBlendMode(SkBlendMode::kSrc); // copy as is, including alpha
@@ -1135,7 +1135,7 @@ void SkiaSalGraphicsImpl::copyArea(long nDestX, long nDestY, long nSrcX, long nS
                                    << SkIRect::MakeXYWH(nDestX, nDestY, nSrcWidth, nSrcHeight));
     assert(!mXorMode);
     ::copyArea(getDrawCanvas(), mSurface, nDestX, nDestY, nSrcX, nSrcY, nSrcWidth, nSrcHeight,
-               !isGPU());
+               !isGPU(), !isGPU());
     addXorRegion(SkRect::MakeXYWH(nDestX, nDestY, nSrcWidth, nSrcHeight));
     postDraw();
 }
@@ -1171,7 +1171,8 @@ void SkiaSalGraphicsImpl::copyBits(const SalTwoRect& rPosAry, SalGraphics* pSrcG
         SAL_INFO("vcl.skia.trace",
                  "copybits(" << this << "): " << srcDebug() << " copy area: " << rPosAry);
         ::copyArea(getDrawCanvas(), src->mSurface, rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnSrcX,
-                   rPosAry.mnSrcY, rPosAry.mnDestWidth, rPosAry.mnDestHeight, !src->isGPU());
+                   rPosAry.mnSrcY, rPosAry.mnDestWidth, rPosAry.mnDestHeight, !src->isGPU(),
+                   !isGPU());
     }
     else
     {
diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx
index ea7cb3362386..5c5582b8ffe6 100644
--- a/vcl/skia/win/gdiimpl.cxx
+++ b/vcl/skia/win/gdiimpl.cxx
@@ -35,21 +35,19 @@ WinSkiaSalGraphicsImpl::WinSkiaSalGraphicsImpl(WinSalGraphics& rGraphics,
 {
 }
 
-void WinSkiaSalGraphicsImpl::createWindowContext()
+void WinSkiaSalGraphicsImpl::createWindowContext(bool forceRaster)
 {
     SkiaZone zone;
     sk_app::DisplayParams displayParams;
-    switch (SkiaHelper::renderMethodToUse())
+    switch (forceRaster ? SkiaHelper::RenderRaster : SkiaHelper::renderMethodToUse())
     {
         case SkiaHelper::RenderRaster:
             mWindowContext = sk_app::window_context_factory::MakeRasterForWin(mWinParent.gethWnd(),
                                                                               displayParams);
-            mIsGPU = false;
             break;
         case SkiaHelper::RenderVulkan:
             mWindowContext = sk_app::window_context_factory::MakeVulkanForWin(mWinParent.gethWnd(),
                                                                               displayParams);
-            mIsGPU = true;
             break;
     }
 }
diff --git a/vcl/skia/x11/gdiimpl.cxx b/vcl/skia/x11/gdiimpl.cxx
index 0f430c4f8100..7a55415ee55a 100644
--- a/vcl/skia/x11/gdiimpl.cxx
+++ b/vcl/skia/x11/gdiimpl.cxx
@@ -40,16 +40,13 @@ void X11SkiaSalGraphicsImpl::Init()
     SkiaSalGraphicsImpl::Init();
 }
 
-void X11SkiaSalGraphicsImpl::createWindowContext()
+void X11SkiaSalGraphicsImpl::createWindowContext(bool forceRaster)
 {
     assert(mX11Parent.GetDrawable() != None);
-    mWindowContext = createWindowContext(mX11Parent.GetXDisplay(), mX11Parent.GetDrawable(),
-                                         &mX11Parent.GetVisual(), GetWidth(), GetHeight(),
-                                         SkiaHelper::renderMethodToUse(), false);
-    if (mWindowContext && SkiaHelper::renderMethodToUse() == SkiaHelper::RenderVulkan)
-        mIsGPU = true;
-    else
-        mIsGPU = false;
+    mWindowContext = createWindowContext(
+        mX11Parent.GetXDisplay(), mX11Parent.GetDrawable(), &mX11Parent.GetVisual(), GetWidth(),
+        GetHeight(), forceRaster ? SkiaHelper::RenderRaster : SkiaHelper::renderMethodToUse(),
+        false);
 }
 
 std::unique_ptr<sk_app::WindowContext>


More information about the Libreoffice-commits mailing list