summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2020-02-06 15:48:14 +0100
committerLuboš Luňák <l.lunak@collabora.com>2020-02-10 10:09:42 +0100
commit3081998ada2ad60d14f8b2343309fe79776f898a (patch)
treea1d43b40191cbfaa56d5c80732875c22cb780aae /vcl
parentc060c80496429d59bb6f158c44957d853dccb06c (diff)
add (Vulkan) blacklisting to Skia
Currently there's nothing blacklisted, but this is the code. And there's not much point in blacklisting CPU-based raster Skia, so check only for Vulkan. Since this requires accessing Vulkan to get the driver info, this commit also reorganizes a bit getting a GrContext when there's no actual window, so that it's usable for the test. Change-Id: I042af0470fb635d8ea471a40837bfcd102d7016f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88205 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/skia/utils.hxx4
-rw-r--r--vcl/inc/skia/x11/gdiimpl.hxx5
-rw-r--r--vcl/skia/SkiaHelper.cxx81
-rw-r--r--vcl/skia/gdiimpl.cxx16
-rw-r--r--vcl/skia/x11/gdiimpl.cxx63
5 files changed, 125 insertions, 44 deletions
diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx
index 6fd61afd0a05..af81ca99f2dd 100644
--- a/vcl/inc/skia/utils.hxx
+++ b/vcl/inc/skia/utils.hxx
@@ -42,6 +42,10 @@ inline sk_sp<SkSurface> createSkSurface(const Size& size, SkColorType type = kN3
return createSkSurface(size.Width(), size.Height(), type);
}
+/// This function is in the X11/Win backend libs, but needs to be used in SkiaHelper in the vcl lib.
+VCL_DLLPUBLIC void
+ setCreateVulkanWindowContext(std::unique_ptr<sk_app::WindowContext> (*function)());
+
#ifdef DBG_UTIL
void prefillSurface(sk_sp<SkSurface>& surface);
VCL_DLLPUBLIC void dump(const SkBitmap& bitmap, const char* file);
diff --git a/vcl/inc/skia/x11/gdiimpl.hxx b/vcl/inc/skia/x11/gdiimpl.hxx
index ad131f64c973..8cedf23d3e1b 100644
--- a/vcl/inc/skia/x11/gdiimpl.hxx
+++ b/vcl/inc/skia/x11/gdiimpl.hxx
@@ -15,6 +15,7 @@
#include <unx/salgdi.h>
#include <unx/x11/x11gdiimpl.h>
#include <skia/gdiimpl.hxx>
+#include <skia/utils.hxx>
class VCL_PLUGIN_PUBLIC X11SkiaSalGraphicsImpl final : public SkiaSalGraphicsImpl,
public X11GraphicsImpl
@@ -34,6 +35,10 @@ private:
virtual void createWindowContext() override;
virtual void performFlush() override;
virtual bool avoidRecreateByResize() const override;
+ static std::unique_ptr<sk_app::WindowContext>
+ createWindowContext(Display* display, Drawable drawable, const SalVisual* visual, int width,
+ int height, SkiaHelper::RenderMethod renderMethod);
+ friend std::unique_ptr<sk_app::WindowContext> createVulkanWindowContext();
};
#endif // INCLUDED_VCL_INC_SKIA_X11_GDIIMPL_HXX
diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx
index 281fdaf65f77..00eafbaf54c4 100644
--- a/vcl/skia/SkiaHelper.cxx
+++ b/vcl/skia/SkiaHelper.cxx
@@ -14,6 +14,7 @@
#include <officecfg/Office/Common.hxx>
#include <watchdog.hxx>
#include <skia/zone.hxx>
+#include <sal/log.hxx>
#if !HAVE_FEATURE_SKIA
@@ -28,7 +29,6 @@ bool isVCLSkiaEnabled() { return false; }
#include <skia/utils.hxx>
#include <SkSurface.h>
-#include <tools/sk_app/VulkanWindowContext.h>
#ifdef DBG_UTIL
#include <fstream>
@@ -36,14 +36,55 @@ bool isVCLSkiaEnabled() { return false; }
namespace SkiaHelper
{
-static bool supportsVCLSkia()
+static bool isVulkanBlacklisted(const VkPhysicalDeviceProperties& props)
{
- static bool bDisableSkia = !!getenv("SAL_DISABLESKIA");
- bool bBlacklisted = false; // TODO isDeviceBlacklisted();
+ static const char* const types[]
+ = { "other", "integrated", "discrete", "virtual", "cpu", "??" }; // VkPhysicalDeviceType
+ SAL_INFO("vcl.skia",
+ "Vulkan API version: "
+ << (props.apiVersion >> 22) << "." << ((props.apiVersion >> 12) & 0x3ff) << "."
+ << (props.apiVersion & 0xfff) << ", driver version: " << std::hex
+ << props.driverVersion << ", vendor:" << props.vendorID
+ << ", device: " << props.deviceID << std::dec
+ << ", type: " << types[std::min<unsigned>(props.deviceType, SAL_N_ELEMENTS(types))]
+ << ", name: " << props.deviceName);
+ return false;
+}
- return !bDisableSkia && !bBlacklisted;
+static void checkDeviceBlacklisted()
+{
+ static bool done = false;
+ if (!done)
+ {
+ SkiaZone zone;
+
+ switch (renderMethodToUse())
+ {
+ case RenderVulkan:
+ {
+ GrContext* grContext = SkiaHelper::getSharedGrContext();
+ bool blacklisted = true; // assume the worst
+ if (grContext) // Vulkan was initialized properly
+ {
+ blacklisted = isVulkanBlacklisted(
+ sk_app::VulkanWindowContext::getPhysDeviceProperties());
+ SAL_INFO("vcl.skia", "Vulkan blacklisted: " << blacklisted);
+ }
+ else
+ SAL_INFO("vcl.skia", "Vulkan could not be initialized");
+ if (blacklisted)
+ disableRenderMethod(RenderVulkan);
+ break;
+ }
+ case RenderRaster:
+ return; // software, never blacklisted
+ }
+ done = true;
+ }
}
+static bool supportsVCLSkia() { return !getenv("SAL_DISABLESKIA"); }
+
bool isVCLSkiaEnabled()
{
/**
@@ -93,6 +134,9 @@ bool isVCLSkiaEnabled()
if (Application::IsSafeModeEnabled())
bEnable = false;
+ if (bEnable)
+ checkDeviceBlacklisted(); // switch to raster if driver is blacklisted
+
bRet = bEnable;
}
@@ -138,6 +182,12 @@ void disableRenderMethod(RenderMethod method)
static sk_app::VulkanWindowContext::SharedGrContext* sharedGrContext;
+static std::unique_ptr<sk_app::WindowContext> (*createVulkanWindowContextFunction)() = nullptr;
+void setCreateVulkanWindowContext(std::unique_ptr<sk_app::WindowContext> (*function)())
+{
+ createVulkanWindowContextFunction = function;
+}
+
GrContext* getSharedGrContext()
{
SkiaZone zone;
@@ -145,7 +195,7 @@ GrContext* getSharedGrContext()
if (sharedGrContext)
return sharedGrContext->getGrContext();
// TODO mutex?
- // Setup the shared GrContext from Skia's (patched) VulkanWindowContext, if it's been
+ // Set up the shared GrContext from Skia's (patched) VulkanWindowContext, if it's been
// already set up.
sk_app::VulkanWindowContext::SharedGrContext context
= sk_app::VulkanWindowContext::getSharedGrContext();
@@ -155,9 +205,22 @@ GrContext* getSharedGrContext()
sharedGrContext = new sk_app::VulkanWindowContext::SharedGrContext(context);
return grContext;
}
- // TODO
- // SkiaSalGraphicsImpl::createOffscreenSurface() creates the shared context using a dummy window,
- // but we do not have a window here. Is it worth it to try to do it here?
+ static bool done = false;
+ if (done)
+ return nullptr;
+ done = true;
+ if (!createVulkanWindowContextFunction)
+ return nullptr;
+ std::unique_ptr<sk_app::WindowContext> tmpContext = createVulkanWindowContextFunction();
+ // Set up using the shared context created by the call above, if successful.
+ context = sk_app::VulkanWindowContext::getSharedGrContext();
+ grContext = context.getGrContext();
+ if (grContext)
+ {
+ sharedGrContext = new sk_app::VulkanWindowContext::SharedGrContext(context);
+ return grContext;
+ }
+ disableRenderMethod(RenderVulkan);
return nullptr;
}
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index b2d4a050f796..dd7431a2662b 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -252,21 +252,7 @@ void SkiaSalGraphicsImpl::createOffscreenSurface()
{
case SkiaHelper::RenderVulkan:
{
- GrContext* grContext = SkiaHelper::getSharedGrContext();
- // We may not get a GrContext if called before any onscreen window is created.
- if (!grContext)
- {
- SAL_INFO("vcl.skia",
- "creating Vulkan offscreen GPU surface before any window exists");
- // Create temporary WindowContext with no window. That will fail,
- // but it will initialize the shared GrContext.
- createWindowContext();
- // This will use the temporarily created context.
- grContext = SkiaHelper::getSharedGrContext();
- // Destroy the temporary WindowContext.
- destroySurface();
- }
- if (grContext)
+ if (SkiaHelper::getSharedGrContext())
{
mSurface = SkiaHelper::createSkSurface(GetWidth(), GetHeight());
assert(mSurface);
diff --git a/vcl/skia/x11/gdiimpl.cxx b/vcl/skia/x11/gdiimpl.cxx
index 503eeee3fa32..c587b143ef69 100644
--- a/vcl/skia/x11/gdiimpl.cxx
+++ b/vcl/skia/x11/gdiimpl.cxx
@@ -19,9 +19,8 @@
#include <skia/x11/gdiimpl.hxx>
#include <tools/sk_app/unix/WindowContextFactory_unix.h>
-#include <tools/sk_app/WindowContext.h>
-#include <vcl/skia/SkiaHelper.hxx>
+#include <skia/utils.hxx>
#include <skia/zone.hxx>
X11SkiaSalGraphicsImpl::X11SkiaSalGraphicsImpl(X11SalGraphics& rParent)
@@ -41,18 +40,32 @@ void X11SkiaSalGraphicsImpl::Init()
void X11SkiaSalGraphicsImpl::createWindowContext()
{
+ assert(mX11Parent.GetDrawable() != None);
+ mWindowContext = createWindowContext(mX11Parent.GetXDisplay(), mX11Parent.GetDrawable(),
+ &mX11Parent.GetVisual(), GetWidth(), GetHeight(),
+ SkiaHelper::renderMethodToUse());
+ if (mWindowContext && SkiaHelper::renderMethodToUse() == SkiaHelper::RenderVulkan)
+ mIsGPU = true;
+ else
+ mIsGPU = false;
+}
+
+std::unique_ptr<sk_app::WindowContext>
+X11SkiaSalGraphicsImpl::createWindowContext(Display* display, Drawable drawable,
+ const SalVisual* visual, int width, int height,
+ SkiaHelper::RenderMethod renderMethod)
+{
SkiaZone zone;
sk_app::DisplayParams displayParams;
displayParams.fColorType = kN32_SkColorType;
sk_app::window_context_factory::XlibWindowInfo winInfo;
- winInfo.fDisplay = mX11Parent.GetXDisplay();
- winInfo.fWindow = mX11Parent.GetDrawable();
- assert(winInfo.fDisplay);
- // Allow window being None if offscreen, this is used to temporarily create GrContext
- // for an offscreen surface.
- assert(winInfo.fWindow != None || isOffscreen());
+ assert(display);
+ winInfo.fDisplay = display;
+ winInfo.fWindow = drawable;
winInfo.fFBConfig = nullptr; // not used
- winInfo.fVisualInfo = const_cast<SalVisual*>(&mX11Parent.GetVisual());
+ winInfo.fVisualInfo = const_cast<SalVisual*>(visual);
+ winInfo.fWidth = width;
+ winInfo.fHeight = height;
#ifdef DBG_UTIL
// Our patched Skia has VulkanWindowContext that shares GrContext, which requires
// that the X11 visual is always the same. Ensure it is so.
@@ -60,25 +73,18 @@ void X11SkiaSalGraphicsImpl::createWindowContext()
assert(checkVisualID == -1U || winInfo.fVisualInfo->visualid == checkVisualID);
checkVisualID = winInfo.fVisualInfo->visualid;
#endif
- winInfo.fWidth = GetWidth();
- winInfo.fHeight = GetHeight();
- switch (SkiaHelper::renderMethodToUse())
+ switch (renderMethod)
{
case SkiaHelper::RenderRaster:
// TODO The Skia Xlib code actually requires the non-native color type to work properly.
displayParams.fColorType
= (displayParams.fColorType == kBGRA_8888_SkColorType ? kRGBA_8888_SkColorType
: kBGRA_8888_SkColorType);
- mWindowContext
- = sk_app::window_context_factory::MakeRasterForXlib(winInfo, displayParams);
- mIsGPU = false;
- break;
+ return sk_app::window_context_factory::MakeRasterForXlib(winInfo, displayParams);
case SkiaHelper::RenderVulkan:
- mWindowContext
- = sk_app::window_context_factory::MakeVulkanForXlib(winInfo, displayParams);
- mIsGPU = true;
- break;
+ return sk_app::window_context_factory::MakeVulkanForXlib(winInfo, displayParams);
}
+ abort();
}
bool X11SkiaSalGraphicsImpl::avoidRecreateByResize() const
@@ -116,4 +122,21 @@ void X11SkiaSalGraphicsImpl::performFlush()
mWindowContext->swapBuffers();
}
+std::unique_ptr<sk_app::WindowContext> createVulkanWindowContext()
+{
+ SalDisplay* salDisplay = vcl_sal::getSalDisplay(GetGenericUnixSalData());
+ return X11SkiaSalGraphicsImpl::createWindowContext(
+ salDisplay->GetDisplay(), None, &salDisplay->GetVisual(salDisplay->GetDefaultXScreen()), 1,
+ 1, SkiaHelper::RenderVulkan);
+}
+
+namespace
+{
+struct SetFunction
+{
+ SetFunction() { SkiaHelper::setCreateVulkanWindowContext(createVulkanWindowContext); }
+};
+SetFunction setFunction;
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */