From 2e70a86900962b1f5f6ad79ca3245bc99873d889 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 4 Oct 2016 11:29:26 +0200 Subject: Move DRM/KMS code from eglfs into kmsconvenience The generic DRM code, not involving any GBM or EGLDevice stuff, can now be reused in components outside eglfs, for example linuxfb in order to get support for DRM dumb buffers. Task-number: QTBUG-56306 Change-Id: If7dffdb2415489dbc6470782fa76efcaeccf01c7 Reviewed-by: Oswald Buddenhagen Reviewed-by: Andy Nichols --- .../eglfs_kms_support/eglfs_kms_support.pro | 6 +- .../eglfs_kms_support/qeglfskmsdevice.cpp | 429 +-------------------- .../eglfs_kms_support/qeglfskmsdevice.h | 60 +-- .../eglfs_kms_support/qeglfskmsintegration.cpp | 121 +----- .../eglfs_kms_support/qeglfskmsintegration.h | 30 +- .../eglfs_kms_support/qeglfskmsscreen.cpp | 52 +-- .../eglfs_kms_support/qeglfskmsscreen.h | 33 +- 7 files changed, 62 insertions(+), 669 deletions(-) (limited to 'src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support') 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 ** 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 -#include +#include "private/qeglfsintegration_p.h" #include -#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 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 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 siblings; - QEglFSIntegration *qpaIntegration = static_cast(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(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 &virtualSiblings) { - m_dri_fd = fd; + QEglFSKmsScreen *s = static_cast(screen); + s->setVirtualPosition(virtualPos); + s->setVirtualSiblings(virtualSiblings); + static_cast(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 ** 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 -#include +#include "private/qeglfsglobal_p.h" +#include 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 &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 -#include -#include -#include +#include + #include #include @@ -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 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 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 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 @@ -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 #include -#include -#include +#include 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 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 virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; } void setVirtualSiblings(QList 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 m_siblings; -- cgit v1.2.3