diff options
Diffstat (limited to 'src/plugins/platforms/windows')
-rw-r--r-- | src/plugins/platforms/windows/qwindowsintegration.cpp | 7 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowsintegration.h | 4 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowsnativeinterface.cpp | 12 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowsvulkaninstance.cpp | 136 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowsvulkaninstance.h | 76 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowswindow.cpp | 72 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowswindow.h | 10 | ||||
-rw-r--r-- | src/plugins/platforms/windows/windows.pri | 5 | ||||
-rw-r--r-- | src/plugins/platforms/windows/windows.pro | 2 |
9 files changed, 311 insertions, 13 deletions
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 316f93e3ac..6614c76a53 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -606,4 +606,11 @@ void QWindowsIntegration::beep() const MessageBeep(MB_OK); // For QApplication } +#if QT_CONFIG(vulkan) +QPlatformVulkanInstance *QWindowsIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const +{ + return new QWindowsVulkanInstance(instance); +} +#endif + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index 607203829f..fbdb341dab 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -113,6 +113,10 @@ public: QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const override; #endif +#if QT_CONFIG(vulkan) + QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const override; +#endif + protected: virtual QWindowsWindow *createPlatformWindowHelper(QWindow *window, const QWindowsWindowData &) const; diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp index d750eef19d..8bc2e1b441 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp @@ -64,7 +64,8 @@ enum ResourceType { HandleType, GlHandleType, GetDCType, - ReleaseDCType + ReleaseDCType, + VkSurface }; static int resourceType(const QByteArray &key) @@ -77,7 +78,8 @@ static int resourceType(const QByteArray &key) "handle", "glhandle", "getdc", - "releasedc" + "releasedc", + "vkSurface" }; const char ** const end = names + sizeof(names) / sizeof(names[0]); const char **result = std::find(names, end, key); @@ -112,6 +114,12 @@ void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resourc case QWindow::OpenGLSurface: case QWindow::OpenVGSurface: break; +#if QT_CONFIG(vulkan) + case QWindow::VulkanSurface: + if (type == VkSurface) + return bw->surface(nullptr, nullptr); // returns the address of the VkSurfaceKHR, not the value, as expected + break; +#endif } qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData()); return 0; diff --git a/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp b/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp new file mode 100644 index 0000000000..d81ee8ba29 --- /dev/null +++ b/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowsvulkaninstance.h" + +QT_BEGIN_NAMESPACE + +QWindowsVulkanInstance::QWindowsVulkanInstance(QVulkanInstance *instance) + : m_instance(instance), + m_getPhysDevPresSupport(nullptr), + m_createSurface(nullptr), + m_destroySurface(nullptr) +{ + if (qEnvironmentVariableIsSet("QT_VULKAN_LIB")) + m_lib.setFileName(QString::fromUtf8(qgetenv("QT_VULKAN_LIB"))); + else + m_lib.setFileName(QStringLiteral("vulkan-1")); + + if (!m_lib.load()) { + qWarning("Failed to load %s: %s", qPrintable(m_lib.fileName()), qPrintable(m_lib.errorString())); + return; + } + + init(&m_lib); +} + +void QWindowsVulkanInstance::createOrAdoptInstance() +{ + initInstance(m_instance, QByteArrayList() << QByteArrayLiteral("VK_KHR_win32_surface")); + + if (!m_vkInst) + return; + + m_getPhysDevPresSupport = reinterpret_cast<PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR>( + m_vkGetInstanceProcAddr(m_vkInst, "vkGetPhysicalDeviceWin32PresentationSupportKHR")); + if (!m_getPhysDevPresSupport) + qWarning("Failed to find vkGetPhysicalDeviceWin32PresentationSupportKHR"); +} + +QWindowsVulkanInstance::~QWindowsVulkanInstance() +{ +} + +bool QWindowsVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + QWindow *window) +{ + if (!m_getPhysDevPresSupport || !m_getPhysDevSurfaceSupport) + return true; + + bool ok = m_getPhysDevPresSupport(physicalDevice, queueFamilyIndex); + + VkSurfaceKHR surface = QVulkanInstance::surfaceForWindow(window); + VkBool32 supported = false; + m_getPhysDevSurfaceSupport(physicalDevice, queueFamilyIndex, surface, &supported); + ok &= bool(supported); + + return ok; +} + +VkSurfaceKHR QWindowsVulkanInstance::createSurface(HWND win) +{ + VkSurfaceKHR surface = 0; + + if (!m_createSurface) { + m_createSurface = reinterpret_cast<PFN_vkCreateWin32SurfaceKHR>( + m_vkGetInstanceProcAddr(m_vkInst, "vkCreateWin32SurfaceKHR")); + } + if (!m_createSurface) { + qWarning("Failed to find vkCreateWin32SurfaceKHR"); + return surface; + } + if (!m_destroySurface) { + m_destroySurface = reinterpret_cast<PFN_vkDestroySurfaceKHR>( + m_vkGetInstanceProcAddr(m_vkInst, "vkDestroySurfaceKHR")); + } + if (!m_destroySurface) { + qWarning("Failed to find vkDestroySurfaceKHR"); + return surface; + } + + VkWin32SurfaceCreateInfoKHR surfaceInfo; + memset(&surfaceInfo, 0, sizeof(surfaceInfo)); + surfaceInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + surfaceInfo.hinstance = GetModuleHandle(nullptr); + surfaceInfo.hwnd = win; + VkResult err = m_createSurface(m_vkInst, &surfaceInfo, nullptr, &surface); + if (err != VK_SUCCESS) + qWarning("Failed to create Vulkan surface: %d", err); + + return surface; +} + +void QWindowsVulkanInstance::destroySurface(VkSurfaceKHR surface) +{ + if (m_destroySurface && surface) + m_destroySurface(m_vkInst, surface, nullptr); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsvulkaninstance.h b/src/plugins/platforms/windows/qwindowsvulkaninstance.h new file mode 100644 index 0000000000..ca60ab7627 --- /dev/null +++ b/src/plugins/platforms/windows/qwindowsvulkaninstance.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSVULKANINSTANCE_H +#define QWINDOWSVULKANINSTANCE_H + +#if defined(VULKAN_H_) && !defined(VK_USE_PLATFORM_WIN32_KHR) +#error "vulkan.h included without Win32 WSI" +#endif + +#define VK_USE_PLATFORM_WIN32_KHR + +#include <QtVulkanSupport/private/qbasicvulkanplatforminstance_p.h> +#include <QLibrary> + +QT_BEGIN_NAMESPACE + +class QWindowsVulkanInstance : public QBasicPlatformVulkanInstance +{ +public: + QWindowsVulkanInstance(QVulkanInstance *instance); + ~QWindowsVulkanInstance(); + + void createOrAdoptInstance() override; + bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override; + + VkSurfaceKHR createSurface(HWND win); + void destroySurface(VkSurfaceKHR surface); + +private: + QVulkanInstance *m_instance; + QLibrary m_lib; + PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR m_getPhysDevPresSupport; + PFN_vkCreateWin32SurfaceKHR m_createSurface; + PFN_vkDestroySurfaceKHR m_destroySurface; +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSVULKANINSTANCE_H diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 8950ec3bfc..25f7e11c60 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -67,6 +67,10 @@ #include <dwmapi.h> +#if QT_CONFIG(vulkan) +#include "qwindowsvulkaninstance.h" +#endif + QT_BEGIN_NAMESPACE enum { @@ -308,13 +312,15 @@ static QWindow::Visibility windowVisibility_sys(HWND hwnd) return QWindow::Windowed; } -static inline bool windowIsOpenGL(const QWindow *w) +static inline bool windowIsAccelerated(const QWindow *w) { switch (w->surfaceType()) { case QSurface::OpenGLSurface: return true; case QSurface::RasterGLSurface: return qt_window_private(const_cast<QWindow *>(w))->compositing; + case QSurface::VulkanSurface: + return true; default: return false; } @@ -375,11 +381,11 @@ bool QWindowsWindow::setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool has return needsLayered; } -static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bool openGL, qreal level) +static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bool accelerated, qreal level) { if (QWindowsWindow::setWindowLayered(hwnd, flags, hasAlpha, level)) { const BYTE alpha = BYTE(qRound(255.0 * level)); - if (hasAlpha && !openGL && (flags & Qt::FramelessWindowHint)) { + if (hasAlpha && !accelerated && (flags & Qt::FramelessWindowHint)) { // Non-GL windows with alpha: Use blend function to update. BLENDFUNCTION blend = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA}; UpdateLayeredWindow(hwnd, NULL, NULL, NULL, NULL, NULL, 0, &blend, ULW_ALPHA); @@ -393,13 +399,13 @@ static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bo static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::WindowFlags flags, qreal opacity) { - const bool isGL = windowIsOpenGL(w); + const bool isAccelerated = windowIsAccelerated(w); const bool hasAlpha = w->format().hasAlpha(); - if (isGL && hasAlpha) + if (isAccelerated && hasAlpha) applyBlurBehindWindow(hwnd); - setWindowOpacity(hwnd, flags, hasAlpha, isGL, opacity); + setWindowOpacity(hwnd, flags, hasAlpha, isAccelerated, opacity); } /*! @@ -1053,6 +1059,9 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) m_data(data), m_cursor(new CursorHandle), m_format(aWindow->requestedFormat()) +#if QT_CONFIG(vulkan) + , m_vkSurface(0) +#endif { // Clear the creation context as the window can be found in QWindowsContext's map. QWindowsContext::instance()->setWindowCreationContext(QSharedPointer<QWindowCreationContext>()); @@ -1068,6 +1077,10 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) setFlag(OpenGL_ES2); } #endif // QT_NO_OPENGL +#if QT_CONFIG(vulkan) + if (aWindow->surfaceType() == QSurface::VulkanSurface) + setFlag(VulkanSurface); +#endif updateDropSite(window()->isTopLevel()); registerTouchWindow(); @@ -1121,6 +1134,14 @@ void QWindowsWindow::destroyWindow() if (hasMouseCapture()) setMouseGrabEnabled(false); setDropSiteEnabled(false); +#if QT_CONFIG(vulkan) + if (m_vkSurface) { + QVulkanInstance *inst = window()->vulkanInstance(); + if (inst) + static_cast<QWindowsVulkanInstance *>(inst->handle())->destroySurface(m_vkSurface); + m_vkSurface = 0; + } +#endif #ifndef QT_NO_OPENGL if (m_surface) { if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) @@ -1470,8 +1491,10 @@ void QWindowsWindow::handleHidden() void QWindowsWindow::handleCompositionSettingsChanged() { const QWindow *w = window(); - if (w->surfaceType() == QWindow::OpenGLSurface && w->format().hasAlpha()) + if ((w->surfaceType() == QWindow::OpenGLSurface || w->surfaceType() == QWindow::VulkanSurface) + && w->format().hasAlpha()) { applyBlurBehindWindow(handle()); + } } static QRect normalFrameGeometry(HWND hwnd) @@ -1693,8 +1716,11 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message, BeginPaint(hwnd, &ps); // Observed painting problems with Aero style disabled (QTBUG-7865). - if (Q_UNLIKELY(testFlag(OpenGLSurface) && testFlag(OpenGLDoubleBuffered) && !dwmIsCompositionEnabled())) + if (Q_UNLIKELY(!dwmIsCompositionEnabled()) + && ((testFlag(OpenGLSurface) && testFlag(OpenGLDoubleBuffered)) || testFlag(VulkanSurface))) + { SelectClipRgn(ps.hdc, NULL); + } // If the a window is obscured by another window (such as a child window) // we still need to send isExposed=true, for compatibility. @@ -2030,7 +2056,7 @@ void QWindowsWindow::setOpacity(qreal level) m_opacity = level; if (m_data.hwnd) setWindowOpacity(m_data.hwnd, m_data.flags, - window()->format().hasAlpha(), testFlag(OpenGLSurface), + window()->format().hasAlpha(), testFlag(OpenGLSurface) || testFlag(VulkanSurface), level); } } @@ -2448,11 +2474,27 @@ void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins) void *QWindowsWindow::surface(void *nativeConfig, int *err) { -#ifdef QT_NO_OPENGL +#if QT_CONFIG(vulkan) + Q_UNUSED(nativeConfig); + Q_UNUSED(err); + if (window()->surfaceType() == QSurface::VulkanSurface) { + if (!m_vkSurface) { + QVulkanInstance *inst = window()->vulkanInstance(); + if (inst) + m_vkSurface = static_cast<QWindowsVulkanInstance *>(inst->handle())->createSurface(handle()); + else + qWarning("Attempted to create Vulkan surface without an instance; was QWindow::setVulkanInstance() called?"); + } + // Different semantics for VkSurfaces: the return value is the address, + // not the value, given that this is a 64-bit handle even on x86. + return &m_vkSurface; + } +#elif defined(QT_NO_OPENGL) Q_UNUSED(err) Q_UNUSED(nativeConfig) return 0; -#else +#endif +#ifndef QT_NO_OPENGL if (!m_surface) { if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) m_surface = staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig, err); @@ -2464,6 +2506,14 @@ void *QWindowsWindow::surface(void *nativeConfig, int *err) void QWindowsWindow::invalidateSurface() { +#if QT_CONFIG(vulkan) + if (m_vkSurface) { + QVulkanInstance *inst = window()->vulkanInstance(); + if (inst) + static_cast<QWindowsVulkanInstance *>(inst->handle())->destroySurface(m_vkSurface); + m_vkSurface = 0; + } +#endif #ifndef QT_NO_OPENGL if (m_surface) { if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index b55529588c..46236c10b5 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -46,6 +46,10 @@ #include <qpa/qplatformwindow.h> #include <QtPlatformHeaders/qwindowswindowfunctions.h> +#if QT_CONFIG(vulkan) +#include "qwindowsvulkaninstance.h" +#endif + QT_BEGIN_NAMESPACE class QWindowsOleDropTarget; @@ -209,6 +213,7 @@ public: Compositing = 0x200000, HasBorderInFullScreen = 0x400000, WithinDpiChanged = 0x800000, + VulkanSurface = 0x1000000 }; QWindowsWindow(QWindow *window, const QWindowsWindowData &data); @@ -351,6 +356,11 @@ private: HICON m_iconSmall = 0; HICON m_iconBig = 0; void *m_surface = nullptr; + +#if QT_CONFIG(vulkan) + // note: intentionally not using void * in order to avoid breaking x86 + VkSurfaceKHR m_vkSurface = 0; +#endif }; #ifndef QT_NO_DEBUG_STREAM diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index 1a80526aab..7694824d20 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -68,6 +68,11 @@ qtConfig(dynamicgl) { HEADERS += $$PWD/qwindowseglcontext.h } +qtConfig(vulkan) { + SOURCES += $$PWD/qwindowsvulkaninstance.cpp + HEADERS += $$PWD/qwindowsvulkaninstance.h +} + !contains( DEFINES, QT_NO_CLIPBOARD ) { SOURCES += $$PWD/qwindowsclipboard.cpp HEADERS += $$PWD/qwindowsclipboard.h diff --git a/src/plugins/platforms/windows/windows.pro b/src/plugins/platforms/windows/windows.pro index 23168c10dc..4d788d91f8 100644 --- a/src/plugins/platforms/windows/windows.pro +++ b/src/plugins/platforms/windows/windows.pro @@ -5,6 +5,8 @@ QT += \ eventdispatcher_support-private accessibility_support-private \ fontdatabase_support-private theme_support-private +qtConfig(vulkan): QT += vulkan_support-private + LIBS += -lgdi32 -ldwmapi include(windows.pri) |