summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vcl/Library_vcl.mk1
-rw-r--r--vcl/inc/skia/zone.hxx30
-rw-r--r--vcl/skia/SkiaHelper.cxx7
-rw-r--r--vcl/skia/gdiimpl.cxx12
-rw-r--r--vcl/skia/salbmp.cxx7
-rw-r--r--vcl/skia/win/gdiimpl.cxx7
-rw-r--r--vcl/skia/x11/gdiimpl.cxx4
-rw-r--r--vcl/skia/zone.cxx58
-rw-r--r--vcl/source/app/svmain.cxx5
-rw-r--r--vcl/source/app/watchdog.cxx7
10 files changed, 138 insertions, 0 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 16be92968a92..6728447a7817 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -592,6 +592,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
$(if $(filter SKIA,$(BUILD_TYPE)), \
vcl/skia/packedsurfaceatlas \
vcl/skia/salbmp \
+ vcl/skia/zone \
vcl/skia/gdiimpl) \
))
diff --git a/vcl/inc/skia/zone.hxx b/vcl/inc/skia/zone.hxx
new file mode 100644
index 000000000000..1f6bbb0dddca
--- /dev/null
+++ b/vcl/inc/skia/zone.hxx
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_VCL_INC_SKIA_ZONE_H
+#define INCLUDED_VCL_INC_SKIA_ZONE_H
+
+#include <comphelper/crashzone.hxx>
+
+#include <vcl/dllapi.h>
+
+// Used around calls to Skia code to detect crashes in drivers.
+class VCL_DLLPUBLIC SkiaZone : public CrashZone<SkiaZone>
+{
+public:
+ static void hardDisable();
+ static void relaxWatchdogTimings();
+ static const CrashWatchdogTimingsValues& getCrashWatchdogTimingsValues();
+ static void checkDebug(int nUnchanged, const CrashWatchdogTimingsValues& aTimingValues);
+ static const char* name() { return "Skia"; }
+};
+
+#endif // INCLUDED_VCL_INC_SKIA_ZONE_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx
index 20bf299cfb56..281fdaf65f77 100644
--- a/vcl/skia/SkiaHelper.cxx
+++ b/vcl/skia/SkiaHelper.cxx
@@ -12,6 +12,8 @@
#include <vcl/svapp.hxx>
#include <desktop/crashreport.hxx>
#include <officecfg/Office/Common.hxx>
+#include <watchdog.hxx>
+#include <skia/zone.hxx>
#if !HAVE_FEATURE_SKIA
@@ -94,6 +96,9 @@ bool isVCLSkiaEnabled()
bRet = bEnable;
}
+ if (bRet)
+ WatchdogThread::start();
+
CrashReporter::addKeyValue("UseSkia", OUString::boolean(bRet), CrashReporter::Write);
return bRet;
@@ -135,6 +140,7 @@ static sk_app::VulkanWindowContext::SharedGrContext* sharedGrContext;
GrContext* getSharedGrContext()
{
+ SkiaZone zone;
assert(renderMethodToUse() == RenderVulkan);
if (sharedGrContext)
return sharedGrContext->getGrContext();
@@ -157,6 +163,7 @@ GrContext* getSharedGrContext()
sk_sp<SkSurface> createSkSurface(int width, int height, SkColorType type)
{
+ SkiaZone zone;
assert(type == kN32_SkColorType || type == kAlpha_8_SkColorType);
sk_sp<SkSurface> surface;
switch (SkiaHelper::renderMethodToUse())
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index 7ec10165f5d0..a1d8c00674d8 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -26,6 +26,7 @@
#include <vcl/lazydelete.hxx>
#include <vcl/skia/SkiaHelper.hxx>
#include <skia/utils.hxx>
+#include <skia/zone.hxx>
#include <SkCanvas.h>
#include <SkPath.h>
@@ -197,6 +198,7 @@ void SkiaSalGraphicsImpl::recreateSurface()
void SkiaSalGraphicsImpl::createSurface()
{
+ SkiaZone zone;
if (isOffscreen())
createOffscreenSurface();
else
@@ -211,6 +213,7 @@ void SkiaSalGraphicsImpl::createSurface()
void SkiaSalGraphicsImpl::createWindowSurface()
{
+ SkiaZone zone;
assert(!isOffscreen());
assert(!mSurface);
assert(!mWindowContext);
@@ -239,6 +242,7 @@ void SkiaSalGraphicsImpl::createWindowSurface()
void SkiaSalGraphicsImpl::createOffscreenSurface()
{
+ SkiaZone zone;
assert(isOffscreen());
assert(!mSurface);
assert(!mWindowContext);
@@ -284,6 +288,7 @@ void SkiaSalGraphicsImpl::createOffscreenSurface()
void SkiaSalGraphicsImpl::destroySurface()
{
+ SkiaZone zone;
if (mSurface)
{
// check setClipRegion() invariant
@@ -309,6 +314,7 @@ void SkiaSalGraphicsImpl::DeInit() { destroySurface(); }
void SkiaSalGraphicsImpl::preDraw()
{
+ SkiaZone::enter(); // matched in postDraw()
checkSurface();
assert(!mXorMode || mXorExtents.isEmpty()); // must be reset in postDraw()
}
@@ -390,6 +396,7 @@ void SkiaSalGraphicsImpl::postDraw()
mSurface->flush();
mPendingPixelsToFlush = 0;
}
+ SkiaZone::leave(); // matched in preDraw()
}
// VCL can sometimes resize us without telling us, update the surface if needed.
@@ -420,6 +427,7 @@ bool SkiaSalGraphicsImpl::setClipRegion(const vcl::Region& region)
{
if (mClipRegion == region)
return true;
+ SkiaZone zone;
mClipRegion = region;
checkSurface();
SAL_INFO("vcl.skia", "setclipregion(" << this << "): " << region);
@@ -438,6 +446,7 @@ bool SkiaSalGraphicsImpl::setClipRegion(const vcl::Region& region)
void SkiaSalGraphicsImpl::setCanvasClipRegion(SkCanvas* canvas, const vcl::Region& region)
{
+ SkiaZone zone;
SkPath path;
// Handle polygons last, since rectangle->polygon area conversions
// are problematic (see addPolygonToPath() comment).
@@ -485,6 +494,7 @@ void SkiaSalGraphicsImpl::SetXORMode(bool set, bool)
SkCanvas* SkiaSalGraphicsImpl::getXorCanvas()
{
+ SkiaZone zone;
assert(mXorMode);
// Skia does not implement xor drawing, so we need to handle it manually by redirecting
// to a temporary SkBitmap and then doing the xor operation on the data ourselves.
@@ -960,6 +970,7 @@ void SkiaSalGraphicsImpl::drawMask(const SalTwoRect& rPosAry, const sk_sp<SkImag
std::shared_ptr<SalBitmap> SkiaSalGraphicsImpl::getBitmap(long nX, long nY, long nWidth,
long nHeight)
{
+ SkiaZone zone;
checkSurface();
SAL_INFO("vcl.skia",
"getbitmap(" << this << "): " << Point(nX, nY) << "/" << Size(nWidth, nHeight));
@@ -973,6 +984,7 @@ std::shared_ptr<SalBitmap> SkiaSalGraphicsImpl::getBitmap(long nX, long nY, long
Color SkiaSalGraphicsImpl::getPixel(long nX, long nY)
{
+ SkiaZone zone;
checkSurface();
SAL_INFO("vcl.skia", "getpixel(" << this << "): " << Point(nX, nY));
mSurface->getCanvas()->flush();
diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx
index b321f4c3f6f7..c354b1e34e4b 100644
--- a/vcl/skia/salbmp.cxx
+++ b/vcl/skia/salbmp.cxx
@@ -34,6 +34,7 @@
#include <SkSurface.h>
#include <skia/utils.hxx>
+#include <skia/zone.hxx>
#ifdef DBG_UTIL
#include <fstream>
@@ -331,6 +332,7 @@ bool SkiaSalBitmap::ScalingSupported() const { return true; }
bool SkiaSalBitmap::Scale(const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag)
{
+ SkiaZone zone;
#ifdef DBG_UTIL
assert(mWriteAccessCount == 0);
#endif
@@ -399,6 +401,7 @@ SkBitmap SkiaSalBitmap::GetAsSkBitmap() const
EnsureBitmapData();
if (!mBitmap.isNull())
return mBitmap;
+ SkiaZone zone;
SkBitmap bitmap;
if (mBuffer)
{
@@ -452,6 +455,7 @@ const sk_sp<SkImage>& SkiaSalBitmap::GetSkImage() const
#endif
if (mImage)
return mImage;
+ SkiaZone zone;
sk_sp<SkSurface> surface = SkiaHelper::createSkSurface(mSize);
assert(surface);
SkPaint paint;
@@ -469,6 +473,7 @@ const sk_sp<SkImage>& SkiaSalBitmap::GetAlphaSkImage() const
#endif
if (mAlphaImage)
return mAlphaImage;
+ SkiaZone zone;
// TODO can we convert directly mImage -> mAlphaImage?
EnsureBitmapData();
SkBitmap alphaBitmap;
@@ -538,6 +543,7 @@ void SkiaSalBitmap::EnsureBitmapData()
return;
if (!mImage)
return;
+ SkiaZone zone;
if (!CreateBitmapData())
abort();
if (!mBitmap.isNull())
@@ -627,6 +633,7 @@ void SkiaSalBitmap::EnsureBitmapUniqueData()
void SkiaSalBitmap::ResetSkImages()
{
+ SkiaZone zone;
mAlphaImage.reset();
mImage.reset();
}
diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx
index aec2f22e5bb3..0d459be03722 100644
--- a/vcl/skia/win/gdiimpl.cxx
+++ b/vcl/skia/win/gdiimpl.cxx
@@ -12,6 +12,7 @@
#include <win/saldata.hxx>
#include <vcl/skia/SkiaHelper.hxx>
#include <skia/utils.hxx>
+#include <skia/zone.hxx>
#include <SkColorFilter.h>
#include <SkPixelRef.h>
@@ -27,6 +28,7 @@ WinSkiaSalGraphicsImpl::WinSkiaSalGraphicsImpl(WinSalGraphics& rGraphics,
void WinSkiaSalGraphicsImpl::createWindowContext()
{
+ SkiaZone zone;
// When created, Init() gets called with size (0,0), which is invalid size
// for Skia. Creating the actual surface is delayed, so the size should be always
// valid here, but better check.
@@ -49,6 +51,7 @@ void WinSkiaSalGraphicsImpl::createWindowContext()
void WinSkiaSalGraphicsImpl::DeInit()
{
+ SkiaZone zone;
SkiaSalGraphicsImpl::DeInit();
mWindowContext.reset();
}
@@ -57,6 +60,7 @@ void WinSkiaSalGraphicsImpl::freeResources() {}
void WinSkiaSalGraphicsImpl::performFlush()
{
+ SkiaZone zone;
mPendingPixelsToFlush = 0;
if (mWindowContext)
mWindowContext->swapBuffers();
@@ -158,6 +162,7 @@ std::unique_ptr<CompatibleDC::Texture> SkiaCompatibleDC::getAsMaskTexture() cons
sk_sp<SkImage> SkiaCompatibleDC::getAsMaskImage() const
{
+ SkiaZone zone;
// mpData is in the BGRA format, with A unused (and set to 0), and RGB are grey,
// so convert it to Skia format, then to 8bit and finally use as alpha mask
SkBitmap tmpBitmap;
@@ -200,6 +205,7 @@ sk_sp<SkImage> SkiaCompatibleDC::getAsMaskImage() const
sk_sp<SkImage> SkiaCompatibleDC::getAsImage() const
{
+ SkiaZone zone;
SkBitmap tmpBitmap;
if (!tmpBitmap.installPixels(SkImageInfo::Make(maRects.mnSrcWidth, maRects.mnSrcHeight,
kBGRA_8888_SkColorType, kUnpremul_SkAlphaType),
@@ -225,6 +231,7 @@ sk_sp<SkImage> SkiaCompatibleDC::getAsImage() const
sk_sp<SkImage> SkiaCompatibleDC::getAsImageDiff(const SkiaCompatibleDC& white) const
{
+ SkiaZone zone;
assert(maRects.mnSrcWidth == white.maRects.mnSrcWidth
|| maRects.mnSrcHeight == white.maRects.mnSrcHeight);
SkBitmap tmpBitmap;
diff --git a/vcl/skia/x11/gdiimpl.cxx b/vcl/skia/x11/gdiimpl.cxx
index a139a336c7b7..503eeee3fa32 100644
--- a/vcl/skia/x11/gdiimpl.cxx
+++ b/vcl/skia/x11/gdiimpl.cxx
@@ -22,6 +22,7 @@
#include <tools/sk_app/WindowContext.h>
#include <vcl/skia/SkiaHelper.hxx>
+#include <skia/zone.hxx>
X11SkiaSalGraphicsImpl::X11SkiaSalGraphicsImpl(X11SalGraphics& rParent)
: SkiaSalGraphicsImpl(rParent, rParent.GetGeometryProvider())
@@ -40,6 +41,7 @@ void X11SkiaSalGraphicsImpl::Init()
void X11SkiaSalGraphicsImpl::createWindowContext()
{
+ SkiaZone zone;
sk_app::DisplayParams displayParams;
displayParams.fColorType = kN32_SkColorType;
sk_app::window_context_factory::XlibWindowInfo winInfo;
@@ -99,6 +101,7 @@ bool X11SkiaSalGraphicsImpl::avoidRecreateByResize() const
void X11SkiaSalGraphicsImpl::DeInit()
{
+ SkiaZone zone;
SkiaSalGraphicsImpl::DeInit();
mWindowContext.reset();
}
@@ -107,6 +110,7 @@ void X11SkiaSalGraphicsImpl::freeResources() {}
void X11SkiaSalGraphicsImpl::performFlush()
{
+ SkiaZone zone;
mPendingPixelsToFlush = 0;
// TODO XPutImage() is somewhat inefficient, XShmPutImage() should be preferred.
mWindowContext->swapBuffers();
diff --git a/vcl/skia/zone.cxx b/vcl/skia/zone.cxx
new file mode 100644
index 000000000000..82b45620ce1c
--- /dev/null
+++ b/vcl/skia/zone.cxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <skia/zone.hxx>
+
+#include <officecfg/Office/Common.hxx>
+#include <com/sun/star/util/XFlushable.hpp>
+#include <com/sun/star/configuration/theDefaultProvider.hpp>
+
+#include <sal/log.hxx>
+
+/**
+ * Called from a signal handler or watchdog thread if we get
+ * a crash or hang in some driver.
+ */
+void SkiaZone::hardDisable()
+{
+ // protect ourselves from double calling etc.
+ static bool bDisabled = false;
+ if (!bDisabled)
+ {
+ bDisabled = true;
+
+ // Disable Skia support
+ std::shared_ptr<comphelper::ConfigurationChanges> xChanges(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::VCL::UseSkia::set(false, xChanges);
+ xChanges->commit();
+
+ // Force synchronous config write
+ css::uno::Reference<css::util::XFlushable>(
+ css::configuration::theDefaultProvider::get(comphelper::getProcessComponentContext()),
+ css::uno::UNO_QUERY_THROW)
+ ->flush();
+ }
+}
+
+void SkiaZone::checkDebug(int nUnchanged, const CrashWatchdogTimingsValues& aTimingValues)
+{
+ SAL_INFO("vcl.watchdog", "Skia watchdog - unchanged "
+ << nUnchanged << " enter count " << enterCount()
+ << " breakpoints mid: " << aTimingValues.mnDisableEntries
+ << " max " << aTimingValues.mnAbortAfter);
+}
+
+const CrashWatchdogTimingsValues& SkiaZone::getCrashWatchdogTimingsValues()
+{
+ static const CrashWatchdogTimingsValues values = { 6, 20 }; /* 1.5s, 5s */
+ return values;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx
index 207a6ff4eaad..6c3cd630561c 100644
--- a/vcl/source/app/svmain.cxx
+++ b/vcl/source/app/svmain.cxx
@@ -88,6 +88,7 @@
#include <opencl/OpenCLZone.hxx>
#include <opengl/zone.hxx>
+#include <skia/zone.hxx>
#include <watchdog.hxx>
#include <basegfx/utils/systemdependentdata.hxx>
@@ -123,6 +124,10 @@ static oslSignalAction VCLExceptionSignal_impl( void* /*pData*/, oslSignalInfo*
if (OpenGLZone::isInZone())
OpenGLZone::hardDisable();
#endif
+#if HAVE_FEATURE_SKIA
+ if (SkiaZone::isInZone())
+ SkiaZone::hardDisable();
+#endif
#if HAVE_FEATURE_OPENCL
if (OpenCLZone::isInZone())
{
diff --git a/vcl/source/app/watchdog.cxx b/vcl/source/app/watchdog.cxx
index 795501ec45ac..bd8b28db89e6 100644
--- a/vcl/source/app/watchdog.cxx
+++ b/vcl/source/app/watchdog.cxx
@@ -17,6 +17,7 @@
#include <sal/log.hxx>
#include <comphelper/debuggerinfo.hxx>
#include <opengl/zone.hxx>
+#include <skia/zone.hxx>
#include <stdlib.h>
@@ -107,12 +108,18 @@ void WatchdogThread::execute()
#if HAVE_FEATURE_OPENGL
WatchdogHelper<OpenGLZone>::setLastEnters();
#endif
+#if HAVE_FEATURE_SKIA
+ WatchdogHelper<SkiaZone>::setLastEnters();
+#endif
gpWatchdogExit->wait(&aQuarterSecond);
#if HAVE_FEATURE_OPENGL
WatchdogHelper<OpenGLZone>::check();
#endif
+#if HAVE_FEATURE_SKIA
+ WatchdogHelper<SkiaZone>::check();
+#endif
} while (!gpWatchdogExit->check());
}