summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/configure.json2
-rw-r--r--src/platformsupport/kmsconvenience/kmsconvenience.pro20
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice.cpp608
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice_p.h165
-rw-r--r--src/platformsupport/platformsupport.pro2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp36
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h11
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp24
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp15
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h4
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp23
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h14
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp21
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h7
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp14
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h4
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro6
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp429
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h60
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp121
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h30
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp52
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h33
-rw-r--r--sync.profile1
27 files changed, 952 insertions, 756 deletions
diff --git a/src/gui/configure.json b/src/gui/configure.json
index f4e2faf08b..f4f099cc23 100644
--- a/src/gui/configure.json
+++ b/src/gui/configure.json
@@ -505,7 +505,7 @@
"kms": {
"label": "KMS",
"condition": "libs.drm",
- "output": [ "publicQtConfig" ]
+ "output": [ "publicQtConfig", "privateFeature" ]
},
"libinput": {
"label": "libinput",
diff --git a/src/platformsupport/kmsconvenience/kmsconvenience.pro b/src/platformsupport/kmsconvenience/kmsconvenience.pro
new file mode 100644
index 0000000000..d0ff0d4efb
--- /dev/null
+++ b/src/platformsupport/kmsconvenience/kmsconvenience.pro
@@ -0,0 +1,20 @@
+TARGET = QtKmsSupport
+MODULE = kms_support
+
+QT = core-private gui-private
+CONFIG += static internal_module
+
+DEFINES += QT_NO_CAST_FROM_ASCII
+PRECOMPILED_HEADER = ../../corelib/global/qt_pch.h
+
+HEADERS +=
+ qkmsdevice_p.h
+
+SOURCES += \
+ qkmsdevice.cpp
+
+QMAKE_USE += drm
+
+LIBS_PRIVATE += $$QMAKE_LIBS_DYNLOAD
+
+load(qt_module)
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
new file mode 100644
index 0000000000..c265073214
--- /dev/null
+++ b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
@@ -0,0 +1,608 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Pelagicore AG
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** 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 "qkmsdevice_p.h"
+
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonObject>
+#include <QtCore/QJsonArray>
+#include <QtCore/QFile>
+#include <QtCore/QLoggingCategory>
+
+#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(qLcKmsDebug, "qt.qpa.eglfs.kms")
+
+enum OutputConfiguration {
+ OutputConfigOff,
+ OutputConfigPreferred,
+ OutputConfigCurrent,
+ OutputConfigMode,
+ OutputConfigModeline
+};
+
+int QKmsDevice::crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector)
+{
+ for (int i = 0; i < connector->count_encoders; i++) {
+ drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->encoders[i]);
+ if (!encoder) {
+ qWarning("Failed to get encoder");
+ continue;
+ }
+
+ quint32 possibleCrtcs = encoder->possible_crtcs;
+ drmModeFreeEncoder(encoder);
+
+ for (int j = 0; j < resources->count_crtcs; j++) {
+ bool isPossible = possibleCrtcs & (1 << j);
+ bool isAvailable = !(m_crtc_allocator & 1 << resources->crtcs[j]);
+
+ if (isPossible && isAvailable)
+ return j;
+ }
+ }
+
+ return -1;
+}
+
+static const char * const connector_type_names[] = { // must match DRM_MODE_CONNECTOR_*
+ "None",
+ "VGA",
+ "DVI",
+ "DVI",
+ "DVI",
+ "Composite",
+ "TV",
+ "LVDS",
+ "CTV",
+ "DIN",
+ "DP",
+ "HDMI",
+ "HDMI",
+ "TV",
+ "eDP",
+ "Virtual",
+ "DSI"
+};
+
+static QByteArray nameForConnector(const drmModeConnectorPtr connector)
+{
+ QByteArray connectorName("UNKNOWN");
+
+ if (connector->connector_type < ARRAY_LENGTH(connector_type_names))
+ connectorName = connector_type_names[connector->connector_type];
+
+ connectorName += QByteArray::number(connector->connector_type_id);
+
+ return connectorName;
+}
+
+static bool parseModeline(const QByteArray &text, drmModeModeInfoPtr mode)
+{
+ char hsync[16];
+ char vsync[16];
+ float fclock;
+
+ mode->type = DRM_MODE_TYPE_USERDEF;
+ mode->hskew = 0;
+ mode->vscan = 0;
+ mode->vrefresh = 0;
+ mode->flags = 0;
+
+ if (sscanf(text.constData(), "%f %hd %hd %hd %hd %hd %hd %hd %hd %15s %15s",
+ &fclock,
+ &mode->hdisplay,
+ &mode->hsync_start,
+ &mode->hsync_end,
+ &mode->htotal,
+ &mode->vdisplay,
+ &mode->vsync_start,
+ &mode->vsync_end,
+ &mode->vtotal, hsync, vsync) != 11)
+ return false;
+
+ mode->clock = fclock * 1000;
+
+ if (strcmp(hsync, "+hsync") == 0)
+ mode->flags |= DRM_MODE_FLAG_PHSYNC;
+ else if (strcmp(hsync, "-hsync") == 0)
+ mode->flags |= DRM_MODE_FLAG_NHSYNC;
+ else
+ return false;
+
+ if (strcmp(vsync, "+vsync") == 0)
+ mode->flags |= DRM_MODE_FLAG_PVSYNC;
+ else if (strcmp(vsync, "-vsync") == 0)
+ mode->flags |= DRM_MODE_FLAG_NVSYNC;
+ else
+ return false;
+
+ return true;
+}
+
+QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
+ drmModeConnectorPtr connector,
+ VirtualDesktopInfo *vinfo)
+{
+ const QByteArray connectorName = nameForConnector(connector);
+
+ const int crtc = crtcForConnector(resources, connector);
+ if (crtc < 0) {
+ qWarning() << "No usable crtc/encoder pair for connector" << connectorName;
+ return Q_NULLPTR;
+ }
+
+ OutputConfiguration configuration;
+ QSize configurationSize;
+ drmModeModeInfo configurationModeline;
+
+ auto userConfig = m_screenConfig->outputSettings();
+ auto userConnectorConfig = userConfig.value(QString::fromUtf8(connectorName));
+ // default to the preferred mode unless overridden in the config
+ const QByteArray mode = userConnectorConfig.value(QStringLiteral("mode"), QStringLiteral("preferred"))
+ .toByteArray().toLower();
+ if (mode == "off") {
+ configuration = OutputConfigOff;
+ } else if (mode == "preferred") {
+ configuration = OutputConfigPreferred;
+ } else if (mode == "current") {
+ configuration = OutputConfigCurrent;
+ } else if (sscanf(mode.constData(), "%dx%d", &configurationSize.rwidth(), &configurationSize.rheight()) == 2) {
+ configuration = OutputConfigMode;
+ } else if (parseModeline(mode, &configurationModeline)) {
+ configuration = OutputConfigModeline;
+ } else {
+ qWarning("Invalid mode \"%s\" for output %s", mode.constData(), connectorName.constData());
+ configuration = OutputConfigPreferred;
+ }
+ if (vinfo) {
+ *vinfo = VirtualDesktopInfo();
+ vinfo->virtualIndex = userConnectorConfig.value(QStringLiteral("virtualIndex"), INT_MAX).toInt();
+ if (userConnectorConfig.contains(QStringLiteral("virtualPos"))) {
+ const QByteArray vpos = userConnectorConfig.value(QStringLiteral("virtualPos")).toByteArray();
+ const QByteArrayList vposComp = vpos.split(',');
+ if (vposComp.count() == 2)
+ vinfo->virtualPos = QPoint(vposComp[0].trimmed().toInt(), vposComp[1].trimmed().toInt());
+ }
+ }
+
+ const uint32_t crtc_id = resources->crtcs[crtc];
+
+ if (configuration == OutputConfigOff) {
+ qCDebug(qLcKmsDebug) << "Turning off output" << connectorName;
+ drmModeSetCrtc(m_dri_fd, crtc_id, 0, 0, 0, 0, 0, Q_NULLPTR);
+ return Q_NULLPTR;
+ }
+
+ // Skip disconnected output
+ if (configuration == OutputConfigPreferred && connector->connection == DRM_MODE_DISCONNECTED) {
+ qCDebug(qLcKmsDebug) << "Skipping disconnected output" << connectorName;
+ return Q_NULLPTR;
+ }
+
+ // Get the current mode on the current crtc
+ drmModeModeInfo crtc_mode;
+ memset(&crtc_mode, 0, sizeof crtc_mode);
+ if (drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->connector_id)) {
+ drmModeCrtcPtr crtc = drmModeGetCrtc(m_dri_fd, encoder->crtc_id);
+ drmModeFreeEncoder(encoder);
+
+ if (!crtc)
+ return Q_NULLPTR;
+
+ if (crtc->mode_valid)
+ crtc_mode = crtc->mode;
+
+ drmModeFreeCrtc(crtc);
+ }
+
+ QList<drmModeModeInfo> modes;
+ modes.reserve(connector->count_modes);
+ qCDebug(qLcKmsDebug) << connectorName << "mode count:" << connector->count_modes;
+ for (int i = 0; i < connector->count_modes; i++) {
+ const drmModeModeInfo &mode = connector->modes[i];
+ qCDebug(qLcKmsDebug) << "mode" << i << mode.hdisplay << "x" << mode.vdisplay
+ << '@' << mode.vrefresh << "hz";
+ modes << connector->modes[i];
+ }
+
+ int preferred = -1;
+ int current = -1;
+ int configured = -1;
+ int best = -1;
+
+ for (int i = modes.size() - 1; i >= 0; i--) {
+ const drmModeModeInfo &m = modes.at(i);
+
+ if (configuration == OutputConfigMode &&
+ m.hdisplay == configurationSize.width() &&
+ m.vdisplay == configurationSize.height()) {
+ configured = i;
+ }
+
+ if (!memcmp(&crtc_mode, &m, sizeof m))
+ current = i;
+
+ if (m.type & DRM_MODE_TYPE_PREFERRED)
+ preferred = i;
+
+ best = i;
+ }
+
+ if (configuration == OutputConfigModeline) {
+ modes << configurationModeline;
+ configured = modes.size() - 1;
+ }
+
+ if (current < 0 && crtc_mode.clock != 0) {
+ modes << crtc_mode;
+ current = mode.size() - 1;
+ }
+
+ if (configuration == OutputConfigCurrent)
+ configured = current;
+
+ int selected_mode = -1;
+
+ if (configured >= 0)
+ selected_mode = configured;
+ else if (preferred >= 0)
+ selected_mode = preferred;
+ else if (current >= 0)
+ selected_mode = current;
+ else if (best >= 0)
+ selected_mode = best;
+
+ if (selected_mode < 0) {
+ qWarning() << "No modes available for output" << connectorName;
+ return Q_NULLPTR;
+ } else {
+ int width = modes[selected_mode].hdisplay;
+ int height = modes[selected_mode].vdisplay;
+ int refresh = modes[selected_mode].vrefresh;
+ qCDebug(qLcKmsDebug) << "Selected mode" << selected_mode << ":" << width << "x" << height
+ << '@' << refresh << "hz for output" << connectorName;
+ }
+
+ // physical size from connector < config values < env vars
+ static const int width = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_WIDTH");
+ static const int height = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_HEIGHT");
+ QSizeF physSize(width, height);
+ if (physSize.isEmpty()) {
+ physSize = QSize(userConnectorConfig.value(QStringLiteral("physicalWidth")).toInt(),
+ userConnectorConfig.value(QStringLiteral("physicalHeight")).toInt());
+ if (physSize.isEmpty()) {
+ physSize.setWidth(connector->mmWidth);
+ physSize.setHeight(connector->mmHeight);
+ }
+ }
+ qCDebug(qLcKmsDebug) << "Physical size is" << physSize << "mm" << "for output" << connectorName;
+
+ QKmsOutput output = {
+ QString::fromUtf8(connectorName),
+ connector->connector_id,
+ crtc_id,
+ physSize,
+ selected_mode,
+ false,
+ drmModeGetCrtc(m_dri_fd, crtc_id),
+ modes,
+ connector->subpixel,
+ connectorProperty(connector, QByteArrayLiteral("DPMS"))
+ };
+
+ m_crtc_allocator |= (1 << output.crtc_id);
+ m_connector_allocator |= (1 << output.connector_id);
+
+ return createScreen(output);
+}
+
+drmModePropertyPtr QKmsDevice::connectorProperty(drmModeConnectorPtr connector, const QByteArray &name)
+{
+ drmModePropertyPtr prop;
+
+ for (int i = 0; i < connector->count_props; i++) {
+ prop = drmModeGetProperty(m_dri_fd, connector->props[i]);
+ if (!prop)
+ continue;
+ if (strcmp(prop->name, name.constData()) == 0)
+ return prop;
+ drmModeFreeProperty(prop);
+ }
+
+ return Q_NULLPTR;
+}
+
+QKmsDevice::QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path)
+ : m_screenConfig(screenConfig)
+ , m_path(path)
+ , m_dri_fd(-1)
+ , m_crtc_allocator(0)
+ , m_connector_allocator(0)
+{
+ if (m_path.isEmpty()) {
+ m_path = m_screenConfig->devicePath();
+ qCDebug(qLcKmsDebug, "Using DRM device %s specified in config file", qPrintable(m_path));
+ if (m_path.isEmpty())
+ qFatal("No DRM device given");
+ } else {
+ qCDebug(qLcKmsDebug, "Using backend-provided DRM device %s", qPrintable(m_path));
+ }
+}
+
+QKmsDevice::~QKmsDevice()
+{
+}
+
+struct OrderedScreen
+{
+ OrderedScreen() : screen(nullptr) { }
+ OrderedScreen(QPlatformScreen *screen, const QKmsDevice::VirtualDesktopInfo &vinfo)
+ : screen(screen), vinfo(vinfo) { }
+ QPlatformScreen *screen;
+ QKmsDevice::VirtualDesktopInfo vinfo;
+};
+
+QDebug operator<<(QDebug dbg, const OrderedScreen &s)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "OrderedScreen(" << s.screen << " : " << s.vinfo.virtualIndex
+ << " / " << s.vinfo.virtualPos << ")";
+ return dbg;
+}
+
+static bool orderedScreenLessThan(const OrderedScreen &a, const OrderedScreen &b)
+{
+ return a.vinfo.virtualIndex < b.vinfo.virtualIndex;
+}
+
+void QKmsDevice::createScreens()
+{
+ drmModeResPtr resources = drmModeGetResources(m_dri_fd);
+ if (!resources) {
+ qWarning("drmModeGetResources failed");
+ return;
+ }
+
+ QVector<OrderedScreen> screens;
+
+ for (int i = 0; i < resources->count_connectors; i++) {
+ drmModeConnectorPtr connector = drmModeGetConnector(m_dri_fd, resources->connectors[i]);
+ if (!connector)
+ continue;
+
+ VirtualDesktopInfo vinfo;
+ QPlatformScreen *screen = createScreenForConnector(resources, connector, &vinfo);
+ if (screen)
+ screens.append(OrderedScreen(screen, vinfo));
+
+ drmModeFreeConnector(connector);
+ }
+
+ drmModeFreeResources(resources);
+
+ // Use stable sort to preserve the original order for outputs with unspecified indices.
+ std::stable_sort(screens.begin(), screens.end(), orderedScreenLessThan);
+ qCDebug(qLcKmsDebug) << "Sorted screen list:" << screens;
+
+ QPoint pos(0, 0);
+ QList<QPlatformScreen *> siblings;
+ QVector<QPoint> virtualPositions;
+
+ for (const OrderedScreen &orderedScreen : screens) {
+ QPlatformScreen *s = orderedScreen.screen;
+ QPoint virtualPos(0, 0);
+ // set up a horizontal or vertical virtual desktop
+ if (orderedScreen.vinfo.virtualPos.isNull()) {
+ virtualPos = pos;
+ if (m_screenConfig->virtualDesktopLayout() == QKmsScreenConfig::VirtualDesktopLayoutVertical)
+ pos.ry() += s->geometry().height();
+ else
+ pos.rx() += s->geometry().width();
+ } else {
+ virtualPos = orderedScreen.vinfo.virtualPos;
+ }
+ qCDebug(qLcKmsDebug) << "Adding screen" << s << "to QPA with geometry" << s->geometry();
+ // The order in qguiapp's screens list will match the order set by
+ // virtualIndex. This is not only handy but also required since for instance
+ // evdevtouch relies on it when performing touch device - screen mapping.
+ if (!m_screenConfig->separateScreens()) {
+ siblings.append(s);
+ virtualPositions.append(virtualPos);
+ } else {
+ registerScreen(s, virtualPos, QList<QPlatformScreen *>() << s);
+ }
+ }
+
+ if (!m_screenConfig->separateScreens()) {
+ // enable the virtual desktop
+ for (int i = 0; i < siblings.count(); ++i)
+ registerScreen(siblings[i], virtualPositions[i], siblings);
+ }
+}
+
+int QKmsDevice::fd() const
+{
+ return m_dri_fd;
+}
+
+QString QKmsDevice::devicePath() const
+{
+ return m_path;
+}
+
+void QKmsDevice::setFd(int fd)
+{
+ m_dri_fd = fd;
+}
+
+QKmsScreenConfig *QKmsDevice::screenConfig() const
+{
+ return m_screenConfig;
+}
+
+QKmsScreenConfig::QKmsScreenConfig()
+ : m_hwCursor(true)
+ , m_separateScreens(false)
+ , m_pbuffers(false)
+ , m_virtualDesktopLayout(VirtualDesktopLayoutHorizontal)
+{
+ loadConfig();
+}
+
+void QKmsScreenConfig::loadConfig()
+{
+ static QByteArray json = qgetenv("QT_QPA_EGLFS_KMS_CONFIG");
+ if (json.isEmpty())
+ return;
+
+ qCDebug(qLcKmsDebug) << "Loading KMS setup from" << json;
+
+ QFile file(QString::fromUtf8(json));
+ if (!file.open(QFile::ReadOnly)) {
+ qCWarning(qLcKmsDebug) << "Could not open config file"
+ << json << "for reading";
+ return;
+ }
+
+ const QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
+ if (!doc.isObject()) {
+ qCWarning(qLcKmsDebug) << "Invalid config file" << json
+ << "- no top-level JSON object";
+ return;
+ }
+
+ const QJsonObject object = doc.object();
+
+ m_hwCursor = object.value(QLatin1String("hwcursor")).toBool(m_hwCursor);
+ m_pbuffers = object.value(QLatin1String("pbuffers")).toBool(m_pbuffers);
+ m_devicePath = object.value(QLatin1String("device")).toString();
+ m_separateScreens = object.value(QLatin1String("separateScreens")).toBool(m_separateScreens);
+
+ const QString vdOriString = object.value(QLatin1String("virtualDesktopLayout")).toString();
+ if (!vdOriString.isEmpty()) {
+ if (vdOriString == QLatin1String("horizontal"))
+ m_virtualDesktopLayout = VirtualDesktopLayoutHorizontal;
+ else if (vdOriString == QLatin1String("vertical"))
+ m_virtualDesktopLayout = VirtualDesktopLayoutVertical;
+ else
+ qCWarning(qLcKmsDebug) << "Unknown virtualDesktopOrientation value" << vdOriString;
+ }
+
+ const QJsonArray outputs = object.value(QLatin1String("outputs")).toArray();
+ for (int i = 0; i < outputs.size(); i++) {
+ const QVariantMap outputSettings = outputs.at(i).toObject().toVariantMap();
+
+ if (outputSettings.contains(QStringLiteral("name"))) {
+ const QString name = outputSettings.value(QStringLiteral("name")).toString();
+
+ if (m_outputSettings.contains(name)) {
+ qCDebug(qLcKmsDebug) << "Output" << name << "configured multiple times!";
+ }
+
+ m_outputSettings.insert(name, outputSettings);
+ }
+ }
+
+ qCDebug(qLcKmsDebug) << "Requested configuration (some settings may be ignored):\n"
+ << "\thwcursor:" << m_hwCursor << "\n"
+ << "\tpbuffers:" << m_pbuffers << "\n"
+ << "\tseparateScreens:" << m_separateScreens << "\n"
+ << "\tvirtualDesktopLayout:" << m_virtualDesktopLayout << "\n"
+ << "\toutputs:" << m_outputSettings;
+}
+
+void QKmsOutput::restoreMode(QKmsDevice *device)
+{
+ if (mode_set && saved_crtc) {
+ drmModeSetCrtc(device->fd(),
+ saved_crtc->crtc_id,
+ saved_crtc->buffer_id,
+ 0, 0,
+ &connector_id, 1,
+ &saved_crtc->mode);
+ mode_set = false;
+ }
+}
+
+void QKmsOutput::cleanup(QKmsDevice *device)
+{
+ if (dpms_prop) {
+ drmModeFreeProperty(dpms_prop);
+ dpms_prop = nullptr;
+ }
+
+ restoreMode(device);
+
+ if (saved_crtc) {
+ drmModeFreeCrtc(saved_crtc);
+ saved_crtc = nullptr;
+ }
+}
+
+QPlatformScreen::SubpixelAntialiasingType QKmsOutput::subpixelAntialiasingTypeHint() const
+{
+ switch (subpixel) {
+ default:
+ case DRM_MODE_SUBPIXEL_UNKNOWN:
+ case DRM_MODE_SUBPIXEL_NONE:
+ return QPlatformScreen::Subpixel_None;
+ case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
+ return QPlatformScreen::Subpixel_RGB;
+ case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
+ return QPlatformScreen::Subpixel_BGR;
+ case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
+ return QPlatformScreen::Subpixel_VRGB;
+ case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
+ return QPlatformScreen::Subpixel_VBGR;
+ }
+}
+
+void QKmsOutput::setPowerState(QKmsDevice *device, QPlatformScreen::PowerState state)
+{
+ if (dpms_prop)
+ drmModeConnectorSetProperty(device->fd(), connector_id,
+ dpms_prop->prop_id, (int) state);
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice_p.h b/src/platformsupport/kmsconvenience/qkmsdevice_p.h
new file mode 100644
index 0000000000..36aba49ff2
--- /dev/null
+++ b/src/platformsupport/kmsconvenience/qkmsdevice_p.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Pelagicore AG
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** 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$
+**
+****************************************************************************/
+
+#ifndef QKMSDEVICE_P_H
+#define QKMSDEVICE_P_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 <qpa/qplatformscreen.h>
+#include <QtCore/QMap>
+#include <QtCore/QVariant>
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+QT_BEGIN_NAMESPACE
+
+class QKmsDevice;
+
+class QKmsScreenConfig
+{
+public:
+ enum VirtualDesktopLayout {
+ VirtualDesktopLayoutHorizontal,
+ VirtualDesktopLayoutVertical
+ };
+
+ QKmsScreenConfig();
+
+ QString devicePath() const { return m_devicePath; }
+
+ bool hwCursor() const { return m_hwCursor; }
+ bool separateScreens() const { return m_separateScreens; }
+ bool supportsPBuffers() const { return m_pbuffers; }
+ VirtualDesktopLayout virtualDesktopLayout() const { return m_virtualDesktopLayout; }
+
+ QMap<QString, QVariantMap> outputSettings() const { return m_outputSettings; }
+
+private:
+ void loadConfig();
+
+ QString m_devicePath;
+ bool m_hwCursor;
+ bool m_separateScreens;
+ bool m_pbuffers;
+ VirtualDesktopLayout m_virtualDesktopLayout;
+ QMap<QString, QVariantMap> m_outputSettings;
+};
+
+struct QKmsOutput
+{
+ QString name;
+ uint32_t connector_id;
+ uint32_t crtc_id;
+ QSizeF physical_size;
+ int mode; // index of selected mode in list below
+ bool mode_set;
+ drmModeCrtcPtr saved_crtc;
+ QList<drmModeModeInfo> modes;
+ int subpixel;
+ drmModePropertyPtr dpms_prop;
+
+ void restoreMode(QKmsDevice *device);
+ void cleanup(QKmsDevice *device);
+ QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const;
+ void setPowerState(QKmsDevice *device, QPlatformScreen::PowerState state);
+};
+
+class QKmsDevice
+{
+public:
+ struct VirtualDesktopInfo {
+ VirtualDesktopInfo() : virtualIndex(0) { }
+ int virtualIndex;
+ QPoint virtualPos;
+ };
+
+ QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path = QString());
+ virtual ~QKmsDevice();
+
+ virtual bool open() = 0;
+ virtual void close() = 0;
+ virtual void *nativeDisplay() const = 0;
+
+ void createScreens();
+
+ int fd() const;
+ QString devicePath() const;
+
+ QKmsScreenConfig *screenConfig() const;
+
+protected:
+ virtual QPlatformScreen *createScreen(const QKmsOutput &output) = 0;
+ virtual void registerScreen(QPlatformScreen *screen,
+ const QPoint &virtualPos,
+ const QList<QPlatformScreen *> &virtualSiblings) = 0;
+
+ void setFd(int fd);
+ int crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector);
+ QPlatformScreen *createScreenForConnector(drmModeResPtr resources,
+ drmModeConnectorPtr connector,
+ VirtualDesktopInfo *vinfo);
+ drmModePropertyPtr connectorProperty(drmModeConnectorPtr connector, const QByteArray &name);
+
+ QKmsScreenConfig *m_screenConfig;
+ QString m_path;
+ int m_dri_fd;
+
+ quint32 m_crtc_allocator;
+ quint32 m_connector_allocator;
+
+private:
+ Q_DISABLE_COPY(QKmsDevice)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro
index b83038dbf9..7a97a12bae 100644
--- a/src/platformsupport/platformsupport.pro
+++ b/src/platformsupport/platformsupport.pro
@@ -24,6 +24,8 @@ qtConfig(egl): \
SUBDIRS += eglconvenience
qtConfig(xlib):qtConfig(opengl):!qtConfig(opengles2): \
SUBDIRS += glxconvenience
+qtConfig(kms): \
+ SUBDIRS += kmsconvenience
qtConfig(accessibility) {
SUBDIRS += accessibility
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
index 255db824b7..e522c0ee1b 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
@@ -4,7 +4,7 @@ PLUGIN_TYPE = egldeviceintegrations
PLUGIN_CLASS_NAME = QEglFSKmsGbmIntegrationPlugin
load(qt_plugin)
-QT += core-private gui-private eglfsdeviceintegration-private eglfs_kms_support-private
+QT += core-private gui-private eglfsdeviceintegration-private eglfs_kms_support-private kms_support-private
INCLUDEPATH += $$PWD/../../api $$PWD/../eglfs_kms_support
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
index 3a220ec942..2040d6bc0e 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
@@ -46,7 +46,6 @@
#include <QtCore/QLoggingCategory>
#include <QtCore/private/qcore_unix_p.h>
-#include <QtGui/private/qguiapplication_p.h>
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
@@ -65,8 +64,8 @@ void QEglFSKmsGbmDevice::pageFlipHandler(int fd, unsigned int sequence, unsigned
screen->flipFinished();
}
-QEglFSKmsGbmDevice::QEglFSKmsGbmDevice(QEglFSKmsIntegration *integration, const QString &path)
- : QEglFSKmsDevice(integration, path)
+QEglFSKmsGbmDevice::QEglFSKmsGbmDevice(QKmsScreenConfig *screenConfig, const QString &path)
+ : QEglFSKmsDevice(screenConfig, path)
, m_gbm_device(Q_NULLPTR)
, m_globalCursor(Q_NULLPTR)
{
@@ -77,7 +76,6 @@ bool QEglFSKmsGbmDevice::open()
Q_ASSERT(fd() == -1);
Q_ASSERT(m_gbm_device == Q_NULLPTR);
- qCDebug(qLcEglfsKmsDebug) << "Opening device" << devicePath();
int fd = qt_safe_open(devicePath().toLocal8Bit().constData(), O_RDWR | O_CLOEXEC);
if (fd == -1) {
qErrnoWarning("Could not open DRM device %s", qPrintable(devicePath()));
@@ -101,6 +99,8 @@ bool QEglFSKmsGbmDevice::open()
void QEglFSKmsGbmDevice::close()
{
+ // Note: screens are gone at this stage.
+
if (m_gbm_device) {
gbm_device_destroy(m_gbm_device);
m_gbm_device = Q_NULLPTR;
@@ -110,15 +110,11 @@ void QEglFSKmsGbmDevice::close()
qt_safe_close(fd());
setFd(-1);
}
-
- if (m_globalCursor)
- m_globalCursor->deleteLater();
- m_globalCursor = Q_NULLPTR;
}
-EGLNativeDisplayType QEglFSKmsGbmDevice::nativeDisplay() const
+void *QEglFSKmsGbmDevice::nativeDisplay() const
{
- return reinterpret_cast<EGLNativeDisplayType>(m_gbm_device);
+ return m_gbm_device;
}
gbm_device * QEglFSKmsGbmDevice::gbmDevice() const
@@ -131,6 +127,17 @@ QPlatformCursor *QEglFSKmsGbmDevice::globalCursor() const
return m_globalCursor;
}
+// Cannot do this from close(), it may be too late.
+// Call this from the last screen dtor instead.
+void QEglFSKmsGbmDevice::destroyGlobalCursor()
+{
+ if (m_globalCursor) {
+ qCDebug(qLcEglfsKmsDebug, "Destroying global GBM mouse cursor");
+ delete m_globalCursor;
+ m_globalCursor = Q_NULLPTR;
+ }
+}
+
void QEglFSKmsGbmDevice::handleDrmEvent()
{
drmEventContext drmEvent = {
@@ -142,14 +149,13 @@ void QEglFSKmsGbmDevice::handleDrmEvent()
drmHandleEvent(fd(), &drmEvent);
}
-QEglFSKmsScreen *QEglFSKmsGbmDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output)
+QPlatformScreen *QEglFSKmsGbmDevice::createScreen(const QKmsOutput &output)
{
- static bool firstScreen = true;
- QEglFSKmsGbmScreen *screen = new QEglFSKmsGbmScreen(integration, device, output);
+ QEglFSKmsGbmScreen *screen = new QEglFSKmsGbmScreen(this, output);
- if (firstScreen && integration->hwCursor()) {
+ if (!m_globalCursor && screenConfig()->hwCursor()) {
+ qCDebug(qLcEglfsKmsDebug, "Creating new global GBM mouse cursor");
m_globalCursor = new QEglFSKmsGbmCursor(screen);
- firstScreen = false;
}
return screen;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h
index 7c0af84422..25284c6468 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h
@@ -43,7 +43,7 @@
#define QEGLFSKMSGBMDEVICE_H
#include "qeglfskmsgbmcursor.h"
-#include "qeglfskmsdevice.h"
+#include <qeglfskmsdevice.h>
#include <gbm.h>
@@ -54,21 +54,20 @@ class QEglFSKmsScreen;
class QEglFSKmsGbmDevice: public QEglFSKmsDevice
{
public:
- QEglFSKmsGbmDevice(QEglFSKmsIntegration *integration, const QString &path);
+ QEglFSKmsGbmDevice(QKmsScreenConfig *screenConfig, const QString &path);
bool open() Q_DECL_OVERRIDE;
void close() Q_DECL_OVERRIDE;
- EGLNativeDisplayType nativeDisplay() const Q_DECL_OVERRIDE;
+ void *nativeDisplay() const Q_DECL_OVERRIDE;
gbm_device *gbmDevice() const;
QPlatformCursor *globalCursor() const;
+ void destroyGlobalCursor();
void handleDrmEvent();
- virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration,
- QEglFSKmsDevice *device,
- QEglFSKmsOutput output) Q_DECL_OVERRIDE;
+ QPlatformScreen *createScreen(const QKmsOutput &output) Q_DECL_OVERRIDE;
private:
Q_DISABLE_COPY(QEglFSKmsGbmDevice)
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
index 38419a55c8..16767114ab 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
@@ -63,8 +63,9 @@ QT_BEGIN_NAMESPACE
QMutex QEglFSKmsGbmScreen::m_waitForFlipMutex;
QEglFSKmsGbmIntegration::QEglFSKmsGbmIntegration()
- : QEglFSKmsIntegration()
-{}
+{
+ qCDebug(qLcEglfsKmsDebug, "New DRM/KMS via GBM integration created");
+}
EGLNativeWindowType QEglFSKmsGbmIntegration::createNativeWindow(QPlatformWindow *platformWindow,
const QSize &size,
@@ -104,10 +105,12 @@ void QEglFSKmsGbmIntegration::destroyNativeWindow(EGLNativeWindowType window)
QPlatformCursor *QEglFSKmsGbmIntegration::createCursor(QPlatformScreen *screen) const
{
- if (hwCursor())
- return Q_NULLPTR;
- else
+ if (screenConfig()->hwCursor()) {
+ return nullptr;
+ } else {
+ qCDebug(qLcEglfsKmsDebug, "Using plain OpenGL mouse cursor");
return new QEglFSCursor(screen);
+ }
}
void QEglFSKmsGbmIntegration::presentBuffer(QPlatformSurface *surface)
@@ -118,13 +121,12 @@ void QEglFSKmsGbmIntegration::presentBuffer(QPlatformSurface *surface)
screen->flip();
}
-QEglFSKmsDevice *QEglFSKmsGbmIntegration::createDevice(const QString &devicePath)
+QKmsDevice *QEglFSKmsGbmIntegration::createDevice()
{
- QString path = devicePath;
- if (!devicePath.isEmpty()) {
- qCDebug(qLcEglfsKmsDebug) << "Using DRM device" << path << "specified in config file";
+ QString path = screenConfig()->devicePath();
+ if (!path.isEmpty()) {
+ qCDebug(qLcEglfsKmsDebug) << "GBM: Using DRM device" << path << "specified in config file";
} else {
-
QDeviceDiscovery *d = QDeviceDiscovery::create(QDeviceDiscovery::Device_VideoMask);
const QStringList devices = d->scanConnectedDevices();
qCDebug(qLcEglfsKmsDebug) << "Found the following video devices:" << devices;
@@ -137,7 +139,7 @@ QEglFSKmsDevice *QEglFSKmsGbmIntegration::createDevice(const QString &devicePath
qCDebug(qLcEglfsKmsDebug) << "Using" << path;
}
- return new QEglFSKmsGbmDevice(this, path);
+ return new QEglFSKmsGbmDevice(screenConfig(), path);
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h
index 727571d3e3..fa2e494a89 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h
@@ -65,7 +65,7 @@ public:
void presentBuffer(QPlatformSurface *surface) Q_DECL_OVERRIDE;
protected:
- QEglFSKmsDevice *createDevice(const QString &devicePath) Q_DECL_OVERRIDE;
+ QKmsDevice *createDevice() Q_DECL_OVERRIDE;
private:
};
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
index bed775ff81..ebce0a4776 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
@@ -92,10 +92,8 @@ QEglFSKmsGbmScreen::FrameBuffer *QEglFSKmsGbmScreen::framebufferForBufferObject(
return fb.take();
}
-QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QEglFSKmsIntegration *integration,
- QEglFSKmsDevice *device,
- QEglFSKmsOutput output)
- : QEglFSKmsScreen(integration, device, output)
+QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output)
+ : QEglFSKmsScreen(device, output)
, m_gbm_surface(Q_NULLPTR)
, m_gbm_bo_current(Q_NULLPTR)
, m_gbm_bo_next(Q_NULLPTR)
@@ -105,12 +103,17 @@ QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QEglFSKmsIntegration *integration,
QEglFSKmsGbmScreen::~QEglFSKmsGbmScreen()
{
+ const int remainingScreenCount = qGuiApp->screens().count();
+ qCDebug(qLcEglfsKmsDebug, "Screen dtor. Remaining screens: %d", remainingScreenCount);
+ if (!remainingScreenCount && !device()->screenConfig()->separateScreens())
+ static_cast<QEglFSKmsGbmDevice *>(device())->destroyGlobalCursor();
}
QPlatformCursor *QEglFSKmsGbmScreen::cursor() const
{
- if (integration()->hwCursor()) {
- if (!integration()->separateScreens())
+ QKmsScreenConfig *config = device()->screenConfig();
+ if (config->hwCursor()) {
+ if (!config->separateScreens())
return static_cast<QEglFSKmsGbmDevice *>(device())->globalCursor();
if (m_cursor.isNull()) {
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h
index d7ad348291..ffc96955d4 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h
@@ -54,9 +54,7 @@ class QEglFSKmsGbmCursor;
class QEglFSKmsGbmScreen : public QEglFSKmsScreen
{
public:
- QEglFSKmsGbmScreen(QEglFSKmsIntegration *integration,
- QEglFSKmsDevice *device,
- QEglFSKmsOutput output);
+ QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output);
~QEglFSKmsGbmScreen();
QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro
index a625021aba..a2dc9c4a50 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro
@@ -1,6 +1,6 @@
TARGET = qeglfs-kms-egldevice-integration
-QT += core-private gui-private eglfsdeviceintegration-private eglfs_kms_support-private
+QT += core-private gui-private eglfsdeviceintegration-private eglfs_kms_support-private kms_support-private
INCLUDEPATH += $$PWD/../../api $$PWD/../eglfs_kms_support
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp
index 60989e2bd0..f0bf59466e 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp
@@ -40,14 +40,16 @@
#include "qeglfskmsegldevice.h"
#include "qeglfskmsegldevicescreen.h"
#include "qeglfskmsegldeviceintegration.h"
+#include "private/qeglfsintegration_p.h"
#include "private/qeglfscursor_p.h"
#include <QtCore/private/qcore_unix_p.h>
QT_BEGIN_NAMESPACE
-QEglFSKmsEglDevice::QEglFSKmsEglDevice(QEglFSKmsIntegration *integration, const QString &path)
- : QEglFSKmsDevice(integration, path),
+QEglFSKmsEglDevice::QEglFSKmsEglDevice(QEglFSKmsEglDeviceIntegration *devInt, QKmsScreenConfig *screenConfig, const QString &path)
+ : QEglFSKmsDevice(screenConfig, path),
+ m_devInt(devInt),
m_globalCursor(nullptr)
{
}
@@ -56,11 +58,9 @@ bool QEglFSKmsEglDevice::open()
{
Q_ASSERT(fd() == -1);
- qCDebug(qLcEglfsKmsDebug, "Opening DRM device %s", qPrintable(devicePath()));
-
int fd = drmOpen(devicePath().toLocal8Bit().constData(), Q_NULLPTR);
if (Q_UNLIKELY(fd < 0))
- qFatal("Could not open DRM device");
+ qFatal("Could not open DRM (NV) device");
setFd(fd);
@@ -69,25 +69,24 @@ bool QEglFSKmsEglDevice::open()
void QEglFSKmsEglDevice::close()
{
- qCDebug(qLcEglfsKmsDebug, "Closing DRM device");
+ // Note: screens are gone at this stage.
if (qt_safe_close(fd()) == -1)
- qErrnoWarning("Could not close DRM device");
+ qErrnoWarning("Could not close DRM (NV) device");
setFd(-1);
}
EGLNativeDisplayType QEglFSKmsEglDevice::nativeDisplay() const
{
- return reinterpret_cast<EGLNativeDisplayType>(static_cast<QEglFSKmsEglDeviceIntegration *>(m_integration)->eglDevice());
+ return reinterpret_cast<EGLNativeDisplayType>(m_devInt->eglDevice());
}
-QEglFSKmsScreen *QEglFSKmsEglDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device,
- QEglFSKmsOutput output)
+QPlatformScreen *QEglFSKmsEglDevice::createScreen(const QKmsOutput &output)
{
- QEglFSKmsScreen *screen = new QEglFSKmsEglDeviceScreen(integration, device, output);
+ QEglFSKmsScreen *screen = new QEglFSKmsEglDeviceScreen(this, output);
- if (!m_globalCursor && !integration->separateScreens()) {
+ if (!m_globalCursor && !screenConfig()->separateScreens()) {
qCDebug(qLcEglfsKmsDebug, "Creating new global mouse cursor");
m_globalCursor = new QEglFSCursor(screen);
}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h
index 8c8f79f70c..b9304b8502 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h
@@ -45,25 +45,25 @@
QT_BEGIN_NAMESPACE
class QPlatformCursor;
+class QEglFSKmsEglDeviceIntegration;
class QEglFSKmsEglDevice: public QEglFSKmsDevice
{
public:
- QEglFSKmsEglDevice(QEglFSKmsIntegration *integration, const QString &path);
+ QEglFSKmsEglDevice(QEglFSKmsEglDeviceIntegration *devInt, QKmsScreenConfig *screenConfig, const QString &path);
- virtual bool open() Q_DECL_OVERRIDE;
- virtual void close() Q_DECL_OVERRIDE;
+ bool open() Q_DECL_OVERRIDE;
+ void close() Q_DECL_OVERRIDE;
- virtual EGLNativeDisplayType nativeDisplay() const Q_DECL_OVERRIDE;
+ void *nativeDisplay() const Q_DECL_OVERRIDE;
- virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration,
- QEglFSKmsDevice *device,
- QEglFSKmsOutput output) Q_DECL_OVERRIDE;
+ QPlatformScreen *createScreen(const QKmsOutput &output) Q_DECL_OVERRIDE;
QPlatformCursor *globalCursor() { return m_globalCursor; }
void destroyGlobalCursor();
private:
+ QEglFSKmsEglDeviceIntegration *m_devInt;
QPlatformCursor *m_globalCursor;
};
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
index d0c9c9565e..36fbfbd05c 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
@@ -50,8 +50,7 @@
QT_BEGIN_NAMESPACE
QEglFSKmsEglDeviceIntegration::QEglFSKmsEglDeviceIntegration()
- : QEglFSKmsIntegration()
- , m_egl_device(EGL_NO_DEVICE_EXT)
+ : m_egl_device(EGL_NO_DEVICE_EXT)
, m_funcs(Q_NULLPTR)
{
qCDebug(qLcEglfsKmsDebug, "New DRM/KMS on EGLDevice integration created");
@@ -101,10 +100,10 @@ bool QEglFSKmsEglDeviceIntegration::supportsPBuffers() const
return true;
}
-class QEglJetsonTK1Window : public QEglFSWindow
+class QEglFSKmsEglDeviceWindow : public QEglFSWindow
{
public:
- QEglJetsonTK1Window(QWindow *w, const QEglFSKmsEglDeviceIntegration *integration)
+ QEglFSKmsEglDeviceWindow(QWindow *w, const QEglFSKmsEglDeviceIntegration *integration)
: QEglFSWindow(w)
, m_integration(integration)
, m_egl_stream(EGL_NO_STREAM_KHR)
@@ -118,13 +117,13 @@ public:
EGLint m_latency;
};
-void QEglJetsonTK1Window::invalidateSurface()
+void QEglFSKmsEglDeviceWindow::invalidateSurface()
{
QEglFSWindow::invalidateSurface();
m_integration->m_funcs->destroy_stream(screen()->display(), m_egl_stream);
}
-void QEglJetsonTK1Window::resetSurface()
+void QEglFSKmsEglDeviceWindow::resetSurface()
{
qCDebug(qLcEglfsKmsDebug, "Creating stream");
@@ -213,7 +212,7 @@ void QEglJetsonTK1Window::resetSurface()
QEglFSWindow *QEglFSKmsEglDeviceIntegration::createWindow(QWindow *window) const
{
- QEglJetsonTK1Window *eglWindow = new QEglJetsonTK1Window(window, this);
+ QEglFSKmsEglDeviceWindow *eglWindow = new QEglFSKmsEglDeviceWindow(window, this);
m_funcs->initialize(eglWindow->screen()->display());
if (Q_UNLIKELY(!(m_funcs->has_egl_output_base && m_funcs->has_egl_output_drm && m_funcs->has_egl_stream &&
@@ -223,10 +222,8 @@ QEglFSWindow *QEglFSKmsEglDeviceIntegration::createWindow(QWindow *window) const
return eglWindow;
}
-QEglFSKmsDevice *QEglFSKmsEglDeviceIntegration::createDevice(const QString &devicePath)
+QKmsDevice *QEglFSKmsEglDeviceIntegration::createDevice()
{
- Q_UNUSED(devicePath)
-
if (Q_UNLIKELY(!query_egl_device()))
qFatal("Could not set up EGL device!");
@@ -234,7 +231,7 @@ QEglFSKmsDevice *QEglFSKmsEglDeviceIntegration::createDevice(const QString &devi
if (Q_UNLIKELY(!deviceName))
qFatal("Failed to query device name from EGLDevice");
- return new QEglFSKmsEglDevice(this, deviceName);
+ return new QEglFSKmsEglDevice(this, screenConfig(), deviceName);
}
bool QEglFSKmsEglDeviceIntegration::query_egl_device()
@@ -261,7 +258,7 @@ bool QEglFSKmsEglDeviceIntegration::query_egl_device()
QPlatformCursor *QEglFSKmsEglDeviceIntegration::createCursor(QPlatformScreen *screen) const
{
- return separateScreens() ? new QEglFSCursor(screen) : nullptr;
+ return screenConfig()->separateScreens() ? new QEglFSCursor(screen) : nullptr;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h
index cddfdbd5c6..a274474433 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h
@@ -64,7 +64,7 @@ public:
EGLDeviceEXT eglDevice() const { return m_egl_device; }
protected:
- QEglFSKmsDevice *createDevice(const QString &devicePath) Q_DECL_OVERRIDE;
+ QKmsDevice *createDevice() Q_DECL_OVERRIDE;
QPlatformCursor *createCursor(QPlatformScreen *screen) const Q_DECL_OVERRIDE;
private:
@@ -72,10 +72,9 @@ private:
bool query_egl_device();
EGLDeviceEXT m_egl_device;
-
- friend class QEglJetsonTK1Window;
- // EGLStream infrastructure
QEGLStreamConvenience *m_funcs;
+
+ friend class QEglFSKmsEglDeviceWindow;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp
index 1f672afeb4..532ec0b440 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp
@@ -40,11 +40,14 @@
#include "qeglfskmsegldevicescreen.h"
#include "qeglfskmsegldevice.h"
#include <QGuiApplication>
+#include <QLoggingCategory>
QT_BEGIN_NAMESPACE
-QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output)
- : QEglFSKmsScreen(integration, device, output)
+Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
+
+QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QKmsDevice *device, const QKmsOutput &output)
+ : QEglFSKmsScreen(device, output)
{
}
@@ -52,7 +55,7 @@ QEglFSKmsEglDeviceScreen::~QEglFSKmsEglDeviceScreen()
{
const int remainingScreenCount = qGuiApp->screens().count();
qCDebug(qLcEglfsKmsDebug, "Screen dtor. Remaining screens: %d", remainingScreenCount);
- if (!remainingScreenCount && !m_integration->separateScreens())
+ if (!remainingScreenCount && !device()->screenConfig()->separateScreens())
static_cast<QEglFSKmsEglDevice *>(device())->destroyGlobalCursor();
}
@@ -62,7 +65,10 @@ QPlatformCursor *QEglFSKmsEglDeviceScreen::cursor() const
// in its ctor. With separateScreens just use that. Otherwise
// there's a virtual desktop and the device has a global cursor
// and the base class has no dedicated cursor at all.
- return m_integration->separateScreens() ? QEglFSScreen::cursor() : static_cast<QEglFSKmsEglDevice *>(device())->globalCursor();
+ // config->hwCursor() is ignored for now, just use the standard OpenGL cursor.
+ return device()->screenConfig()->separateScreens()
+ ? QEglFSScreen::cursor()
+ : static_cast<QEglFSKmsEglDevice *>(device())->globalCursor();
}
void QEglFSKmsEglDeviceScreen::waitForFlip()
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h
index c57f52c6b7..1655a3f038 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h
@@ -47,9 +47,7 @@ QT_BEGIN_NAMESPACE
class QEglFSKmsEglDeviceScreen : public QEglFSKmsScreen
{
public:
- QEglFSKmsEglDeviceScreen(QEglFSKmsIntegration *integration,
- QEglFSKmsDevice *device,
- QEglFSKmsOutput output);
+ QEglFSKmsEglDeviceScreen(QKmsDevice *device, const QKmsOutput &output);
~QEglFSKmsEglDeviceScreen();
QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro
index 487edb569e..3c0a0ce30f 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro
@@ -2,7 +2,7 @@ TARGET = QtEglFsKmsSupport
CONFIG += no_module_headers internal_module
load(qt_module)
-QT += core-private gui-private eglfsdeviceintegration-private
+QT += core-private gui-private eglfsdeviceintegration-private kms_support-private
INCLUDEPATH += $$PWD/../../api
@@ -15,8 +15,8 @@ QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
SOURCES += $$PWD/qeglfskmsintegration.cpp \
$$PWD/qeglfskmsdevice.cpp \
- $$PWD/qeglfskmsscreen.cpp \
+ $$PWD/qeglfskmsscreen.cpp
HEADERS += $$PWD/qeglfskmsintegration.h \
$$PWD/qeglfskmsdevice.h \
- $$PWD/qeglfskmsscreen.h \
+ $$PWD/qeglfskmsscreen.h
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp
index f6b58d1ba6..e99a6957a8 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp
@@ -1,6 +1,5 @@
/****************************************************************************
**
-** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2016 Pelagicore AG
** Contact: https://www.qt.io/licensing/
@@ -41,432 +40,24 @@
#include "qeglfskmsdevice.h"
#include "qeglfskmsscreen.h"
-
-#include "qeglfsintegration_p.h"
-
-#include <QtCore/QLoggingCategory>
-#include <QtCore/private/qcore_unix_p.h>
+#include "private/qeglfsintegration_p.h"
#include <QtGui/private/qguiapplication_p.h>
-#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
-
QT_BEGIN_NAMESPACE
-Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
-
-enum OutputConfiguration {
- OutputConfigOff,
- OutputConfigPreferred,
- OutputConfigCurrent,
- OutputConfigMode,
- OutputConfigModeline
-};
-
-int QEglFSKmsDevice::crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector)
-{
- for (int i = 0; i < connector->count_encoders; i++) {
- drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->encoders[i]);
- if (!encoder) {
- qWarning("Failed to get encoder");
- continue;
- }
-
- quint32 possibleCrtcs = encoder->possible_crtcs;
- drmModeFreeEncoder(encoder);
-
- for (int j = 0; j < resources->count_crtcs; j++) {
- bool isPossible = possibleCrtcs & (1 << j);
- bool isAvailable = !(m_crtc_allocator & 1 << resources->crtcs[j]);
-
- if (isPossible && isAvailable)
- return j;
- }
- }
-
- return -1;
-}
-
-static const char * const connector_type_names[] = { // must match DRM_MODE_CONNECTOR_*
- "None",
- "VGA",
- "DVI",
- "DVI",
- "DVI",
- "Composite",
- "TV",
- "LVDS",
- "CTV",
- "DIN",
- "DP",
- "HDMI",
- "HDMI",
- "TV",
- "eDP",
- "Virtual",
- "DSI"
-};
-
-static QByteArray nameForConnector(const drmModeConnectorPtr connector)
-{
- QByteArray connectorName("UNKNOWN");
-
- if (connector->connector_type < ARRAY_LENGTH(connector_type_names))
- connectorName = connector_type_names[connector->connector_type];
-
- connectorName += QByteArray::number(connector->connector_type_id);
-
- return connectorName;
-}
-
-static bool parseModeline(const QByteArray &text, drmModeModeInfoPtr mode)
-{
- char hsync[16];
- char vsync[16];
- float fclock;
-
- mode->type = DRM_MODE_TYPE_USERDEF;
- mode->hskew = 0;
- mode->vscan = 0;
- mode->vrefresh = 0;
- mode->flags = 0;
-
- if (sscanf(text.constData(), "%f %hd %hd %hd %hd %hd %hd %hd %hd %15s %15s",
- &fclock,
- &mode->hdisplay,
- &mode->hsync_start,
- &mode->hsync_end,
- &mode->htotal,
- &mode->vdisplay,
- &mode->vsync_start,
- &mode->vsync_end,
- &mode->vtotal, hsync, vsync) != 11)
- return false;
-
- mode->clock = fclock * 1000;
-
- if (strcmp(hsync, "+hsync") == 0)
- mode->flags |= DRM_MODE_FLAG_PHSYNC;
- else if (strcmp(hsync, "-hsync") == 0)
- mode->flags |= DRM_MODE_FLAG_NHSYNC;
- else
- return false;
-
- if (strcmp(vsync, "+vsync") == 0)
- mode->flags |= DRM_MODE_FLAG_PVSYNC;
- else if (strcmp(vsync, "-vsync") == 0)
- mode->flags |= DRM_MODE_FLAG_NVSYNC;
- else
- return false;
-
- return true;
-}
-
-QEglFSKmsScreen *QEglFSKmsDevice::createScreenForConnector(drmModeResPtr resources,
- drmModeConnectorPtr connector,
- VirtualDesktopInfo *vinfo)
-{
- const QByteArray connectorName = nameForConnector(connector);
-
- const int crtc = crtcForConnector(resources, connector);
- if (crtc < 0) {
- qWarning() << "No usable crtc/encoder pair for connector" << connectorName;
- return Q_NULLPTR;
- }
-
- OutputConfiguration configuration;
- QSize configurationSize;
- drmModeModeInfo configurationModeline;
-
- auto userConfig = m_integration->outputSettings();
- auto userConnectorConfig = userConfig.value(QString::fromUtf8(connectorName));
- // default to the preferred mode unless overridden in the config
- const QByteArray mode = userConnectorConfig.value(QStringLiteral("mode"), QStringLiteral("preferred"))
- .toByteArray().toLower();
- if (mode == "off") {
- configuration = OutputConfigOff;
- } else if (mode == "preferred") {
- configuration = OutputConfigPreferred;
- } else if (mode == "current") {
- configuration = OutputConfigCurrent;
- } else if (sscanf(mode.constData(), "%dx%d", &configurationSize.rwidth(), &configurationSize.rheight()) == 2) {
- configuration = OutputConfigMode;
- } else if (parseModeline(mode, &configurationModeline)) {
- configuration = OutputConfigModeline;
- } else {
- qWarning("Invalid mode \"%s\" for output %s", mode.constData(), connectorName.constData());
- configuration = OutputConfigPreferred;
- }
- if (vinfo) {
- *vinfo = VirtualDesktopInfo();
- vinfo->virtualIndex = userConnectorConfig.value(QStringLiteral("virtualIndex"), INT_MAX).toInt();
- if (userConnectorConfig.contains(QStringLiteral("virtualPos"))) {
- const QByteArray vpos = userConnectorConfig.value(QStringLiteral("virtualPos")).toByteArray();
- const QByteArrayList vposComp = vpos.split(',');
- if (vposComp.count() == 2)
- vinfo->virtualPos = QPoint(vposComp[0].trimmed().toInt(), vposComp[1].trimmed().toInt());
- }
- }
-
- const uint32_t crtc_id = resources->crtcs[crtc];
-
- if (configuration == OutputConfigOff) {
- qCDebug(qLcEglfsKmsDebug) << "Turning off output" << connectorName;
- drmModeSetCrtc(m_dri_fd, crtc_id, 0, 0, 0, 0, 0, Q_NULLPTR);
- return Q_NULLPTR;
- }
-
- // Skip disconnected output
- if (configuration == OutputConfigPreferred && connector->connection == DRM_MODE_DISCONNECTED) {
- qCDebug(qLcEglfsKmsDebug) << "Skipping disconnected output" << connectorName;
- return Q_NULLPTR;
- }
-
- // Get the current mode on the current crtc
- drmModeModeInfo crtc_mode;
- memset(&crtc_mode, 0, sizeof crtc_mode);
- if (drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->connector_id)) {
- drmModeCrtcPtr crtc = drmModeGetCrtc(m_dri_fd, encoder->crtc_id);
- drmModeFreeEncoder(encoder);
-
- if (!crtc)
- return Q_NULLPTR;
-
- if (crtc->mode_valid)
- crtc_mode = crtc->mode;
-
- drmModeFreeCrtc(crtc);
- }
-
- QList<drmModeModeInfo> modes;
- modes.reserve(connector->count_modes);
- qCDebug(qLcEglfsKmsDebug) << connectorName << "mode count:" << connector->count_modes;
- for (int i = 0; i < connector->count_modes; i++) {
- const drmModeModeInfo &mode = connector->modes[i];
- qCDebug(qLcEglfsKmsDebug) << "mode" << i << mode.hdisplay << "x" << mode.vdisplay
- << '@' << mode.vrefresh << "hz";
- modes << connector->modes[i];
- }
-
- int preferred = -1;
- int current = -1;
- int configured = -1;
- int best = -1;
-
- for (int i = modes.size() - 1; i >= 0; i--) {
- const drmModeModeInfo &m = modes.at(i);
-
- if (configuration == OutputConfigMode &&
- m.hdisplay == configurationSize.width() &&
- m.vdisplay == configurationSize.height()) {
- configured = i;
- }
-
- if (!memcmp(&crtc_mode, &m, sizeof m))
- current = i;
-
- if (m.type & DRM_MODE_TYPE_PREFERRED)
- preferred = i;
-
- best = i;
- }
-
- if (configuration == OutputConfigModeline) {
- modes << configurationModeline;
- configured = modes.size() - 1;
- }
-
- if (current < 0 && crtc_mode.clock != 0) {
- modes << crtc_mode;
- current = mode.size() - 1;
- }
-
- if (configuration == OutputConfigCurrent)
- configured = current;
-
- int selected_mode = -1;
-
- if (configured >= 0)
- selected_mode = configured;
- else if (preferred >= 0)
- selected_mode = preferred;
- else if (current >= 0)
- selected_mode = current;
- else if (best >= 0)
- selected_mode = best;
-
- if (selected_mode < 0) {
- qWarning() << "No modes available for output" << connectorName;
- return Q_NULLPTR;
- } else {
- int width = modes[selected_mode].hdisplay;
- int height = modes[selected_mode].vdisplay;
- int refresh = modes[selected_mode].vrefresh;
- qCDebug(qLcEglfsKmsDebug) << "Selected mode" << selected_mode << ":" << width << "x" << height
- << '@' << refresh << "hz for output" << connectorName;
- }
-
- // physical size from connector < config values < env vars
- static const int width = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_WIDTH");
- static const int height = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_HEIGHT");
- QSizeF physSize(width, height);
- if (physSize.isEmpty()) {
- physSize = QSize(userConnectorConfig.value(QStringLiteral("physicalWidth")).toInt(),
- userConnectorConfig.value(QStringLiteral("physicalHeight")).toInt());
- if (physSize.isEmpty()) {
- physSize.setWidth(connector->mmWidth);
- physSize.setHeight(connector->mmHeight);
- }
- }
- qCDebug(qLcEglfsKmsDebug) << "Physical size is" << physSize << "mm" << "for output" << connectorName;
-
- QEglFSKmsOutput output = {
- QString::fromUtf8(connectorName),
- connector->connector_id,
- crtc_id,
- physSize,
- selected_mode,
- false,
- drmModeGetCrtc(m_dri_fd, crtc_id),
- modes,
- connector->subpixel,
- connectorProperty(connector, QByteArrayLiteral("DPMS"))
- };
-
- m_crtc_allocator |= (1 << output.crtc_id);
- m_connector_allocator |= (1 << output.connector_id);
-
- return createScreen(m_integration, this, output);
-}
-
-drmModePropertyPtr QEglFSKmsDevice::connectorProperty(drmModeConnectorPtr connector, const QByteArray &name)
-{
- drmModePropertyPtr prop;
-
- for (int i = 0; i < connector->count_props; i++) {
- prop = drmModeGetProperty(m_dri_fd, connector->props[i]);
- if (!prop)
- continue;
- if (strcmp(prop->name, name.constData()) == 0)
- return prop;
- drmModeFreeProperty(prop);
- }
-
- return Q_NULLPTR;
-}
-
-QEglFSKmsDevice::QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QString &path)
- : m_integration(integration)
- , m_path(path)
- , m_dri_fd(-1)
- , m_crtc_allocator(0)
- , m_connector_allocator(0)
-{
-}
-
-QEglFSKmsDevice::~QEglFSKmsDevice()
-{
-}
-
-struct OrderedScreen
-{
- OrderedScreen() : screen(nullptr) { }
- OrderedScreen(QEglFSKmsScreen *screen, const QEglFSKmsDevice::VirtualDesktopInfo &vinfo)
- : screen(screen), vinfo(vinfo) { }
- QEglFSKmsScreen *screen;
- QEglFSKmsDevice::VirtualDesktopInfo vinfo;
-};
-
-QDebug operator<<(QDebug dbg, const OrderedScreen &s)
-{
- QDebugStateSaver saver(dbg);
- dbg.nospace() << "OrderedScreen(" << s.screen << " : " << s.vinfo.virtualIndex
- << " / " << s.vinfo.virtualPos << ")";
- return dbg;
-}
-
-static bool orderedScreenLessThan(const OrderedScreen &a, const OrderedScreen &b)
-{
- return a.vinfo.virtualIndex < b.vinfo.virtualIndex;
-}
-
-void QEglFSKmsDevice::createScreens()
-{
- drmModeResPtr resources = drmModeGetResources(m_dri_fd);
- if (!resources) {
- qWarning("drmModeGetResources failed");
- return;
- }
-
- QVector<OrderedScreen> screens;
-
- for (int i = 0; i < resources->count_connectors; i++) {
- drmModeConnectorPtr connector = drmModeGetConnector(m_dri_fd, resources->connectors[i]);
- if (!connector)
- continue;
-
- VirtualDesktopInfo vinfo;
- QEglFSKmsScreen *screen = createScreenForConnector(resources, connector, &vinfo);
- if (screen)
- screens.append(OrderedScreen(screen, vinfo));
-
- drmModeFreeConnector(connector);
- }
-
- drmModeFreeResources(resources);
-
- // Use stable sort to preserve the original order for outputs with unspecified indices.
- std::stable_sort(screens.begin(), screens.end(), orderedScreenLessThan);
- qCDebug(qLcEglfsKmsDebug) << "Sorted screen list:" << screens;
-
- QPoint pos(0, 0);
- QList<QPlatformScreen *> siblings;
- QEglFSIntegration *qpaIntegration = static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration());
-
- for (const OrderedScreen &orderedScreen : screens) {
- QEglFSKmsScreen *s = orderedScreen.screen;
- // set up a horizontal or vertical virtual desktop
- if (orderedScreen.vinfo.virtualPos.isNull()) {
- s->setVirtualPosition(pos);
- if (m_integration->virtualDesktopLayout() == QEglFSKmsIntegration::VirtualDesktopLayoutVertical)
- pos.ry() += s->geometry().height();
- else
- pos.rx() += s->geometry().width();
- } else {
- s->setVirtualPosition(orderedScreen.vinfo.virtualPos);
- }
- qCDebug(qLcEglfsKmsDebug) << "Adding screen" << s << "to QPA with geometry" << s->geometry();
- // The order in qguiapp's screens list will match the order set by
- // virtualIndex. This is not only handy but also required since for instance
- // evdevtouch relies on it when performing touch device - screen mapping.
- qpaIntegration->addScreen(s);
- siblings << s;
- }
-
- if (!m_integration->separateScreens()) {
- // enable the virtual desktop
- Q_FOREACH (QPlatformScreen *screen, siblings)
- static_cast<QEglFSKmsScreen *>(screen)->setVirtualSiblings(siblings);
- }
-}
-
-int QEglFSKmsDevice::fd() const
-{
- return m_dri_fd;
-}
-
-QString QEglFSKmsDevice::devicePath() const
-{
- return m_path;
-}
-
-QEglFSKmsScreen *QEglFSKmsDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output)
+QEglFSKmsDevice::QEglFSKmsDevice(QKmsScreenConfig *screenConfig, const QString &path)
+ : QKmsDevice(screenConfig, path)
{
- return new QEglFSKmsScreen(integration, device, output);
}
-void QEglFSKmsDevice::setFd(int fd)
+void QEglFSKmsDevice::registerScreen(QPlatformScreen *screen,
+ const QPoint &virtualPos,
+ const QList<QPlatformScreen *> &virtualSiblings)
{
- m_dri_fd = fd;
+ QEglFSKmsScreen *s = static_cast<QEglFSKmsScreen *>(screen);
+ s->setVirtualPosition(virtualPos);
+ s->setVirtualSiblings(virtualSiblings);
+ static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration())->addScreen(s);
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h
index 3e7ac7e3f0..1bbea250bb 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h
@@ -1,6 +1,5 @@
/****************************************************************************
**
-** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2016 Pelagicore AG
** Contact: https://www.qt.io/licensing/
@@ -42,64 +41,21 @@
#ifndef QEGLFSKMSDEVICE_H
#define QEGLFSKMSDEVICE_H
-#include "qeglfskmsintegration.h"
-#include "qeglfskmsscreen.h"
-
-#include <xf86drm.h>
-#include <xf86drmMode.h>
+#include "private/qeglfsglobal_p.h"
+#include <QtKmsSupport/private/qkmsdevice_p.h>
QT_BEGIN_NAMESPACE
-class Q_EGLFS_EXPORT QEglFSKmsDevice
+class Q_EGLFS_EXPORT QEglFSKmsDevice : public QKmsDevice
{
public:
- struct VirtualDesktopInfo {
- VirtualDesktopInfo() : virtualIndex(0) { }
- int virtualIndex;
- QPoint virtualPos;
- };
-
- QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QString &path);
- virtual ~QEglFSKmsDevice();
-
- virtual bool open() = 0;
- virtual void close() = 0;
-
- virtual void createScreens();
-
- virtual EGLNativeDisplayType nativeDisplay() const = 0;
- int fd() const;
- QString devicePath() const;
-
-protected:
- virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration,
- QEglFSKmsDevice *device,
- QEglFSKmsOutput output);
- void setFd(int fd);
-
- QEglFSKmsIntegration *m_integration;
- QString m_path;
- int m_dri_fd;
-
- quint32 m_crtc_allocator;
- quint32 m_connector_allocator;
-
- int crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector);
- QEglFSKmsScreen *createScreenForConnector(drmModeResPtr resources,
- drmModeConnectorPtr connector,
- VirtualDesktopInfo *vinfo);
- drmModePropertyPtr connectorProperty(drmModeConnectorPtr connector, const QByteArray &name);
-
- static void pageFlipHandler(int fd,
- unsigned int sequence,
- unsigned int tv_sec,
- unsigned int tv_usec,
- void *user_data);
+ QEglFSKmsDevice(QKmsScreenConfig *screenConfig, const QString &path);
-private:
- Q_DISABLE_COPY(QEglFSKmsDevice)
+ void registerScreen(QPlatformScreen *screen,
+ const QPoint &virtualPos,
+ const QList<QPlatformScreen *> &virtualSiblings) override;
};
QT_END_NAMESPACE
-#endif
+#endif // QEGLFSKMSDEVICE_H
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
index 5368a6d031..c77151181e 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
@@ -40,13 +40,10 @@
****************************************************************************/
#include "qeglfskmsintegration.h"
-#include "qeglfskmsdevice.h"
#include "qeglfskmsscreen.h"
-#include <QtCore/QJsonDocument>
-#include <QtCore/QJsonObject>
-#include <QtCore/QJsonArray>
-#include <QtCore/QFile>
+#include <QtKmsSupport/private/qkmsdevice_p.h>
+
#include <QtGui/qpa/qplatformwindow.h>
#include <QtGui/QScreen>
@@ -58,28 +55,27 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(qLcEglfsKmsDebug, "qt.qpa.eglfs.kms")
QEglFSKmsIntegration::QEglFSKmsIntegration()
- : m_device(Q_NULLPTR)
- , m_hwCursor(false)
- , m_pbuffers(false)
- , m_separateScreens(false)
- , m_virtualDesktopLayout(VirtualDesktopLayoutHorizontal)
-{}
-
-void QEglFSKmsIntegration::platformInit()
+ : m_device(Q_NULLPTR),
+ m_screenConfig(new QKmsScreenConfig)
{
- loadConfig();
+}
- if (!m_devicePath.isEmpty()) {
- qCDebug(qLcEglfsKmsDebug) << "Using DRM device" << m_devicePath << "specified in config file";
- }
+QEglFSKmsIntegration::~QEglFSKmsIntegration()
+{
+ delete m_screenConfig;
+}
- m_device = createDevice(m_devicePath);
+void QEglFSKmsIntegration::platformInit()
+{
+ qCDebug(qLcEglfsKmsDebug, "platformInit: Opening DRM device");
+ m_device = createDevice();
if (Q_UNLIKELY(!m_device->open()))
- qFatal("Could not open device %s - aborting!", qPrintable(m_devicePath));
+ qFatal("Could not open DRM device");
}
void QEglFSKmsIntegration::platformDestroy()
{
+ qCDebug(qLcEglfsKmsDebug, "platformDestroy: Closing DRM device");
m_device->close();
delete m_device;
m_device = Q_NULLPTR;
@@ -88,7 +84,7 @@ void QEglFSKmsIntegration::platformDestroy()
EGLNativeDisplayType QEglFSKmsIntegration::platformDisplay() const
{
Q_ASSERT(m_device);
- return m_device->nativeDisplay();
+ return (EGLNativeDisplayType) m_device->nativeDisplay();
}
bool QEglFSKmsIntegration::usesDefaultScreen()
@@ -134,94 +130,17 @@ void QEglFSKmsIntegration::waitForVSync(QPlatformSurface *surface) const
bool QEglFSKmsIntegration::supportsPBuffers() const
{
- return m_pbuffers;
-}
-
-bool QEglFSKmsIntegration::hwCursor() const
-{
- return m_hwCursor;
-}
-
-bool QEglFSKmsIntegration::separateScreens() const
-{
- return m_separateScreens;
-}
-
-QEglFSKmsIntegration::VirtualDesktopLayout QEglFSKmsIntegration::virtualDesktopLayout() const
-{
- return m_virtualDesktopLayout;
+ return m_screenConfig->supportsPBuffers();
}
-QMap<QString, QVariantMap> QEglFSKmsIntegration::outputSettings() const
-{
- return m_outputSettings;
-}
-
-QEglFSKmsDevice *QEglFSKmsIntegration::device() const
+QKmsDevice *QEglFSKmsIntegration::device() const
{
return m_device;
}
-void QEglFSKmsIntegration::loadConfig()
+QKmsScreenConfig *QEglFSKmsIntegration::screenConfig() const
{
- static QByteArray json = qgetenv("QT_QPA_EGLFS_KMS_CONFIG");
- if (json.isEmpty())
- return;
-
- qCDebug(qLcEglfsKmsDebug) << "Loading KMS setup from" << json;
-
- QFile file(QString::fromUtf8(json));
- if (!file.open(QFile::ReadOnly)) {
- qCWarning(qLcEglfsKmsDebug) << "Could not open config file"
- << json << "for reading";
- return;
- }
-
- const QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
- if (!doc.isObject()) {
- qCWarning(qLcEglfsKmsDebug) << "Invalid config file" << json
- << "- no top-level JSON object";
- return;
- }
-
- const QJsonObject object = doc.object();
-
- m_hwCursor = object.value(QLatin1String("hwcursor")).toBool(m_hwCursor);
- m_pbuffers = object.value(QLatin1String("pbuffers")).toBool(m_pbuffers);
- m_devicePath = object.value(QLatin1String("device")).toString();
- m_separateScreens = object.value(QLatin1String("separateScreens")).toBool(m_separateScreens);
-
- const QString vdOriString = object.value(QLatin1String("virtualDesktopLayout")).toString();
- if (!vdOriString.isEmpty()) {
- if (vdOriString == QLatin1String("horizontal"))
- m_virtualDesktopLayout = VirtualDesktopLayoutHorizontal;
- else if (vdOriString == QLatin1String("vertical"))
- m_virtualDesktopLayout = VirtualDesktopLayoutVertical;
- else
- qCWarning(qLcEglfsKmsDebug) << "Unknown virtualDesktopOrientation value" << vdOriString;
- }
-
- const QJsonArray outputs = object.value(QLatin1String("outputs")).toArray();
- for (int i = 0; i < outputs.size(); i++) {
- const QVariantMap outputSettings = outputs.at(i).toObject().toVariantMap();
-
- if (outputSettings.contains(QStringLiteral("name"))) {
- const QString name = outputSettings.value(QStringLiteral("name")).toString();
-
- if (m_outputSettings.contains(name)) {
- qCDebug(qLcEglfsKmsDebug) << "Output" << name << "configured multiple times!";
- }
-
- m_outputSettings.insert(name, outputSettings);
- }
- }
-
- qCDebug(qLcEglfsKmsDebug) << "Configuration:\n"
- << "\thwcursor:" << m_hwCursor << "\n"
- << "\tpbuffers:" << m_pbuffers << "\n"
- << "\tseparateScreens:" << m_separateScreens << "\n"
- << "\tvirtualDesktopLayout:" << m_virtualDesktopLayout << "\n"
- << "\toutputs:" << m_outputSettings;
+ return m_screenConfig;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h
index ba49945715..21347d9131 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h
@@ -49,19 +49,16 @@
QT_BEGIN_NAMESPACE
-class QEglFSKmsDevice;
+class QKmsDevice;
+class QKmsScreenConfig;
Q_EGLFS_EXPORT Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
class Q_EGLFS_EXPORT QEglFSKmsIntegration : public QEglFSDeviceIntegration
{
public:
- enum VirtualDesktopLayout {
- VirtualDesktopLayoutHorizontal,
- VirtualDesktopLayoutVertical
- };
-
QEglFSKmsIntegration();
+ ~QEglFSKmsIntegration();
void platformInit() Q_DECL_OVERRIDE;
void platformDestroy() Q_DECL_OVERRIDE;
@@ -73,25 +70,14 @@ public:
void waitForVSync(QPlatformSurface *surface) const Q_DECL_OVERRIDE;
bool supportsPBuffers() const Q_DECL_OVERRIDE;
- virtual bool hwCursor() const;
- virtual bool separateScreens() const;
- virtual VirtualDesktopLayout virtualDesktopLayout() const;
- QMap<QString, QVariantMap> outputSettings() const;
-
- QEglFSKmsDevice *device() const;
+ QKmsDevice *device() const;
+ QKmsScreenConfig *screenConfig() const;
protected:
- virtual QEglFSKmsDevice *createDevice(const QString &devicePath) = 0;
-
- void loadConfig();
+ virtual QKmsDevice *createDevice() = 0;
- QEglFSKmsDevice *m_device;
- bool m_hwCursor;
- bool m_pbuffers;
- bool m_separateScreens;
- VirtualDesktopLayout m_virtualDesktopLayout;
- QString m_devicePath;
- QMap<QString, QVariantMap> m_outputSettings;
+ QKmsDevice *m_device;
+ QKmsScreenConfig *m_screenConfig;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
index 4021609407..a2af586947 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
@@ -40,7 +40,6 @@
****************************************************************************/
#include "qeglfskmsscreen.h"
-#include "qeglfskmsdevice.h"
#include "qeglfsintegration_p.h"
#include <QtCore/QLoggingCategory>
@@ -69,30 +68,19 @@ private:
QEglFSKmsScreen *m_screen;
};
-QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsIntegration *integration,
- QEglFSKmsDevice *device,
- QEglFSKmsOutput output)
- : QEglFSScreen(eglGetDisplay(device->nativeDisplay()))
- , m_integration(integration)
+QEglFSKmsScreen::QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output)
+ : QEglFSScreen(eglGetDisplay((EGLNativeDisplayType) device->nativeDisplay()))
, m_device(device)
, m_output(output)
, m_powerState(PowerStateOn)
, m_interruptHandler(new QEglFSKmsInterruptHandler(this))
{
- m_siblings << this; // gets overridden by QEglFSKmsDevice later if !separateScreens
+ m_siblings << this; // gets overridden later
}
QEglFSKmsScreen::~QEglFSKmsScreen()
{
- if (m_output.dpms_prop) {
- drmModeFreeProperty(m_output.dpms_prop);
- m_output.dpms_prop = Q_NULLPTR;
- }
- restoreMode();
- if (m_output.saved_crtc) {
- drmModeFreeCrtc(m_output.saved_crtc);
- m_output.saved_crtc = Q_NULLPTR;
- }
+ m_output.cleanup(m_device);
delete m_interruptHandler;
}
@@ -171,16 +159,7 @@ void QEglFSKmsScreen::flipFinished()
void QEglFSKmsScreen::restoreMode()
{
- if (m_output.mode_set && m_output.saved_crtc) {
- drmModeSetCrtc(m_device->fd(),
- m_output.saved_crtc->crtc_id,
- m_output.saved_crtc->buffer_id,
- 0, 0,
- &m_output.connector_id, 1,
- &m_output.saved_crtc->mode);
-
- m_output.mode_set = false;
- }
+ m_output.restoreMode(m_device);
}
qreal QEglFSKmsScreen::refreshRate() const
@@ -191,20 +170,7 @@ qreal QEglFSKmsScreen::refreshRate() const
QPlatformScreen::SubpixelAntialiasingType QEglFSKmsScreen::subpixelAntialiasingTypeHint() const
{
- switch (m_output.subpixel) {
- default:
- case DRM_MODE_SUBPIXEL_UNKNOWN:
- case DRM_MODE_SUBPIXEL_NONE:
- return Subpixel_None;
- case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
- return Subpixel_RGB;
- case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
- return Subpixel_BGR;
- case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
- return Subpixel_VRGB;
- case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
- return Subpixel_VBGR;
- }
+ return m_output.subpixelAntialiasingTypeHint();
}
QPlatformScreen::PowerState QEglFSKmsScreen::powerState() const
@@ -214,11 +180,7 @@ QPlatformScreen::PowerState QEglFSKmsScreen::powerState() const
void QEglFSKmsScreen::setPowerState(QPlatformScreen::PowerState state)
{
- if (!m_output.dpms_prop)
- return;
-
- drmModeConnectorSetProperty(m_device->fd(), m_output.connector_id,
- m_output.dpms_prop->prop_id, (int)state);
+ m_output.setPowerState(m_device, state);
m_powerState = state;
}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
index 2b6a0ffe6c..25740697d7 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
@@ -42,39 +42,20 @@
#ifndef QEGLFSKMSSCREEN_H
#define QEGLFSKMSSCREEN_H
-#include "qeglfskmsintegration.h"
#include "private/qeglfsscreen_p.h"
#include <QtCore/QList>
#include <QtCore/QMutex>
-#include <xf86drm.h>
-#include <xf86drmMode.h>
+#include <QtKmsSupport/private/qkmsdevice_p.h>
QT_BEGIN_NAMESPACE
-class QEglFSKmsDevice;
class QEglFSKmsInterruptHandler;
-struct QEglFSKmsOutput
-{
- QString name;
- uint32_t connector_id;
- uint32_t crtc_id;
- QSizeF physical_size;
- int mode; // index of selected mode in list below
- bool mode_set;
- drmModeCrtcPtr saved_crtc;
- QList<drmModeModeInfo> modes;
- int subpixel;
- drmModePropertyPtr dpms_prop;
-};
-
class Q_EGLFS_EXPORT QEglFSKmsScreen : public QEglFSScreen
{
public:
- QEglFSKmsScreen(QEglFSKmsIntegration *integration,
- QEglFSKmsDevice *device,
- QEglFSKmsOutput output);
+ QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output);
~QEglFSKmsScreen();
void setVirtualPosition(const QPoint &pos);
@@ -96,8 +77,7 @@ public:
QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; }
void setVirtualSiblings(QList<QPlatformScreen *> sl) { m_siblings = sl; }
- QEglFSKmsIntegration *integration() const { return m_integration; }
- QEglFSKmsDevice *device() const { return m_device; }
+ QKmsDevice *device() const { return m_device; }
void destroySurface();
@@ -105,7 +85,7 @@ public:
virtual void flip();
virtual void flipFinished();
- QEglFSKmsOutput &output() { return m_output; }
+ QKmsOutput &output() { return m_output; }
void restoreMode();
SubpixelAntialiasingType subpixelAntialiasingTypeHint() const Q_DECL_OVERRIDE;
@@ -114,10 +94,9 @@ public:
void setPowerState(QPlatformScreen::PowerState state) Q_DECL_OVERRIDE;
protected:
- QEglFSKmsIntegration *m_integration;
- QEglFSKmsDevice *m_device;
+ QKmsDevice *m_device;
- QEglFSKmsOutput m_output;
+ QKmsOutput m_output;
QPoint m_pos;
QList<QPlatformScreen *> m_siblings;
diff --git a/sync.profile b/sync.profile
index 2f6c5399d4..a4c94ff29b 100644
--- a/sync.profile
+++ b/sync.profile
@@ -25,6 +25,7 @@
"QtEglSupport" => "$basedir/src/platformsupport/eglconvenience",
"QtFbSupport" => "$basedir/src/platformsupport/fbconvenience",
"QtGlxSupport" => "$basedir/src/platformsupport/glxconvenience",
+ "QtKmsSupport" => "$basedir/src/platformsupport/kmsconvenience",
"QtPlatformHeaders" => "$basedir/src/platformheaders",
"QtANGLE/KHR" => "!$basedir/src/3rdparty/angle/include/KHR",
"QtANGLE/GLES2" => "!$basedir/src/3rdparty/angle/include/GLES2",