diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2020-02-06 15:48:14 +0100 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2020-02-10 10:09:42 +0100 |
commit | 3081998ada2ad60d14f8b2343309fe79776f898a (patch) | |
tree | a1d43b40191cbfaa56d5c80732875c22cb780aae /vcl | |
parent | c060c80496429d59bb6f158c44957d853dccb06c (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.hxx | 4 | ||||
-rw-r--r-- | vcl/inc/skia/x11/gdiimpl.hxx | 5 | ||||
-rw-r--r-- | vcl/skia/SkiaHelper.cxx | 81 | ||||
-rw-r--r-- | vcl/skia/gdiimpl.cxx | 16 | ||||
-rw-r--r-- | vcl/skia/x11/gdiimpl.cxx | 63 |
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: */ |