summaryrefslogtreecommitdiff
path: root/vcl/skia
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/skia')
-rw-r--r--vcl/skia/SkiaHelper.cxx37
-rw-r--r--vcl/skia/win/gdiimpl.cxx2
-rw-r--r--vcl/skia/x11/gdiimpl.cxx49
3 files changed, 71 insertions, 17 deletions
diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx
index 4b21e6740603..ff2a2a588741 100644
--- a/vcl/skia/SkiaHelper.cxx
+++ b/vcl/skia/SkiaHelper.cxx
@@ -69,6 +69,8 @@ static bool isVulkanBlacklisted(const VkPhysicalDeviceProperties& props)
deviceIdStr);
}
+static sk_app::VulkanWindowContext::SharedGrContext getTemporaryGrContext();
+
static void checkDeviceBlacklisted(bool blockDisable = false)
{
static bool done = false;
@@ -80,9 +82,23 @@ static void checkDeviceBlacklisted(bool blockDisable = false)
{
case RenderVulkan:
{
- GrContext* grContext = SkiaHelper::getSharedGrContext();
+ // First try if a GrContext already exists.
+ sk_app::VulkanWindowContext::SharedGrContext grContext
+ = sk_app::VulkanWindowContext::getSharedGrContext();
+ if (!grContext.getGrContext())
+ {
+ // This function is called from isVclSkiaEnabled(), which
+ // may be called when deciding which X11 visual to use,
+ // and that visual is normally needed when creating
+ // Skia's VulkanWindowContext, which is needed for the GrContext.
+ // Avoid the loop by creating a temporary GrContext
+ // that will use the default X11 visual (that shouldn't matter
+ // for just finding out information about Vulkan) and destroying
+ // the temporary context will clean up again.
+ grContext = getTemporaryGrContext();
+ }
bool blacklisted = true; // assume the worst
- if (grContext) // Vulkan was initialized properly
+ if (grContext.getGrContext()) // Vulkan was initialized properly
{
blacklisted = isVulkanBlacklisted(
sk_app::VulkanWindowContext::getPhysDeviceProperties());
@@ -230,8 +246,8 @@ void disableRenderMethod(RenderMethod method)
static sk_app::VulkanWindowContext::SharedGrContext* sharedGrContext;
-static std::unique_ptr<sk_app::WindowContext> (*createVulkanWindowContextFunction)() = nullptr;
-static void setCreateVulkanWindowContext(std::unique_ptr<sk_app::WindowContext> (*function)())
+static std::unique_ptr<sk_app::WindowContext> (*createVulkanWindowContextFunction)(bool) = nullptr;
+static void setCreateVulkanWindowContext(std::unique_ptr<sk_app::WindowContext> (*function)(bool))
{
createVulkanWindowContextFunction = function;
}
@@ -259,7 +275,7 @@ GrContext* getSharedGrContext()
done = true;
if (createVulkanWindowContextFunction == nullptr)
return nullptr; // not initialized properly (e.g. used from a VCL backend with no Skia support)
- std::unique_ptr<sk_app::WindowContext> tmpContext = createVulkanWindowContextFunction();
+ std::unique_ptr<sk_app::WindowContext> tmpContext = createVulkanWindowContextFunction(false);
// Set up using the shared context created by the call above, if successful.
context = sk_app::VulkanWindowContext::getSharedGrContext();
grContext = context.getGrContext();
@@ -272,6 +288,15 @@ GrContext* getSharedGrContext()
return nullptr;
}
+static sk_app::VulkanWindowContext::SharedGrContext getTemporaryGrContext()
+{
+ if (createVulkanWindowContextFunction == nullptr)
+ return sk_app::VulkanWindowContext::SharedGrContext();
+ std::unique_ptr<sk_app::WindowContext> tmpContext = createVulkanWindowContextFunction(true);
+ // Set up using the shared context created by the call above, if successful.
+ return sk_app::VulkanWindowContext::getSharedGrContext();
+}
+
sk_sp<SkSurface> createSkSurface(int width, int height, SkColorType type)
{
SkiaZone zone;
@@ -315,7 +340,7 @@ void cleanup()
// Skia should not be used from VCL backends that do not actually support it, as there will be setup missing.
// The code here (that is in the vcl lib) needs a function for creating Vulkan context that is
// usually available only in the backend libs.
-void prepareSkia(std::unique_ptr<sk_app::WindowContext> (*createVulkanWindowContext)())
+void prepareSkia(std::unique_ptr<sk_app::WindowContext> (*createVulkanWindowContext)(bool))
{
setCreateVulkanWindowContext(createVulkanWindowContext);
skiaSupportedByBackend = true;
diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx
index 0708c8ea633f..221819ca1c4f 100644
--- a/vcl/skia/win/gdiimpl.cxx
+++ b/vcl/skia/win/gdiimpl.cxx
@@ -349,7 +349,7 @@ SkiaControlCacheType& SkiaControlsCache::get()
namespace
{
-std::unique_ptr<sk_app::WindowContext> createVulkanWindowContext()
+std::unique_ptr<sk_app::WindowContext> createVulkanWindowContext(bool /*temporary*/)
{
SkiaZone zone;
sk_app::DisplayParams displayParams;
diff --git a/vcl/skia/x11/gdiimpl.cxx b/vcl/skia/x11/gdiimpl.cxx
index fe4553814758..0ed4b6a0ccbd 100644
--- a/vcl/skia/x11/gdiimpl.cxx
+++ b/vcl/skia/x11/gdiimpl.cxx
@@ -23,6 +23,8 @@
#include <skia/utils.hxx>
#include <skia/zone.hxx>
+#include <X11/Xutil.h>
+
X11SkiaSalGraphicsImpl::X11SkiaSalGraphicsImpl(X11SalGraphics& rParent)
: SkiaSalGraphicsImpl(rParent, rParent.GetGeometryProvider())
, mX11Parent(rParent)
@@ -43,7 +45,7 @@ void X11SkiaSalGraphicsImpl::createWindowContext()
assert(mX11Parent.GetDrawable() != None);
mWindowContext = createWindowContext(mX11Parent.GetXDisplay(), mX11Parent.GetDrawable(),
&mX11Parent.GetVisual(), GetWidth(), GetHeight(),
- SkiaHelper::renderMethodToUse());
+ SkiaHelper::renderMethodToUse(), false);
if (mWindowContext && SkiaHelper::renderMethodToUse() == SkiaHelper::RenderVulkan)
mIsGPU = true;
else
@@ -52,8 +54,8 @@ void X11SkiaSalGraphicsImpl::createWindowContext()
std::unique_ptr<sk_app::WindowContext>
X11SkiaSalGraphicsImpl::createWindowContext(Display* display, Drawable drawable,
- const SalVisual* visual, int width, int height,
- SkiaHelper::RenderMethod renderMethod)
+ const XVisualInfo* visual, int width, int height,
+ SkiaHelper::RenderMethod renderMethod, bool temporary)
{
SkiaZone zone;
sk_app::DisplayParams displayParams;
@@ -63,15 +65,24 @@ X11SkiaSalGraphicsImpl::createWindowContext(Display* display, Drawable drawable,
winInfo.fDisplay = display;
winInfo.fWindow = drawable;
winInfo.fFBConfig = nullptr; // not used
- winInfo.fVisualInfo = const_cast<SalVisual*>(visual);
+ winInfo.fVisualInfo = const_cast<XVisualInfo*>(visual);
+ assert(winInfo.fVisualInfo->visual != nullptr); // make sure it's not an uninitialized SalVisual
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.
static VisualID checkVisualID = -1U;
- assert(checkVisualID == -1U || winInfo.fVisualInfo->visualid == checkVisualID);
- checkVisualID = winInfo.fVisualInfo->visualid;
+ // Exception is for the temporary case during startup, when SkiaHelper's
+ // checkDeviceBlacklisted() needs a WindowContext and may be called before SalVisual
+ // is ready.
+ if (!temporary)
+ {
+ assert(checkVisualID == -1U || winInfo.fVisualInfo->visualid == checkVisualID);
+ checkVisualID = winInfo.fVisualInfo->visualid;
+ }
+#else
+ (void)temporary;
#endif
switch (renderMethod)
{
@@ -122,12 +133,30 @@ void X11SkiaSalGraphicsImpl::performFlush()
mWindowContext->swapBuffers();
}
-std::unique_ptr<sk_app::WindowContext> createVulkanWindowContext()
+std::unique_ptr<sk_app::WindowContext> createVulkanWindowContext(bool temporary)
{
SalDisplay* salDisplay = vcl_sal::getSalDisplay(GetGenericUnixSalData());
- return X11SkiaSalGraphicsImpl::createWindowContext(
- salDisplay->GetDisplay(), None, &salDisplay->GetVisual(salDisplay->GetDefaultXScreen()), 1,
- 1, SkiaHelper::RenderVulkan);
+ const XVisualInfo* visual;
+ XVisualInfo* visuals = nullptr;
+ if (!temporary)
+ visual = &salDisplay->GetVisual(salDisplay->GetDefaultXScreen());
+ else
+ {
+ // SalVisual from salDisplay may not be setup yet at this point, get
+ // info for the default visual.
+ XVisualInfo search;
+ search.visualid = XVisualIDFromVisual(
+ DefaultVisual(salDisplay->GetDisplay(), salDisplay->GetDefaultXScreen().getXScreen()));
+ int count;
+ visuals = XGetVisualInfo(salDisplay->GetDisplay(), VisualIDMask, &search, &count);
+ assert(count == 1);
+ visual = visuals;
+ }
+ std::unique_ptr<sk_app::WindowContext> ret = X11SkiaSalGraphicsImpl::createWindowContext(
+ salDisplay->GetDisplay(), None, visual, 1, 1, SkiaHelper::RenderVulkan, temporary);
+ if (temporary)
+ XFree(visuals);
+ return ret;
}
void X11SkiaSalGraphicsImpl::prepareSkia() { SkiaHelper::prepareSkia(createVulkanWindowContext); }