From 85a85537b17742a839092bcc2a4684ab0bdb65d5 Mon Sep 17 00:00:00 2001 From: Naoto Yamaguchi Date: Tue, 4 Jan 2022 23:52:31 +0900 Subject: [PATCH] Add drm-lease client support to eglfs kms backend This patch is adding drm-lease-manager client support to Qt eglfs backend. When this patch is enable, Qt wayland compositor and Qt eglfs without compositor possible to use leased drm device. List of environment variable: QT_QPA_EGLFS_DRMLEASE : When this variable is set, drm-lease-manager client support is enable. Shall set drm lease device such as `card0-LVDS-1`, `card0-HDMI-A-1 ` and etc. DLM_RUNTIME_PATH : It use drm-lease-manager client, typically it need to set own. Signed-off-by: Naoto Yamaguchi --- cmake/3rdparty/kwin/FindLibdlmclient.cmake | 127 ++++++++++++++++++ src/gui/configure.cmake | 1 + .../eglfs_kms/CMakeLists.txt | 2 + .../eglfs_kms/qeglfskmsgbmdevice.cpp | 43 ++++-- .../eglfs_kms/qeglfskmsgbmdevice_p.h | 4 + 5 files changed, 167 insertions(+), 10 deletions(-) create mode 100644 cmake/3rdparty/kwin/FindLibdlmclient.cmake diff --git a/cmake/3rdparty/kwin/FindLibdlmclient.cmake b/cmake/3rdparty/kwin/FindLibdlmclient.cmake new file mode 100644 index 0000000000..8dfac920ca --- /dev/null +++ b/cmake/3rdparty/kwin/FindLibdlmclient.cmake @@ -0,0 +1,127 @@ +#.rst: +# FindLibdlmclient +# ------- +# FindLibdlmclient.cmake is created based on FindLibinput.cmake +# +# Try to find libdlmclient on a Unix system. +# +# This will define the following variables: +# +# ``Libdlmclient_FOUND`` +# True if (the requested version of) libdlmclient is available +# ``Libdlmclient_VERSION`` +# The version of libdlmclient +# ``Libdlmclient_LIBRARIES`` +# This can be passed to target_link_libraries() instead of the ``Libdlmclient::Libdlmclient`` +# target +# ``Libdlmclient_INCLUDE_DIRS`` +# This should be passed to target_include_directories() if the target is not +# used for linking +# ``Libdlmclient_DEFINITIONS`` +# This should be passed to target_compile_options() if the target is not +# used for linking +# +# If ``Libdlmclient_FOUND`` is TRUE, it will also define the following imported target: +# +# ``Libdlmclient::Libdlmclient`` +# The libdlmclient library +# +# In general we recommend using the imported target, as it is easier to use. +# Bear in mind, however, that if the target is in the link interface of an +# exported library, it must be made available by the package config file. + +#============================================================================= +# Copyright 2014 Alex Merry +# Copyright 2014 Martin Gräßlin +# Copyright 2022 Naoto Yamaguchi +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +if(CMAKE_VERSION VERSION_LESS 2.8.12) + message(FATAL_ERROR "CMake 2.8.12 is required by FindLibdlmclient.cmake") +endif() +if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12) + message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use FindLibdlmclient.cmake") +endif() + +if(NOT WIN32) + # Use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + find_package(PkgConfig QUIET) + pkg_check_modules(PKG_Libdlmclient QUIET libdlmclient) + + set(Libdlmclient_DEFINITIONS ${PKG_Libdlmclient_CFLAGS_OTHER}) + set(Libdlmclient_VERSION ${PKG_Libdlmclient_VERSION}) + + find_path(Libdlmclient_INCLUDE_DIR + NAMES + dlmclient.h + HINTS + ${PKG_Libdlmclient_INCLUDE_DIRS} + ) + find_library(Libdlmclient_LIBRARY + NAMES + dlmclient + HINTS + ${PKG_Libdlmclient_LIBRARY_DIRS} + ) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(Libdlmclient + FOUND_VAR + Libdlmclient_FOUND + REQUIRED_VARS + Libdlmclient_LIBRARY + Libdlmclient_INCLUDE_DIR + VERSION_VAR + Libdlmclient_VERSION + ) + + if(Libdlmclient_FOUND AND NOT TARGET Libdlmclient::Libdlmclient) + add_library(Libdlmclient::Libdlmclient UNKNOWN IMPORTED) + set_target_properties(Libdlmclient::Libdlmclient PROPERTIES + IMPORTED_LOCATION "${Libdlmclient_LIBRARY}" + INTERFACE_COMPILE_OPTIONS "${Libdlmclient_DEFINITIONS}" + INTERFACE_INCLUDE_DIRECTORIES "${Libdlmclient_INCLUDE_DIR}" + ) + endif() + + mark_as_advanced(Libdlmclient_LIBRARY Libdlmclient_INCLUDE_DIR) + + # compatibility variables + set(Libdlmclient_LIBRARIES ${Libdlmclient_LIBRARY}) + set(Libdlmclient_INCLUDE_DIRS ${Libdlmclient_INCLUDE_DIR}) + set(Libdlmclient_VERSION_STRING ${Libdlmclient_VERSION}) + +else() + message(STATUS "FindLibdlmclient.cmake cannot find libdlmclient on Windows systems.") + set(Libdlmclient_FOUND FALSE) +endif() + +include(FeatureSummary) +set_package_properties(Libdlmclient PROPERTIES + URL "https://git.automotivelinux.org/src/drm-lease-manager/" + DESCRIPTION "The DRM Lease Manager uses the DRM Lease feature, introduced in the Linux kernel version 4.15, to partition display controller output resources between multiple processes." +) diff --git a/src/gui/configure.cmake b/src/gui/configure.cmake index 0bf250eab6..b092b746c0 100644 --- a/src/gui/configure.cmake +++ b/src/gui/configure.cmake @@ -38,6 +38,7 @@ endif() qt_find_package(Fontconfig PROVIDED_TARGETS Fontconfig::Fontconfig MODULE_NAME gui QMAKE_LIB fontconfig) qt_add_qmake_lib_dependency(fontconfig freetype) qt_find_package(gbm PROVIDED_TARGETS gbm::gbm MODULE_NAME gui QMAKE_LIB gbm) +qt_find_package(Libdlmclient PROVIDED_TARGETS Libdlmclient::Libdlmclient MODULE_NAME gui QMAKE_LIB libdlmclient) qt_find_package(WrapSystemHarfbuzz 2.6.0 PROVIDED_TARGETS WrapSystemHarfbuzz::WrapSystemHarfbuzz MODULE_NAME gui QMAKE_LIB harfbuzz) qt_find_package(Libinput PROVIDED_TARGETS Libinput::Libinput MODULE_NAME gui QMAKE_LIB libinput) qt_find_package(JPEG PROVIDED_TARGETS JPEG::JPEG MODULE_NAME gui QMAKE_LIB libjpeg) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/CMakeLists.txt index a20a4a084d..2af7904eb6 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/CMakeLists.txt +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/CMakeLists.txt @@ -23,6 +23,7 @@ qt_internal_add_module(EglFsKmsGbmSupportPrivate Qt::GuiPrivate Qt::KmsSupportPrivate gbm::gbm + Libdlmclient::Libdlmclient ) ##################################################################### ## QEglFSKmsGbmIntegrationPlugin Plugin: @@ -44,6 +45,7 @@ qt_internal_add_plugin(QEglFSKmsGbmIntegrationPlugin Qt::GuiPrivate Qt::KmsSupportPrivate gbm::gbm + Libdlmclient::Libdlmclient ) #### Keys ignored in scope 3:.:.:eglfs_kms-plugin.pro:: diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp index b5b7811b79..1e77c72ee5 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp @@ -56,32 +56,51 @@ Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) QEglFSKmsGbmDevice::QEglFSKmsGbmDevice(QKmsScreenConfig *screenConfig, const QString &path) : QEglFSKmsDevice(screenConfig, path) , m_gbm_device(nullptr) + , m_lease(nullptr) , m_globalCursor(nullptr) { } bool QEglFSKmsGbmDevice::open() { + QByteArray lease = qgetenv("QT_QPA_EGLFS_DRMLEASE"); + int drmfd = -1; Q_ASSERT(fd() == -1); Q_ASSERT(m_gbm_device == nullptr); - int fd = qt_safe_open(devicePath().toLocal8Bit().constData(), O_RDWR | O_CLOEXEC); - if (fd == -1) { - qErrnoWarning("Could not open DRM device %s", qPrintable(devicePath())); - return false; + if (lease.isEmpty()) { + drmfd = qt_safe_open(devicePath().toLocal8Bit().constData(), O_RDWR | O_CLOEXEC); + if (drmfd == -1) { + qErrnoWarning("Could not open DRM device %s", qPrintable(devicePath())); + return false; + } + } else { + QString lease_path(QString::fromUtf8(lease)); + + m_lease = ::dlm_get_lease(lease_path.toLocal8Bit().constData()); + if (m_lease == nullptr) { + qErrnoWarning("Could not open DRM lease %s", qPrintable(lease_path)); + return false; + } + drmfd = dlm_lease_fd(m_lease); } - qCDebug(qLcEglfsKmsDebug) << "Creating GBM device for file descriptor" << fd + qCDebug(qLcEglfsKmsDebug) << "Creating GBM device for file descriptor" << drmfd << "obtained from" << devicePath(); - m_gbm_device = gbm_create_device(fd); + m_gbm_device = gbm_create_device(drmfd); if (!m_gbm_device) { qErrnoWarning("Could not create GBM device"); - qt_safe_close(fd); - fd = -1; + if (m_lease) { + ::dlm_release_lease(m_lease); + m_lease = nullptr; + } else { + qt_safe_close(drmfd); + } + drmfd = -1; return false; } - setFd(fd); + setFd(drmfd); m_eventReader.create(this); @@ -99,7 +118,11 @@ void QEglFSKmsGbmDevice::close() m_gbm_device = nullptr; } - if (fd() != -1) { + if (m_lease) { + setFd(-1); + ::dlm_release_lease(m_lease); + m_lease = nullptr; + } else if (fd() != -1) { qt_safe_close(fd()); setFd(-1); } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h index bb67d800ee..b2d705800e 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h @@ -57,6 +57,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -92,6 +93,9 @@ private: gbm_device *m_gbm_device; + // only used for DRM lease + struct dlm_lease *m_lease; + QEglFSKmsGbmCursor *m_globalCursor; }; -- 2.25.1