diff options
Diffstat (limited to 'src/plugins')
16 files changed, 543 insertions, 188 deletions
diff --git a/src/plugins/platforms/CMakeLists.txt b/src/plugins/platforms/CMakeLists.txt index bb246565b9..f6206942ea 100644 --- a/src/plugins/platforms/CMakeLists.txt +++ b/src/plugins/platforms/CMakeLists.txt @@ -52,3 +52,6 @@ endif() if(QT_FEATURE_integrityfb) # add_subdirectory(integrity) # special case TODO endif() +if(QT_FEATURE_vkkhrdisplay) + add_subdirectory(vkkhrdisplay) +endif() diff --git a/src/plugins/platforms/eglfs/CMakeLists.txt b/src/plugins/platforms/eglfs/CMakeLists.txt index 4333a04df5..25223d5d3b 100644 --- a/src/plugins/platforms/eglfs/CMakeLists.txt +++ b/src/plugins/platforms/eglfs/CMakeLists.txt @@ -90,11 +90,6 @@ if(QT_FEATURE_cursor) ) endif() -qt_internal_extend_target(EglFSDeviceIntegration CONDITION QT_FEATURE_vulkan - SOURCES - api/vulkan/qeglfsvulkaninstance.cpp api/vulkan/qeglfsvulkaninstance_p.h - api/vulkan/qeglfsvulkanwindow.cpp api/vulkan/qeglfsvulkanwindow_p.h -) ##################################################################### ## QEglFSIntegrationPlugin Plugin: ##################################################################### diff --git a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp index 3ef30f1fa9..813de2fc47 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp @@ -376,14 +376,6 @@ void *QEglFSDeviceIntegration::wlDisplay() const return nullptr; } -#if QT_CONFIG(vulkan) -QPlatformVulkanInstance *QEglFSDeviceIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) -{ - Q_UNUSED(instance); - return nullptr; -} -#endif - EGLConfig QEglFSDeviceIntegration::chooseConfig(EGLDisplay display, const QSurfaceFormat &format) { class Chooser : public QEglConfigChooser { diff --git a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h index 29efb75137..f8c0d6c508 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h @@ -108,10 +108,6 @@ public: virtual void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen); virtual void *wlDisplay() const; -#if QT_CONFIG(vulkan) - virtual QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance); -#endif - static EGLConfig chooseConfig(EGLDisplay display, const QSurfaceFormat &format); }; diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp index a2dd426ad6..33b57353fc 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp @@ -241,13 +241,6 @@ QPlatformOffscreenSurface *QEglFSIntegration::createPlatformOffscreenSurface(QOf } #endif // QT_NO_OPENGL -#if QT_CONFIG(vulkan) -QPlatformVulkanInstance *QEglFSIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const -{ - return qt_egl_device_integration()->createPlatformVulkanInstance(instance); -} -#endif - bool QEglFSIntegration::hasCapability(QPlatformIntegration::Capability cap) const { // We assume that devices will have more and not less capabilities @@ -367,12 +360,6 @@ void *QEglFSIntegration::nativeResourceForWindow(const QByteArray &resource, QWi if (window && window->handle()) result = reinterpret_cast<void*>(static_cast<QEglFSWindow *>(window->handle())->surface()); break; -#if QT_CONFIG(vulkan) - case VkSurface: - if (window && window->handle() && window->surfaceType() == QSurface::VulkanSurface) - result = static_cast<QEglFSWindow *>(window->handle())->vulkanSurfacePtr(); - break; -#endif default: break; } diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h b/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h index bba1f2843f..f08ea73641 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h @@ -97,9 +97,6 @@ public: QOpenGLContext *createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const override; QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override; #endif -#if QT_CONFIG(vulkan) - QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const override; -#endif bool hasCapability(QPlatformIntegration::Capability cap) const override; QPlatformNativeInterface *nativeInterface() const override; diff --git a/src/plugins/platforms/eglfs/api/qeglfswindow_p.h b/src/plugins/platforms/eglfs/api/qeglfswindow_p.h index 130b87eef7..6b34071d1a 100644 --- a/src/plugins/platforms/eglfs/api/qeglfswindow_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfswindow_p.h @@ -97,9 +97,6 @@ public: EGLNativeWindowType eglWindow() const; EGLSurface surface() const; QEglFSScreen *screen() const override; -#if QT_CONFIG(vulkan) - virtual void *vulkanSurfacePtr() { return nullptr; } -#endif bool hasNativeWindow() const { return m_flags.testFlag(HasNativeWindow); } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp index 2daf277d71..0f6e36caf7 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp @@ -41,11 +41,6 @@ #include <EGL/eglvivante.h> #include <QDebug> -#if QT_CONFIG(vulkan) -#include "private/qeglfsvulkaninstance_p.h" -#include "private/qeglfsvulkanwindow_p.h" -#endif - #ifdef Q_OS_INTEGRITY extern "C" void VivanteInit(void); #endif @@ -102,20 +97,4 @@ void QEglFSVivIntegration::destroyNativeWindow(EGLNativeWindowType window) fbDestroyWindow(window); } -#if QT_CONFIG(vulkan) - -QEglFSWindow *QEglFSVivIntegration::createWindow(QWindow *window) const -{ - if (window->surfaceType() == QSurface::VulkanSurface) - return new QEglFSVulkanWindow(window); - return QEglFSDeviceIntegration::createWindow(window); -} - -QPlatformVulkanInstance *QEglFSVivIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) -{ - return new QEglFSVulkanInstance(instance); -} - -#endif // vulkan - QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h index 02b59c16b5..4d1718afcf 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h @@ -53,12 +53,6 @@ public: void destroyNativeWindow(EGLNativeWindowType window) override; EGLNativeDisplayType platformDisplay() const override; - // Vulkan support with VK_KHR_display -#if QT_CONFIG(vulkan) - QEglFSWindow *createWindow(QWindow *window) const override; - QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) override; -#endif - private: QSize mScreenSize; EGLNativeDisplayType mNativeDisplay; diff --git a/src/plugins/platforms/vkkhrdisplay/CMakeLists.txt b/src/plugins/platforms/vkkhrdisplay/CMakeLists.txt new file mode 100644 index 0000000000..de604bc491 --- /dev/null +++ b/src/plugins/platforms/vkkhrdisplay/CMakeLists.txt @@ -0,0 +1,29 @@ +qt_find_package(WrapFreetype PROVIDED_TARGETS WrapFreetype::WrapFreetype) + +qt_internal_add_plugin(QVkKhrDisplayIntegrationPlugin + OUTPUT_NAME qvkkhrdisplay + TYPE platforms + DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES vkkhrdisplay + SOURCES + main.cpp + qvkkhrdisplayintegration.cpp qvkkhrdisplayintegration.h + qvkkhrdisplayvulkaninstance.cpp qvkkhrdisplayvulkaninstance.h + DEFINES + QT_NO_FOREACH + PUBLIC_LIBRARIES + Qt::Core + Qt::CorePrivate + Qt::FbSupportPrivate + Qt::Gui + Qt::GuiPrivate +) + +qt_internal_extend_target(QVkKhrDisplayIntegrationPlugin CONDITION QT_FEATURE_freetype + LIBRARIES + WrapFreetype::WrapFreetype +) + +qt_internal_extend_target(QVkKhrDisplayIntegrationPlugin CONDITION TARGET Qt::InputSupportPrivate + PUBLIC_LIBRARIES + Qt::InputSupportPrivate +) diff --git a/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkanwindow_p.h b/src/plugins/platforms/vkkhrdisplay/main.cpp index 492fb41ca4..d9a0a155f4 100644 --- a/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkanwindow_p.h +++ b/src/plugins/platforms/vkkhrdisplay/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -37,38 +37,27 @@ ** ****************************************************************************/ -#ifndef QEGLFSVULKANWINDOW_H -#define QEGLFSVULKANWINDOW_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qeglfsglobal_p.h" -#include "qeglfswindow_p.h" -#include "qeglfsvulkaninstance_p.h" +#include <qpa/qplatformintegrationplugin.h> +#include "qvkkhrdisplayintegration.h" QT_BEGIN_NAMESPACE -class Q_EGLFS_EXPORT QEglFSVulkanWindow : public QEglFSWindow +class QVkKhrDisplayIntegrationPlugin : public QPlatformIntegrationPlugin { + Q_OBJECT + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "vkkhrdisplay.json") public: - QEglFSVulkanWindow(QWindow *window); - ~QEglFSVulkanWindow(); + QPlatformIntegration *create(const QString&, const QStringList&) override; +}; - void *vulkanSurfacePtr() override; +QPlatformIntegration *QVkKhrDisplayIntegrationPlugin::create(const QString &system, const QStringList ¶mList) +{ + if (!system.compare(QLatin1String("vkkhrdisplay"), Qt::CaseInsensitive)) + return new QVkKhrDisplayIntegration(paramList); -private: - VkSurfaceKHR m_surface; -}; + return 0; +} QT_END_NAMESPACE -#endif +#include "main.moc" diff --git a/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayintegration.cpp b/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayintegration.cpp new file mode 100644 index 0000000000..34f5ebb962 --- /dev/null +++ b/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayintegration.cpp @@ -0,0 +1,345 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the 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 "qvkkhrdisplayintegration.h" +#include "qvkkhrdisplayvulkaninstance.h" + +#include <qpa/qplatformwindow.h> +#include <qpa/qplatformbackingstore.h> +#include <qpa/qplatforminputcontextfactory_p.h> +#include <qpa/qwindowsysteminterface.h> + +#include <QtGui/private/qguiapplication_p.h> +#include <QtGui/private/qwindow_p.h> +#include <QtGui/private/qgenericunixeventdispatcher_p.h> +#include <QtGui/private/qgenericunixfontdatabase_p.h> +#include <QtGui/private/qgenericunixthemes_p.h> +#include <QtGui/private/qgenericunixservices_p.h> + +#include <QtFbSupport/private/qfbvthandler_p.h> + +#if QT_CONFIG(libinput) +#include <QtInputSupport/private/qlibinputhandler_p.h> +#endif + +#if QT_CONFIG(evdev) +#include <QtInputSupport/private/qevdevmousemanager_p.h> +#include <QtInputSupport/private/qevdevkeyboardmanager_p.h> +#include <QtInputSupport/private/qevdevtouchmanager_p.h> +#endif + +#if QT_CONFIG(tslib) +#include <QtInputSupport/private/qtslib_p.h> +#endif + +QT_BEGIN_NAMESPACE + +class QVkKhrDisplayScreen : public QPlatformScreen +{ +public: + QRect geometry() const override { return m_geometry; } + int depth() const override { return m_depth; } + QImage::Format format() const override { return m_format; } + void setVk(QVkKhrDisplayVulkanInstance *inst); + +private: + QVkKhrDisplayVulkanInstance *m_vk = nullptr; + QRect m_geometry; + int m_depth = 32; + QImage::Format m_format = QImage::Format_ARGB32_Premultiplied; + friend class QVkKhrDisplayIntegration; +}; + +void QVkKhrDisplayScreen::setVk(QVkKhrDisplayVulkanInstance *inst) +{ + m_vk = inst; + m_geometry = QRect(QPoint(0, 0), m_vk->displaySize()); + QWindowSystemInterface::handleScreenGeometryChange(screen(), m_geometry, m_geometry); + qDebug() << "Screen will report geometry" << m_geometry; + + // Thanks to this deferred screen setup, a QWindow with a size based on the + // dummy screen size may already exist. Try to resize it. + QScreen *thisScreen = screen(); + for (QWindow *window : QGuiApplication::allWindows()) { + if (window->isTopLevel() && window->screen() == thisScreen) + window->handle()->setGeometry(QRect()); // set fullscreen geometry + } +} + +class QVkKhrDisplayWindow : public QPlatformWindow +{ +public: + QVkKhrDisplayWindow(QWindow *window) : QPlatformWindow(window) { } + ~QVkKhrDisplayWindow(); + + void *vulkanSurfacePtr(); + + void setGeometry(const QRect &r) override; + +private: + VkSurfaceKHR m_surface = VK_NULL_HANDLE; +}; + +QVkKhrDisplayWindow::~QVkKhrDisplayWindow() +{ + if (m_surface) { + QVulkanInstance *inst = window()->vulkanInstance(); + if (inst) + static_cast<QVkKhrDisplayVulkanInstance *>(inst->handle())->destroySurface(m_surface); + } +} + +void *QVkKhrDisplayWindow::vulkanSurfacePtr() +{ + if (m_surface) + return &m_surface; + + QVulkanInstance *inst = window()->vulkanInstance(); + if (!inst) { + qWarning("Attempted to create Vulkan surface without an instance; was QWindow::setVulkanInstance() called?"); + return nullptr; + } + QVkKhrDisplayVulkanInstance *vkdinst = static_cast<QVkKhrDisplayVulkanInstance *>(inst->handle()); + m_surface = vkdinst->createSurface(window()); + + return &m_surface; +} + +void QVkKhrDisplayWindow::setGeometry(const QRect &) +{ + // We only support full-screen windows + QRect rect(screen()->availableGeometry()); + QWindowSystemInterface::handleGeometryChange(window(), rect); + QPlatformWindow::setGeometry(rect); + + const QRect lastReportedGeometry = qt_window_private(window())->geometry; + if (rect != lastReportedGeometry) + QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), rect.size())); +} + +// does not actually support raster content, just paint into a QImage and that's it for now +class QVkKhrDisplayBackingStore : public QPlatformBackingStore +{ +public: + QVkKhrDisplayBackingStore(QWindow *window) : QPlatformBackingStore(window) { } + + QPaintDevice *paintDevice() override { return &m_image; } + void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) override { + Q_UNUSED(window); + Q_UNUSED(region); + Q_UNUSED(offset); + } + void resize(const QSize &size, const QRegion &staticContents) override { + Q_UNUSED(staticContents); + QImage::Format format = QGuiApplication::primaryScreen()->handle()->format(); + if (m_image.size() != size) + m_image = QImage(size, format); + } + +private: + QImage m_image; +}; + +QVkKhrDisplayIntegration::QVkKhrDisplayIntegration(const QStringList ¶meters) +{ + Q_UNUSED(parameters); +} + +QVkKhrDisplayIntegration::~QVkKhrDisplayIntegration() +{ + QWindowSystemInterface::handleScreenRemoved(m_primaryScreen); + delete m_services; + delete m_fontDatabase; + delete m_vtHandler; +} + +bool QVkKhrDisplayIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case ThreadedPixmaps: return true; + case WindowManagement: return false; + default: return QPlatformIntegration::hasCapability(cap); + } +} + +void QVkKhrDisplayIntegration::initialize() +{ + m_primaryScreen = new QVkKhrDisplayScreen; + + // The real values are only known when the QVulkanInstance initializes, use + // dummy values until then. + m_primaryScreen->m_geometry = QRect(0, 0, 1920, 1080); + m_primaryScreen->m_depth = 32; + m_primaryScreen->m_format = QImage::Format_ARGB32_Premultiplied; + + QWindowSystemInterface::handleScreenAdded(m_primaryScreen); + + m_inputContext = QPlatformInputContextFactory::create(); + + m_vtHandler = new QFbVtHandler; + + if (!qEnvironmentVariableIntValue("QT_QPA_DISABLE_INPUT")) + createInputHandlers(); +} + +QPlatformFontDatabase *QVkKhrDisplayIntegration::fontDatabase() const +{ + if (!m_fontDatabase) + m_fontDatabase = new QGenericUnixFontDatabase; + + return m_fontDatabase; +} + +QPlatformServices *QVkKhrDisplayIntegration::services() const +{ + if (!m_services) + m_services = new QGenericUnixServices; + + return m_services; +} + +QPlatformInputContext *QVkKhrDisplayIntegration::inputContext() const +{ + return m_inputContext; +} + +QPlatformTheme *QVkKhrDisplayIntegration::createPlatformTheme(const QString &name) const +{ + return QGenericUnixTheme::createUnixTheme(name); +} + +QPlatformNativeInterface *QVkKhrDisplayIntegration::nativeInterface() const +{ + return const_cast<QVkKhrDisplayIntegration *>(this); +} + +QPlatformWindow *QVkKhrDisplayIntegration::createPlatformWindow(QWindow *window) const +{ + if (window->surfaceType() != QSurface::VulkanSurface) { + qWarning("vkkhrdisplay platform plugin only supports QWindow with surfaceType == VulkanSurface"); + return nullptr; + } + + QVkKhrDisplayWindow *w = new QVkKhrDisplayWindow(window); + w->setGeometry(QRect()); // set fullscreen geometry + w->requestActivateWindow(); + return w; +} + +QPlatformBackingStore *QVkKhrDisplayIntegration::createPlatformBackingStore(QWindow *window) const +{ + return new QVkKhrDisplayBackingStore(window); +} + +QAbstractEventDispatcher *QVkKhrDisplayIntegration::createEventDispatcher() const +{ + return createUnixEventDispatcher(); +} + +void QVkKhrDisplayIntegration::handleInstanceCreated(QVkKhrDisplayVulkanInstance *inst, void *userData) +{ + QVkKhrDisplayIntegration *self = static_cast<QVkKhrDisplayIntegration *>(userData); + self->m_primaryScreen->setVk(inst); +} + +QPlatformVulkanInstance *QVkKhrDisplayIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const +{ + QVkKhrDisplayVulkanInstance *inst = new QVkKhrDisplayVulkanInstance(instance); + inst->setCreatedCallback(handleInstanceCreated, const_cast<QVkKhrDisplayIntegration *>(this)); + return inst; +} + +enum ResourceType { + VkSurface +}; + +static int resourceType(const QByteArray &key) +{ + static const QByteArray names[] = { // match ResourceType + QByteArrayLiteral("vksurface") + }; + const QByteArray *end = names + sizeof(names) / sizeof(names[0]); + const QByteArray *result = std::find(names, end, key); + if (result == end) + result = std::find(names, end, key.toLower()); + return int(result - names); +} + +void *QVkKhrDisplayIntegration::nativeResourceForWindow(const QByteArray &resource, QWindow *window) +{ + void *result = nullptr; + + switch (resourceType(resource)) { + case VkSurface: + if (window && window->handle() && window->surfaceType() == QSurface::VulkanSurface) + result = static_cast<QVkKhrDisplayWindow *>(window->handle())->vulkanSurfacePtr(); + break; + default: + break; + } + + return result; +} + +void QVkKhrDisplayIntegration::createInputHandlers() +{ +#if QT_CONFIG(libinput) + if (!qEnvironmentVariableIntValue("QT_QPA_NO_LIBINPUT")) { + new QLibInputHandler(QLatin1String("libinput"), QString()); + return; + } +#endif + +#if QT_CONFIG(tslib) + bool useTslib = qEnvironmentVariableIntValue("QT_QPA_TSLIB"); + if (useTslib) + new QTsLibMouseHandler(QLatin1String("TsLib"), QString()); +#endif + +#if QT_CONFIG(evdev) + new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this); + new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this); +#if QT_CONFIG(tslib) + if (!useTslib) +#endif + new QEvdevTouchManager(QLatin1String("EvdevTouch"), QString() /* spec */, this); +#endif +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkanwindow.cpp b/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayintegration.h index ae41ca00b6..9eb32291bd 100644 --- a/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkanwindow.cpp +++ b/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayintegration.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -37,39 +37,52 @@ ** ****************************************************************************/ -#include "qeglfsvulkanwindow_p.h" +#ifndef QPLATFORMINTEGRATION_VKKHRDISPLAY_H +#define QPLATFORMINTEGRATION_VKKHRDISPLAY_H + +#include <qpa/qplatformintegration.h> +#include <qpa/qplatformnativeinterface.h> +#include <qpa/qplatformscreen.h> QT_BEGIN_NAMESPACE -QEglFSVulkanWindow::QEglFSVulkanWindow(QWindow *window) - : QEglFSWindow(window), - m_surface(VK_NULL_HANDLE) -{ -} +class QVkKhrDisplayScreen; +class QVkKhrDisplayVulkanInstance; +class QFbVtHandler; -QEglFSVulkanWindow::~QEglFSVulkanWindow() +class QVkKhrDisplayIntegration : public QPlatformIntegration, public QPlatformNativeInterface { - if (m_surface) { - QVulkanInstance *inst = window()->vulkanInstance(); - if (inst) - static_cast<QEglFSVulkanInstance *>(inst->handle())->destroySurface(m_surface); - } -} +public: + explicit QVkKhrDisplayIntegration(const QStringList ¶meters); + ~QVkKhrDisplayIntegration(); -void *QEglFSVulkanWindow::vulkanSurfacePtr() -{ - if (m_surface) - return &m_surface; + void initialize() override; + + bool hasCapability(QPlatformIntegration::Capability cap) const override; + QPlatformFontDatabase *fontDatabase() const override; + QPlatformServices *services() const override; + QPlatformInputContext *inputContext() const override; + QPlatformTheme *createPlatformTheme(const QString &name) const override; + QPlatformNativeInterface *nativeInterface() const override; - QVulkanInstance *inst = window()->vulkanInstance(); - if (!inst) { - qWarning("Attempted to create Vulkan surface without an instance; was QWindow::setVulkanInstance() called?"); - return nullptr; - } - QEglFSVulkanInstance *eglfsInst = static_cast<QEglFSVulkanInstance *>(inst->handle()); - m_surface = eglfsInst->createSurface(this); + QPlatformWindow *createPlatformWindow(QWindow *window) const override; + QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override; + QAbstractEventDispatcher *createEventDispatcher() const override; + QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const override; - return &m_surface; -} + void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) override; + +private: + static void handleInstanceCreated(QVkKhrDisplayVulkanInstance *, void *); + void createInputHandlers(); + + mutable QPlatformFontDatabase *m_fontDatabase = nullptr; + mutable QPlatformServices *m_services = nullptr; + QPlatformInputContext *m_inputContext = nullptr; + QFbVtHandler *m_vtHandler = nullptr; + QVkKhrDisplayScreen *m_primaryScreen = nullptr; +}; QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkaninstance.cpp b/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayvulkaninstance.cpp index a75251ca5f..f6be2f3305 100644 --- a/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkaninstance.cpp +++ b/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayvulkaninstance.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -37,29 +37,25 @@ ** ****************************************************************************/ -#include "qeglfsvulkaninstance_p.h" -#include "qeglfswindow_p.h" -#include "qeglfshooks_p.h" -#include <QLoggingCategory> +#include "qvkkhrdisplayvulkaninstance.h" QT_BEGIN_NAMESPACE -Q_DECLARE_LOGGING_CATEGORY(qLcEglDevDebug) - -QEglFSVulkanInstance::QEglFSVulkanInstance(QVulkanInstance *instance) +QVkKhrDisplayVulkanInstance::QVkKhrDisplayVulkanInstance(QVulkanInstance *instance) : m_instance(instance) { loadVulkanLibrary(QStringLiteral("vulkan")); } -void QEglFSVulkanInstance::createOrAdoptInstance() +void QVkKhrDisplayVulkanInstance::createOrAdoptInstance() { - qCDebug(qLcEglDevDebug, "Creating Vulkan instance for VK_KHR_display"); + qDebug("Creating Vulkan instance for VK_KHR_display"); const QByteArray extName = QByteArrayLiteral("VK_KHR_display"); initInstance(m_instance, { extName }); if (!m_vkInst) return; + if (!enabledExtensions().contains(extName)) { qWarning("Failed to enable VK_KHR_display extension"); return; @@ -109,11 +105,16 @@ void QEglFSVulkanInstance::createOrAdoptInstance() if (m_physDev == VK_NULL_HANDLE) m_physDev = physDevs[0]; + + if (chooseDisplay()) { + if (m_createdCallback) + m_createdCallback(this, m_createdCallbackUserData); + } } -bool QEglFSVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex, - QWindow *window) +bool QVkKhrDisplayVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + QWindow *window) { Q_UNUSED(physicalDevice); Q_UNUSED(queueFamilyIndex); @@ -121,43 +122,41 @@ bool QEglFSVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, return true; } -VkSurfaceKHR QEglFSVulkanInstance::createSurface(QEglFSWindow *window) +bool QVkKhrDisplayVulkanInstance::chooseDisplay() { #if VK_KHR_display - qCDebug(qLcEglDevDebug, "Creating VkSurfaceKHR via VK_KHR_display for window %p", (void *) window); - - if (!m_physDev) { - qWarning("No physical device, cannot create surface"); - return VK_NULL_HANDLE; - } - uint32_t displayCount = 0; VkResult err = m_getPhysicalDeviceDisplayPropertiesKHR(m_physDev, &displayCount, nullptr); if (err != VK_SUCCESS) { qWarning("Failed to get display properties: %d", err); - return VK_NULL_HANDLE; + return false; } - qCDebug(qLcEglDevDebug, "Display count: %u", displayCount); + qDebug("Display count: %u", displayCount); QVarLengthArray<VkDisplayPropertiesKHR, 4> displayProps(displayCount); m_getPhysicalDeviceDisplayPropertiesKHR(m_physDev, &displayCount, displayProps.data()); - VkDisplayKHR display = VK_NULL_HANDLE; - VkDisplayModeKHR displayMode = VK_NULL_HANDLE; - uint32_t width = 0; - uint32_t height = 0; + m_display = VK_NULL_HANDLE; + m_displayMode = VK_NULL_HANDLE; + + // Pick the first display and the first mode, unless specified via env.vars. + uint32_t wantedDisplayIndex = 0; + uint32_t wantedModeIndex = 0; + if (qEnvironmentVariableIsSet("QT_VK_DISPLAY_INDEX")) + wantedDisplayIndex = uint32_t(qEnvironmentVariableIntValue("QT_VK_DISPLAY_INDEX")); + if (qEnvironmentVariableIsSet("QT_VK_MODE_INDEX")) + wantedModeIndex = uint32_t(qEnvironmentVariableIntValue("QT_VK_MODE_INDEX")); for (uint32_t i = 0; i < displayCount; ++i) { const VkDisplayPropertiesKHR &disp(displayProps[i]); - qCDebug(qLcEglDevDebug, "Display #%u:\n display: %p\n name: %s\n dimensions: %ux%u\n resolution: %ux%u", + qDebug("Display #%u:\n display: %p\n name: %s\n dimensions: %ux%u\n resolution: %ux%u", i, (void *) disp.display, disp.displayName, disp.physicalDimensions.width, disp.physicalDimensions.height, disp.physicalResolution.width, disp.physicalResolution.height); - // Just pick the first display and the first mode. - if (i == 0) - display = disp.display; + if (i == wantedDisplayIndex) + m_display = disp.display; uint32_t modeCount = 0; if (m_getDisplayModePropertiesKHR(m_physDev, disp.display, &modeCount, nullptr) != VK_SUCCESS) { @@ -168,56 +167,59 @@ VkSurfaceKHR QEglFSVulkanInstance::createSurface(QEglFSWindow *window) m_getDisplayModePropertiesKHR(m_physDev, disp.display, &modeCount, modeProps.data()); for (uint32_t j = 0; j < modeCount; ++j) { const VkDisplayModePropertiesKHR &mode(modeProps[j]); - qCDebug(qLcEglDevDebug, " Mode #%u:\n mode: %p\n visibleRegion: %ux%u\n refreshRate: %u", + qDebug(" Mode #%u:\n mode: %p\n visibleRegion: %ux%u\n refreshRate: %u", j, (void *) mode.displayMode, mode.parameters.visibleRegion.width, mode.parameters.visibleRegion.height, mode.parameters.refreshRate); - if (j == 0) { - displayMode = mode.displayMode; - width = mode.parameters.visibleRegion.width; - height = mode.parameters.visibleRegion.height; + if (j == wantedModeIndex) { + m_displayMode = mode.displayMode; + m_width = mode.parameters.visibleRegion.width; + m_height = mode.parameters.visibleRegion.height; } } } - if (display == VK_NULL_HANDLE || displayMode == VK_NULL_HANDLE) { + if (m_display == VK_NULL_HANDLE || m_displayMode == VK_NULL_HANDLE) { qWarning("Failed to choose display and mode"); - return VK_NULL_HANDLE; + return false; } + + qDebug("Using display #%u with mode #%u", wantedDisplayIndex, wantedModeIndex); + uint32_t planeCount = 0; err = m_getPhysicalDeviceDisplayPlanePropertiesKHR(m_physDev, &planeCount, nullptr); if (err != VK_SUCCESS) { qWarning("Failed to get plane properties: %d", err); - return VK_NULL_HANDLE; + return false; } - qCDebug(qLcEglDevDebug, "Plane count: %u", planeCount); + qDebug("Plane count: %u", planeCount); QVarLengthArray<VkDisplayPlanePropertiesKHR, 4> planeProps(planeCount); m_getPhysicalDeviceDisplayPlanePropertiesKHR(m_physDev, &planeCount, planeProps.data()); - uint32_t planeIndex = UINT_MAX; + m_planeIndex = UINT_MAX; for (uint32_t i = 0; i < planeCount; ++i) { uint32_t supportedDisplayCount = 0; err = m_getDisplayPlaneSupportedDisplaysKHR(m_physDev, i, &supportedDisplayCount, nullptr); if (err != VK_SUCCESS) { qWarning("Failed to query supported displays for plane: %d", err); - return VK_NULL_HANDLE; + return false; } QVarLengthArray<VkDisplayKHR, 4> supportedDisplays(supportedDisplayCount); m_getDisplayPlaneSupportedDisplaysKHR(m_physDev, i, &supportedDisplayCount, supportedDisplays.data()); - qCDebug(qLcEglDevDebug, "Plane #%u supports %u displays, currently bound to display %p", + qDebug("Plane #%u supports %u displays, currently bound to display %p", i, supportedDisplayCount, (void *) planeProps[i].currentDisplay); VkDisplayPlaneCapabilitiesKHR caps; - err = m_getDisplayPlaneCapabilitiesKHR(m_physDev, displayMode, i, &caps); + err = m_getDisplayPlaneCapabilitiesKHR(m_physDev, m_displayMode, i, &caps); if (err != VK_SUCCESS) { qWarning("Failed to query plane capabilities: %d", err); - return VK_NULL_HANDLE; + return false; } - qCDebug(qLcEglDevDebug, " supportedAlpha: %d (1=no, 2=global, 4=per pixel, 8=per pixel premul)\n" + qDebug(" supportedAlpha: %d (1=no, 2=global, 4=per pixel, 8=per pixel premul)\n" " minSrc=%d, %d %ux%u\n" " maxSrc=%d, %d %ux%u\n" " minDst=%d, %d %ux%u\n" @@ -229,52 +231,69 @@ VkSurfaceKHR QEglFSVulkanInstance::createSurface(QEglFSWindow *window) caps.maxDstPosition.x, caps.maxDstPosition.y, caps.maxDstExtent.width, caps.maxDstExtent.height); // if the plane is not in use and supports our chosen display, use that plane - if (supportedDisplays.contains(display) - && (planeProps[i].currentDisplay == VK_NULL_HANDLE || planeProps[i].currentDisplay == display)) + if (supportedDisplays.contains(m_display) + && (planeProps[i].currentDisplay == VK_NULL_HANDLE || planeProps[i].currentDisplay == m_display)) { - planeIndex = i; + m_planeIndex = i; + m_planeStackIndex = planeProps[i].currentStackIndex; } } - if (planeIndex == UINT_MAX) { + if (m_planeIndex == UINT_MAX) { qWarning("Failed to find a suitable plane"); - return VK_NULL_HANDLE; + return false; } - qCDebug(qLcEglDevDebug, "Using plane #%u", planeIndex); + qDebug("Using plane #%u", m_planeIndex); + return true; +#else + return false; +#endif +} + +VkSurfaceKHR QVkKhrDisplayVulkanInstance::createSurface(QWindow *window) +{ +#if VK_KHR_display + qDebug("Creating VkSurfaceKHR via VK_KHR_display for window %p", (void *) window); + + if (!m_physDev) { + qWarning("No physical device, cannot create surface"); + return VK_NULL_HANDLE; + } + if (!m_display || !m_displayMode) { + qWarning("No display mode chosen, cannot create surface"); + return VK_NULL_HANDLE; + } VkDisplaySurfaceCreateInfoKHR surfaceCreateInfo = {}; surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR; - surfaceCreateInfo.displayMode = displayMode; - surfaceCreateInfo.planeIndex = planeIndex; - surfaceCreateInfo.planeStackIndex = planeProps[planeIndex].currentStackIndex; + surfaceCreateInfo.displayMode = m_displayMode; + surfaceCreateInfo.planeIndex = m_planeIndex; + surfaceCreateInfo.planeStackIndex = m_planeStackIndex; surfaceCreateInfo.transform = VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR; surfaceCreateInfo.globalAlpha = 1.0f; surfaceCreateInfo.alphaMode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR; - surfaceCreateInfo.imageExtent = { width, height }; + surfaceCreateInfo.imageExtent = { m_width, m_height }; VkSurfaceKHR surface = VK_NULL_HANDLE; - err = m_createDisplayPlaneSurfaceKHR(m_vkInst, &surfaceCreateInfo, nullptr, &surface); + VkResult err = m_createDisplayPlaneSurfaceKHR(m_vkInst, &surfaceCreateInfo, nullptr, &surface); if (err != VK_SUCCESS || surface == VK_NULL_HANDLE) { qWarning("Failed to create surface: %d", err); return VK_NULL_HANDLE; } - qCDebug(qLcEglDevDebug, "Created surface %p", (void *) surface); + qDebug("Created surface %p", (void *) surface); return surface; - #else Q_UNUSED(window); - qWarning("VK_KHR_display support was not compiled in, cannot create surface"); return VK_NULL_HANDLE; #endif } -void QEglFSVulkanInstance::presentAboutToBeQueued(QWindow *window) +void QVkKhrDisplayVulkanInstance::presentAboutToBeQueued(QWindow *window) { - // support QT_QPA_EGLFS_FORCEVSYNC (i.MX8 with eglfs_viv) - qt_egl_device_integration()->waitForVSync(window->handle()); + Q_UNUSED(window); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkaninstance_p.h b/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayvulkaninstance.h index 7715cc37c0..efbc773b69 100644 --- a/src/plugins/platforms/eglfs/api/vulkan/qeglfsvulkaninstance_p.h +++ b/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayvulkaninstance.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef QEGLFSVULKANINSTANCE_H -#define QEGLFSVULKANINSTANCE_H +#ifndef QVKKHRDISPLAYVULKANINSTANCE_H +#define QVKKHRDISPLAYVULKANINSTANCE_H // // W A R N I N G @@ -51,25 +51,33 @@ // We mean it. // -#include "qeglfsglobal_p.h" #include <QtGui/private/qbasicvulkanplatforminstance_p.h> +#include <QtCore/qsize.h> QT_BEGIN_NAMESPACE -class QEglFSWindow; - -class Q_EGLFS_EXPORT QEglFSVulkanInstance : public QBasicPlatformVulkanInstance +class QVkKhrDisplayVulkanInstance : public QBasicPlatformVulkanInstance { public: - QEglFSVulkanInstance(QVulkanInstance *instance); + QVkKhrDisplayVulkanInstance(QVulkanInstance *instance); void createOrAdoptInstance() override; bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override; void presentAboutToBeQueued(QWindow *window) override; - VkSurfaceKHR createSurface(QEglFSWindow *window); + VkSurfaceKHR createSurface(QWindow *window); + + QSize displaySize() const { return QSize(int(m_width), int(m_height)); } + + using CreatedCallback = void (*)(QVkKhrDisplayVulkanInstance *, void *); + void setCreatedCallback(CreatedCallback callback, void *userData) { + m_createdCallback = callback; + m_createdCallbackUserData = userData; + } private: + bool chooseDisplay(); + QVulkanInstance *m_instance; VkPhysicalDevice m_physDev = VK_NULL_HANDLE; PFN_vkEnumeratePhysicalDevices m_enumeratePhysicalDevices = nullptr; @@ -81,6 +89,15 @@ private: PFN_vkGetDisplayPlaneCapabilitiesKHR m_getDisplayPlaneCapabilitiesKHR = nullptr; PFN_vkCreateDisplayPlaneSurfaceKHR m_createDisplayPlaneSurfaceKHR = nullptr; #endif + + CreatedCallback m_createdCallback = nullptr; + void *m_createdCallbackUserData = nullptr; + VkDisplayKHR m_display = VK_NULL_HANDLE; + VkDisplayModeKHR m_displayMode = VK_NULL_HANDLE; + uint32_t m_width = 0; + uint32_t m_height = 0; + uint32_t m_planeIndex = UINT_MAX; + uint32_t m_planeStackIndex = UINT_MAX; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/vkkhrdisplay/vkkhrdisplay.json b/src/plugins/platforms/vkkhrdisplay/vkkhrdisplay.json new file mode 100644 index 0000000000..dd7a77eb68 --- /dev/null +++ b/src/plugins/platforms/vkkhrdisplay/vkkhrdisplay.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "vkkhrdisplay" ] +} |