diff options
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/configure.json | 86 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 4 | ||||
-rw-r--r-- | src/gui/kernel/qhighdpiscaling_p.h | 2 | ||||
-rw-r--r-- | src/gui/kernel/qscreen.cpp | 19 | ||||
-rw-r--r-- | src/gui/kernel/qscreen.h | 1 | ||||
-rw-r--r-- | src/gui/rhi/qrhivulkan.cpp | 4 | ||||
-rw-r--r-- | src/gui/vulkan/qplatformvulkaninstance.cpp | 5 | ||||
-rw-r--r-- | src/gui/vulkan/qplatformvulkaninstance.h | 1 | ||||
-rw-r--r-- | src/gui/vulkan/qvulkaninstance.cpp | 14 | ||||
-rw-r--r-- | src/gui/vulkan/qvulkaninstance.h | 1 | ||||
-rw-r--r-- | src/gui/vulkan/qvulkanwindow.cpp | 113 | ||||
-rw-r--r-- | src/gui/vulkan/qvulkanwindow.h | 7 | ||||
-rw-r--r-- | src/gui/vulkan/qvulkanwindow_p.h | 1 |
13 files changed, 198 insertions, 60 deletions
diff --git a/src/gui/configure.json b/src/gui/configure.json index c2793bf236..39b8d0c2b8 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -41,11 +41,10 @@ "sm": { "type": "boolean", "name": "sessionmanager" }, "tslib": "boolean", "vulkan": "boolean", - "xcb": { "type": "enum", "values": [ "no", "yes", "qt", "system" ] }, + "xcb": "boolean", + "bundled-xcb-xinput": "boolean", "xcb-native-painting": "boolean", "xcb-xlib": "boolean", - "xcb-xinput": "boolean", - "xkb": "boolean", "xkbcommon": "boolean" } }, @@ -573,18 +572,22 @@ ] }, "xcb": { - "label": "XCB >= 1.9", + "label": "XCB >= 1.11", "test": { "main": [ "int primaryScreen = 0;", "(void)xcb_connect(\"\", &primaryScreen);", - "// This won't compile unless libxcb >= 1.9 which defines XCB_CONN_CLOSED_INVALID_SCREEN.", - "int xcbScreenError = XCB_CONN_CLOSED_INVALID_SCREEN;" + "/* XCB_PACKED define was added in libxcb 1.11 */", + "#ifdef XCB_PACKED", + " return 0;", + "#else", + " return -1;", + "#endif" ] }, "headers": "xcb/xcb.h", "sources": [ - { "type": "pkgConfig", "args": "xcb >= 1.9" }, + { "type": "pkgConfig", "args": "xcb >= 1.11" }, "-lxcb" ] }, @@ -691,21 +694,10 @@ "use": "xcb xlib" }, "xcb_xkb": { - "label": "XCB XKB >= 1.10", - "test": { - "head": [ - "// xkb.h is using a variable called 'explicit', which is a reserved keyword in C++", - "#define explicit dont_use_cxx_explicit" - ], - "tail": "#undef explicit", - "main": [ - "// This takes more arguments in xcb-xkb < 1.10.", - "xcb_xkb_get_kbd_by_name_unchecked(NULL, 0, 0, 0, 0);" - ] - }, + "label": "XCB XKB", "headers": "xcb/xkb.h", "sources": [ - { "type": "pkgConfig", "args": "xcb-xkb >= 1.10" }, + { "type": "pkgConfig", "args": "xcb-xkb" }, "-lxcb-xkb" ], "use": "xcb" @@ -769,7 +761,7 @@ "xkbcommon_x11": { "label": "xkbcommon-x11", "test": { - "main": "xkb_x11_get_core_keyboard_device_id(nullptr);" + "main": "xkb_x11_setup_xkb_extension_flags flag = XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS;" }, "headers": [ "xkbcommon/xkbcommon-x11.h" ], "sources": [ @@ -1056,6 +1048,11 @@ "label": "XCB (extensions)", "type": "compile", "test": { + "head": [ + "// xkb.h is using a variable called 'explicit', which is a reserved keyword in C++", + "#define explicit dont_use_cxx_explicit" + ], + "tail": "#undef explicit", "include": [ "xcb/xcb.h", "xcb/xcb_image.h", @@ -1068,7 +1065,8 @@ "xcb/xfixes.h", "xcb/xinerama.h", "xcb/xcb_icccm.h", - "xcb/xcb_renderutil.h" + "xcb/xcb_renderutil.h", + "xcb/xkb.h" ], "main": [ "int primaryScreen = 0;", @@ -1082,10 +1080,13 @@ " xcb_render_query_pict_formats_reply(c, formatsCookie, &error);", "/* RENDERUTIL: xcb_renderutil.h include won't compile unless version >= 0.3.9 */", - "xcb_render_util_find_standard_format(nullptr, XCB_PICT_STANDARD_ARGB_32);" + "xcb_render_util_find_standard_format(nullptr, XCB_PICT_STANDARD_ARGB_32);", + + "/* XKB: This takes more arguments in xcb-xkb < 1.11 */", + "xcb_xkb_get_kbd_by_name_replies_key_names_value_list_sizeof(nullptr, 0, 0, 0, 0, 0, 0, 0, 0);" ] }, - "use": "xcb_icccm xcb_image xcb_keysyms xcb_randr xcb_render xcb_renderutil xcb_shape xcb_shm xcb_sync xcb_xfixes xcb_xinerama xcb" + "use": "xcb_icccm xcb_image xcb_keysyms xcb_randr xcb_render xcb_renderutil xcb_shape xcb_shm xcb_sync xcb_xfixes xcb_xinerama xcb_xkb xcb" }, "x11prefix": { "label": "X11 prefix", @@ -1514,16 +1515,7 @@ "label": "XCB", "section": "Platform plugins", "autoDetect": "!config.darwin", - "enable": "input.xcb == 'system' || input.xcb == 'qt' || input.xcb == 'yes'", - "condition": "features.thread && features.xkbcommon && libs.xcb", - "output": [ "privateFeature" ] - }, - "system-xcb": { - "label": "Using system-provided XCB libraries", - "enable": "input.xcb == 'system'", - "disable": "input.xcb == 'qt'", - "autoDetect": "!config.darwin", - "condition": "features.xcb && tests.xcb_syslibs", + "condition": "features.thread && libs.xcb && tests.xcb_syslibs && features.xkbcommon-x11", "output": [ "privateFeature" ] }, "x11-prefix": { @@ -1562,12 +1554,6 @@ "condition": "features.xcb-native-painting", "output": [ "privateFeature" ] }, - "xkb": { - "label": "XCB XKB", - "emitIf": "features.xcb", - "condition": "(!features.system-xcb || libs.xcb_xkb) && libs.xkbcommon_x11", - "output": [ "privateFeature" ] - }, "xcb-xlib": { "label": "XCB Xlib", "condition": "features.xlib && libs.xcb_xlib", @@ -1579,10 +1565,12 @@ "condition": "features.sessionmanager && libs.x11sm", "output": [ "privateFeature" ] }, - "xcb-xinput": { - "label": "XCB XInput", + "system-xcb-xinput": { + "label": "Using system-provided xcb-xinput", "emitIf": "features.xcb", - "condition": "!features.system-xcb || libs.xcb_xinput", + "disable": "input.bundled-xcb-xinput == 'yes'", + "enable": "input.bundled-xcb-xinput == 'no'", + "condition": "libs.xcb_xinput", "output": [ "privateFeature" ] }, "xkbcommon": { @@ -1590,6 +1578,11 @@ "condition": "libs.xkbcommon", "output": [ "privateFeature" ] }, + "xkbcommon-x11": { + "label": "xkbcommon-x11", + "condition": "features.xkbcommon && libs.xkbcommon_x11", + "output": [ "privateFeature" ] + }, "xlib": { "label": "XLib", "autoDetect": "!config.darwin || features.xcb", @@ -1831,7 +1824,7 @@ { "type": "error", "condition": "input.xcb != '' && input.xcb != 'no' && input.xkbcommon == 'no'", - "message": "XCB plugin requires xkbcommon, but -no-xkbcommon was provided." + "message": "XCB plugin requires xkbcommon and xkbcommon-x11, but -no-xkbcommon was provided." } ], @@ -1953,7 +1946,8 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla "entries": [ "xlib", "xcb-xlib", - "egl_x11" + "egl_x11", + "xkbcommon-x11" ] } ] @@ -1986,7 +1980,7 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla "section": "XCB", "condition": "features.xcb", "entries": [ - "system-xcb", "xkb", "xcb-xinput", "xcb-native-painting", + "system-xcb-xinput", "xcb-native-painting", { "section": "GL integrations", "entries": [ diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 13de8af8b5..b4c4231910 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1040,7 +1040,9 @@ QList<QScreen *> QGuiApplication::screens() The \a point is in relation to the virtualGeometry() of each set of virtual siblings. If the point maps to more than one set of virtual siblings the first - match is returned. + match is returned. If you wish to search only the virtual desktop siblings + of a known screen (for example siblings of the screen of your application + window \c QWidget::windowHandle()->screen()), use QScreen::virtualSiblingAt(). \since 5.10 */ diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h index f58944a7d2..3c85481495 100644 --- a/src/gui/kernel/qhighdpiscaling_p.h +++ b/src/gui/kernel/qhighdpiscaling_p.h @@ -313,7 +313,7 @@ public: static inline QPoint mapPositionToNative(const QPoint &pos, const QPlatformScreen *) { return pos; } static inline QPoint mapPositionToGlobal(const QPoint &pos, const QPoint &windowGlobalPosition, const QWindow *window) { return pos; } static inline QPoint mapPositionFromGlobal(const QPoint &pos, const QPoint &windowGlobalPosition, const QWindow *window) { return pos; } - static inline QDpi logicalDpi() { return QDpi(-1,-1); } + static inline QDpi logicalDpi(const QScreen *screen) { return QDpi(-1,-1); } }; namespace QHighDpi { diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp index 7adf3db1b8..80de561297 100644 --- a/src/gui/kernel/qscreen.cpp +++ b/src/gui/kernel/qscreen.cpp @@ -700,6 +700,25 @@ void QScreenPrivate::updatePrimaryOrientation() } /*! + Returns the screen at \a point within the set of \l QScreen::virtualSiblings(), + or \c nullptr if outside of any screen. + + The \a point is in relation to the virtualGeometry() of each set of virtual + siblings. + + \since 5.15 +*/ +QScreen *QScreen::virtualSiblingAt(const QPoint &point) +{ + const auto &siblings = virtualSiblings(); + for (QScreen *sibling : siblings) { + if (sibling->geometry().contains(point)) + return sibling; + } + return nullptr; +} + +/*! Creates and returns a pixmap constructed by grabbing the contents of the given \a window restricted by QRect(\a x, \a y, \a width, \a height). diff --git a/src/gui/kernel/qscreen.h b/src/gui/kernel/qscreen.h index 14392d3036..88925ab731 100644 --- a/src/gui/kernel/qscreen.h +++ b/src/gui/kernel/qscreen.h @@ -125,6 +125,7 @@ public: QRect availableGeometry() const; QList<QScreen *> virtualSiblings() const; + QScreen *virtualSiblingAt(const QPoint &point); QSize virtualSize() const; QRect virtualGeometry() const; diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index 36a6557e04..d07777d63a 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -1705,6 +1705,10 @@ QRhi::FrameOpResult QRhiVulkan::endFrame(QRhiSwapChain *swapChain, QRhi::EndFram presInfo.waitSemaphoreCount = 1; presInfo.pWaitSemaphores = &frame.drawSem; // gfxQueueFamilyIdx == presQueueFamilyIdx ? &frame.drawSem : &frame.presTransSem; + // Do platform-specific WM notification. F.ex. essential on Wayland in + // order to circumvent driver frame callbacks + inst->presentAboutToBeQueued(swapChainD->window); + VkResult err = vkQueuePresentKHR(gfxQueue, &presInfo); if (err != VK_SUCCESS) { if (err == VK_ERROR_OUT_OF_DATE_KHR) { diff --git a/src/gui/vulkan/qplatformvulkaninstance.cpp b/src/gui/vulkan/qplatformvulkaninstance.cpp index 9d044bfd58..1b5d3370f0 100644 --- a/src/gui/vulkan/qplatformvulkaninstance.cpp +++ b/src/gui/vulkan/qplatformvulkaninstance.cpp @@ -80,6 +80,11 @@ QPlatformVulkanInstance::~QPlatformVulkanInstance() { } +void QPlatformVulkanInstance::presentAboutToBeQueued(QWindow *window) +{ + Q_UNUSED(window); +} + void QPlatformVulkanInstance::presentQueued(QWindow *window) { Q_UNUSED(window); diff --git a/src/gui/vulkan/qplatformvulkaninstance.h b/src/gui/vulkan/qplatformvulkaninstance.h index d47c59b5db..f96f1720fb 100644 --- a/src/gui/vulkan/qplatformvulkaninstance.h +++ b/src/gui/vulkan/qplatformvulkaninstance.h @@ -77,6 +77,7 @@ public: virtual QByteArrayList enabledExtensions() const = 0; virtual PFN_vkVoidFunction getInstanceProcAddr(const char *name) = 0; virtual bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) = 0; + virtual void presentAboutToBeQueued(QWindow *window); virtual void presentQueued(QWindow *window); virtual void setDebugFilters(const QVector<QVulkanInstance::DebugFilter> &filters); diff --git a/src/gui/vulkan/qvulkaninstance.cpp b/src/gui/vulkan/qvulkaninstance.cpp index 0605d88cca..daf37e3dc8 100644 --- a/src/gui/vulkan/qvulkaninstance.cpp +++ b/src/gui/vulkan/qvulkaninstance.cpp @@ -775,6 +775,20 @@ bool QVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, uint32_t } /*! + This function should be called by the application's renderer before queuing + a present operation for \a window. + + While on some platforms this will be a no-op, some may perform windowing + system dependent synchronization. For example, on Wayland this will + add send a wl_surface.frame request in order to prevent the driver from + blocking for minimized windows. + */ +void QVulkanInstance::presentAboutToBeQueued(QWindow *window) +{ + d_ptr->platformInst->presentAboutToBeQueued(window); +} + +/*! This function should be called by the application's renderer after queuing a present operation for \a window. diff --git a/src/gui/vulkan/qvulkaninstance.h b/src/gui/vulkan/qvulkaninstance.h index 70f2fd5102..5b3db9a4c8 100644 --- a/src/gui/vulkan/qvulkaninstance.h +++ b/src/gui/vulkan/qvulkaninstance.h @@ -186,6 +186,7 @@ public: bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window); + void presentAboutToBeQueued(QWindow *window); void presentQueued(QWindow *window); typedef bool (*DebugFilter)(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, diff --git a/src/gui/vulkan/qvulkanwindow.cpp b/src/gui/vulkan/qvulkanwindow.cpp index 4b5c2b56ee..790bef9e14 100644 --- a/src/gui/vulkan/qvulkanwindow.cpp +++ b/src/gui/vulkan/qvulkanwindow.cpp @@ -647,18 +647,40 @@ void QVulkanWindowPrivate::init() #endif qCDebug(lcGuiVk, "Using queue families: graphics = %u present = %u", gfxQueueFamilyIdx, presQueueFamilyIdx); - VkDeviceQueueCreateInfo queueInfo[2]; + QVector<VkDeviceQueueCreateInfo> queueInfo; + queueInfo.reserve(2); const float prio[] = { 0 }; - memset(queueInfo, 0, sizeof(queueInfo)); - queueInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueInfo[0].queueFamilyIndex = gfxQueueFamilyIdx; - queueInfo[0].queueCount = 1; - queueInfo[0].pQueuePriorities = prio; + VkDeviceQueueCreateInfo addQueueInfo; + memset(&addQueueInfo, 0, sizeof(addQueueInfo)); + addQueueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + addQueueInfo.queueFamilyIndex = gfxQueueFamilyIdx; + addQueueInfo.queueCount = 1; + addQueueInfo.pQueuePriorities = prio; + queueInfo.append(addQueueInfo); if (gfxQueueFamilyIdx != presQueueFamilyIdx) { - queueInfo[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueInfo[1].queueFamilyIndex = presQueueFamilyIdx; - queueInfo[1].queueCount = 1; - queueInfo[1].pQueuePriorities = prio; + addQueueInfo.queueFamilyIndex = presQueueFamilyIdx; + addQueueInfo.queueCount = 1; + addQueueInfo.pQueuePriorities = prio; + queueInfo.append(addQueueInfo); + } + if (queueCreateInfoModifier) { + queueCreateInfoModifier(queueFamilyProps.constData(), queueCount, queueInfo); + bool foundGfxQueue = false; + bool foundPresQueue = false; + for (const VkDeviceQueueCreateInfo& createInfo : qAsConst(queueInfo)) { + foundGfxQueue |= createInfo.queueFamilyIndex == gfxQueueFamilyIdx; + foundPresQueue |= createInfo.queueFamilyIndex == presQueueFamilyIdx; + } + if (!foundGfxQueue) { + qWarning("QVulkanWindow: Graphics queue missing after call to queueCreateInfoModifier"); + status = StatusFail; + return; + } + if (!foundPresQueue) { + qWarning("QVulkanWindow: Present queue missing after call to queueCreateInfoModifier"); + status = StatusFail; + return; + } } // Filter out unsupported extensions in order to keep symmetry @@ -676,8 +698,8 @@ void QVulkanWindowPrivate::init() VkDeviceCreateInfo devInfo; memset(&devInfo, 0, sizeof(devInfo)); devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - devInfo.queueCreateInfoCount = gfxQueueFamilyIdx == presQueueFamilyIdx ? 1 : 2; - devInfo.pQueueCreateInfos = queueInfo; + devInfo.queueCreateInfoCount = queueInfo.size(); + devInfo.pQueueCreateInfos = queueInfo.constData(); devInfo.enabledExtensionCount = devExts.count(); devInfo.ppEnabledExtensionNames = devExts.constData(); @@ -1546,6 +1568,52 @@ bool QVulkanWindow::event(QEvent *e) } /*! + \typedef QVulkanWindow::QueueCreateInfoModifier + + A function function that is called during graphics initialization to add + additAional queues that should be created. + + Set if the renderer needs additional queues besides the default graphics + queue (e.g. a transfer queue). + The provided queue family properties can be used to select the indices for + the additional queues. + The renderer can subsequently request the actual queue in initResources(). + + Note when requesting additional graphics queues: Qt itself always requests + a graphics queue, you'll need to search queueCreateInfo for the appropriate + entry and manipulate it to obtain the additional queue. + + \sa setQueueCreateInfoModifier() + */ + +/*! + Return a previously set queue create info modification function. + + \sa setQueueCreateInfoModifier() + + \since 5.15 + */ +QVulkanWindow::QueueCreateInfoModifier QVulkanWindow::queueCreateInfoModifier() const +{ + Q_D(const QVulkanWindow); + return d->queueCreateInfoModifier; +} + +/*! + Set a queue create info modification function. + + \sa queueCreateInfoModifier() + + \since 5.15 + */ +void QVulkanWindow::setQueueCreateInfoModifier(QueueCreateInfoModifier modifier) +{ + Q_D(QVulkanWindow); + d->queueCreateInfoModifier = modifier; +} + + +/*! Returns true if this window has successfully initialized all Vulkan resources, including the swapchain. @@ -1950,6 +2018,10 @@ void QVulkanWindowPrivate::endFrame() presInfo.waitSemaphoreCount = 1; presInfo.pWaitSemaphores = gfxQueueFamilyIdx == presQueueFamilyIdx ? &frame.drawSem : &frame.presTransSem; + // Do platform-specific WM notification. F.ex. essential on Wayland in + // order to circumvent driver frame callbacks + inst->presentAboutToBeQueued(q); + err = vkQueuePresentKHR(gfxQueue, &presInfo); if (err != VK_SUCCESS) { if (err == VK_ERROR_OUT_OF_DATE_KHR) { @@ -2211,6 +2283,23 @@ VkQueue QVulkanWindow::graphicsQueue() const } /*! + Returns the family index of the active graphics queue. + + \note Calling this function is only valid from the invocation of + QVulkanWindowRenderer::initResources() up until + QVulkanWindowRenderer::releaseResources(). Implementations of + QVulkanWindowRenderer::updateQueueCreateInfo() can also call this + function. + + \since 5.15 + */ +uint32_t QVulkanWindow::graphicsQueueFamilyIndex() const +{ + Q_D(const QVulkanWindow); + return d->gfxQueueFamilyIdx; +} + +/*! Returns the active graphics command pool. \note Calling this function is only valid from the invocation of diff --git a/src/gui/vulkan/qvulkanwindow.h b/src/gui/vulkan/qvulkanwindow.h index 927c81042f..530b6c0744 100644 --- a/src/gui/vulkan/qvulkanwindow.h +++ b/src/gui/vulkan/qvulkanwindow.h @@ -103,6 +103,12 @@ public: QVector<int> supportedSampleCounts(); void setSampleCount(int sampleCount); + typedef std::function<void(const VkQueueFamilyProperties *, + uint32_t, + QVector<VkDeviceQueueCreateInfo> &)> QueueCreateInfoModifier; + QueueCreateInfoModifier queueCreateInfoModifier() const; + void setQueueCreateInfoModifier(QueueCreateInfoModifier modifier); + bool isValid() const; virtual QVulkanWindowRenderer *createRenderer(); @@ -112,6 +118,7 @@ public: const VkPhysicalDeviceProperties *physicalDeviceProperties() const; VkDevice device() const; VkQueue graphicsQueue() const; + uint32_t graphicsQueueFamilyIndex() const; VkCommandPool graphicsCommandPool() const; uint32_t hostVisibleMemoryIndex() const; uint32_t deviceLocalMemoryIndex() const; diff --git a/src/gui/vulkan/qvulkanwindow_p.h b/src/gui/vulkan/qvulkanwindow_p.h index fb374a5564..777be237a8 100644 --- a/src/gui/vulkan/qvulkanwindow_p.h +++ b/src/gui/vulkan/qvulkanwindow_p.h @@ -102,6 +102,7 @@ public: QHash<VkPhysicalDevice, QVulkanInfoVector<QVulkanExtension> > supportedDevExtensions; QVector<VkFormat> requestedColorFormats; VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; + QVulkanWindow::QueueCreateInfoModifier queueCreateInfoModifier; VkDevice dev = VK_NULL_HANDLE; QVulkanDeviceFunctions *devFuncs; |