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 3ac3afcfd5615740fbaf9476792671fea2d940df Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Tue Sep 22 12:48:10 2020 +0200 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Wed Sep 23 10:06:58 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.lu...@collabora.com> (cherry picked from commit 19365e6e2b3311bacb2ae2abb70be5cfaf843776) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103188 Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index 06f84e5b5b3e..5b72e4b4e249 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -231,8 +231,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 aeea89a081f1..3e02ef29cea2 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -390,11 +390,15 @@ sk_sp<SkSurface> createSkSurface(int width, int height, SkColorType type) surface = SkSurface::MakeRenderTarget( grContext, 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; } @@ -422,11 +426,16 @@ sk_sp<SkImage> createSkImage(const SkBitmap& bitmap) { sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget( grContext, 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 0555cb9549f6..a34bb4f0d4c1 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -280,13 +280,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) @@ -294,16 +294,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 @@ -326,13 +325,12 @@ void SkiaSalGraphicsImpl::createOffscreenSurface() if (SkiaHelper::getSharedGrContext()) { 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: @@ -1082,7 +1080,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. @@ -1090,7 +1089,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 @@ -1119,7 +1119,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(); } @@ -1155,7 +1155,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 c42bd79fa22a..b79ed5f9c8f6 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 93025c0ef7d1..1602218c16ac 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> _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits