1 | // Copyright (C) 2017 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qxcbvulkaninstance.h" |
5 | #include "qxcbwindow.h" |
6 | #include "qxcbscreen.h" |
7 | |
8 | QT_BEGIN_NAMESPACE |
9 | |
10 | QXcbVulkanInstance::QXcbVulkanInstance(QVulkanInstance *instance) |
11 | : m_instance(instance), |
12 | m_getPhysDevPresSupport(nullptr), |
13 | m_createSurface(nullptr) |
14 | { |
15 | loadVulkanLibrary(QStringLiteral("vulkan" ), defaultLibraryVersion: 1); |
16 | } |
17 | |
18 | QXcbVulkanInstance::~QXcbVulkanInstance() |
19 | { |
20 | } |
21 | |
22 | void QXcbVulkanInstance::createOrAdoptInstance() |
23 | { |
24 | initInstance(instance: m_instance, extraExts: QByteArrayList() << QByteArrayLiteral("VK_KHR_xcb_surface" )); |
25 | |
26 | if (!m_vkInst) |
27 | return; |
28 | |
29 | m_getPhysDevPresSupport = reinterpret_cast<PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR>( |
30 | m_vkGetInstanceProcAddr(m_vkInst, "vkGetPhysicalDeviceXcbPresentationSupportKHR" )); |
31 | if (!m_getPhysDevPresSupport) |
32 | qWarning(msg: "Failed to find vkGetPhysicalDeviceXcbPresentationSupportKHR" ); |
33 | } |
34 | |
35 | bool QXcbVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, |
36 | uint32_t queueFamilyIndex, |
37 | QWindow *window) |
38 | { |
39 | if (!m_getPhysDevPresSupport || !m_getPhysDevSurfaceSupport) |
40 | return true; |
41 | |
42 | QXcbWindow *w = static_cast<QXcbWindow *>(window->handle()); |
43 | if (!w) { |
44 | qWarning(msg: "Attempted to call supportsPresent() without a valid platform window" ); |
45 | return false; |
46 | } |
47 | xcb_connection_t *connection = w->xcbScreen()->xcb_connection(); |
48 | bool ok = m_getPhysDevPresSupport(physicalDevice, queueFamilyIndex, connection, w->visualId()); |
49 | |
50 | VkSurfaceKHR surface = QVulkanInstance::surfaceForWindow(window); |
51 | VkBool32 supported = false; |
52 | m_getPhysDevSurfaceSupport(physicalDevice, queueFamilyIndex, surface, &supported); |
53 | ok &= bool(supported); |
54 | |
55 | return ok; |
56 | } |
57 | |
58 | VkSurfaceKHR QXcbVulkanInstance::createSurface(QXcbWindow *window) |
59 | { |
60 | VkSurfaceKHR surface = VK_NULL_HANDLE; |
61 | |
62 | if (!m_createSurface) { |
63 | m_createSurface = reinterpret_cast<PFN_vkCreateXcbSurfaceKHR>( |
64 | m_vkGetInstanceProcAddr(m_vkInst, "vkCreateXcbSurfaceKHR" )); |
65 | } |
66 | if (!m_createSurface) { |
67 | qWarning(msg: "Failed to find vkCreateXcbSurfaceKHR" ); |
68 | return surface; |
69 | } |
70 | |
71 | VkXcbSurfaceCreateInfoKHR surfaceInfo; |
72 | memset(s: &surfaceInfo, c: 0, n: sizeof(surfaceInfo)); |
73 | surfaceInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; |
74 | surfaceInfo.connection = window->xcbScreen()->xcb_connection(); |
75 | surfaceInfo.window = window->xcb_window(); |
76 | VkResult err = m_createSurface(m_vkInst, &surfaceInfo, nullptr, &surface); |
77 | if (err != VK_SUCCESS) |
78 | qWarning(msg: "Failed to create Vulkan surface: %d" , err); |
79 | |
80 | return surface; |
81 | } |
82 | |
83 | void QXcbVulkanInstance::presentQueued(QWindow *window) |
84 | { |
85 | QXcbWindow *w = static_cast<QXcbWindow *>(window->handle()); |
86 | if (!w) { |
87 | qWarning(msg: "Attempted to call presentQueued() without a valid platform window" ); |
88 | return; |
89 | } |
90 | |
91 | if (w->needsSync()) |
92 | w->postSyncWindowRequest(); |
93 | } |
94 | |
95 | QT_END_NAMESPACE |
96 | |