summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2020-09-22 12:48:10 +0200
committerCaolán McNamara <caolanm@redhat.com>2020-09-23 10:06:58 +0200
commit3ac3afcfd5615740fbaf9476792671fea2d940df (patch)
treed5b1edccaa9a48398e44759f3e2b17831e020234 /vcl
parent79b29b6edcdc5ef598056eb1d92084f27cf02f40 (diff)
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@collabora.com> (cherry picked from commit 19365e6e2b3311bacb2ae2abb70be5cfaf843776) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103188 Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/skia/gdiimpl.hxx4
-rw-r--r--vcl/inc/skia/win/gdiimpl.hxx2
-rw-r--r--vcl/inc/skia/x11/gdiimpl.hxx2
-rw-r--r--vcl/skia/SkiaHelper.cxx25
-rw-r--r--vcl/skia/gdiimpl.cxx35
-rw-r--r--vcl/skia/win/gdiimpl.cxx6
-rw-r--r--vcl/skia/x11/gdiimpl.cxx13
7 files changed, 46 insertions, 41 deletions
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>