From 2afead0211302799519abee5c164ae0602a7e13b Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 9 Aug 2016 10:08:46 +0200 Subject: eglfs: Configurable screen order in the virtual desktop Say one wants a virtual desktop with the display on HDMI above the display on DisplayPort: { "device": "drm-nvdc", "virtualDesktopOrientation": "vertical", "outputs": [ { "name": "HDMI1", "virtualIndex": 0 }, { "name": "DP1" } ] } Undefined virtualIndex values map to INT_MAX and will go after the explicitly specified ones. However, the sorting is stable so the original order from the DRM connector list is preserved between such outputs. Task-number: QTBUG-55188 Change-Id: I204fb08205ea7dbfbcdefd1d22ed22f5387f3e8c Reviewed-by: Andy Nichols --- .../eglfs_kms/qeglfskmsgbmdevice.cpp | 4 +- .../eglfs_kms/qeglfskmsgbmdevice.h | 3 +- .../eglfs_kms/qeglfskmsgbmscreen.cpp | 7 +- .../eglfs_kms/qeglfskmsgbmscreen.h | 5 +- .../eglfs_kms_egldevice/qeglfskmsegldevice.cpp | 4 +- .../eglfs_kms_egldevice/qeglfskmsegldevice.h | 3 +- .../qeglfskmsegldevicescreen.cpp | 4 +- .../eglfs_kms_egldevice/qeglfskmsegldevicescreen.h | 3 +- .../eglfs_kms_support/qeglfskmsdevice.cpp | 77 +++++++++++++++------- .../eglfs_kms_support/qeglfskmsdevice.h | 5 +- .../eglfs_kms_support/qeglfskmsintegration.cpp | 2 +- .../eglfs_kms_support/qeglfskmsscreen.cpp | 35 +++------- .../eglfs_kms_support/qeglfskmsscreen.h | 6 +- 13 files changed, 84 insertions(+), 74 deletions(-) (limited to 'src/plugins/platforms/eglfs') diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp index 278752bddf..99f6cfb0ca 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp @@ -142,10 +142,10 @@ void QEglFSKmsGbmDevice::handleDrmEvent() drmHandleEvent(fd(), &drmEvent); } -QEglFSKmsScreen *QEglFSKmsGbmDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position) +QEglFSKmsScreen *QEglFSKmsGbmDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output) { static bool firstScreen = true; - QEglFSKmsGbmScreen *screen = new QEglFSKmsGbmScreen(integration, device, output, position); + QEglFSKmsGbmScreen *screen = new QEglFSKmsGbmScreen(integration, device, output); if (firstScreen && integration->hwCursor()) { m_globalCursor = new QEglFSKmsGbmCursor(screen); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h index 6a45f9ffa0..7c0af84422 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h @@ -68,8 +68,7 @@ public: virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, - QEglFSKmsOutput output, - QPoint position) Q_DECL_OVERRIDE; + QEglFSKmsOutput output) Q_DECL_OVERRIDE; private: Q_DISABLE_COPY(QEglFSKmsGbmDevice) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp index 9ffffd7471..dde386fc57 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp @@ -93,10 +93,9 @@ QEglFSKmsGbmScreen::FrameBuffer *QEglFSKmsGbmScreen::framebufferForBufferObject( } QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QEglFSKmsIntegration *integration, - QEglFSKmsDevice *device, - QEglFSKmsOutput output, - QPoint position) - : QEglFSKmsScreen(integration, device, output, position) + QEglFSKmsDevice *device, + QEglFSKmsOutput output) + : QEglFSKmsScreen(integration, device, output) , m_gbm_surface(Q_NULLPTR) , m_gbm_bo_current(Q_NULLPTR) , m_gbm_bo_next(Q_NULLPTR) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h index 3381bbfdbb..d7ad348291 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h @@ -55,9 +55,8 @@ class QEglFSKmsGbmScreen : public QEglFSKmsScreen { public: QEglFSKmsGbmScreen(QEglFSKmsIntegration *integration, - QEglFSKmsDevice *device, - QEglFSKmsOutput output, - QPoint position); + QEglFSKmsDevice *device, + QEglFSKmsOutput output); ~QEglFSKmsGbmScreen(); QPlatformCursor *cursor() const Q_DECL_OVERRIDE; 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 f45b947fa6..d30963ff96 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp @@ -83,9 +83,9 @@ EGLNativeDisplayType QEglFSKmsEglDevice::nativeDisplay() const } QEglFSKmsScreen *QEglFSKmsEglDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, - QEglFSKmsOutput output, QPoint position) + QEglFSKmsOutput output) { - QEglFSKmsScreen *screen = new QEglFSKmsEglDeviceScreen(integration, device, output, position); + QEglFSKmsScreen *screen = new QEglFSKmsEglDeviceScreen(integration, device, output); if (!m_globalCursor && !integration->separateScreens()) { qCDebug(qLcEglfsKmsDebug, "Creating new global mouse cursor"); 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 a27112fb4f..8c8f79f70c 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h @@ -58,8 +58,7 @@ public: virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, - QEglFSKmsOutput output, - QPoint position) Q_DECL_OVERRIDE; + QEglFSKmsOutput output) Q_DECL_OVERRIDE; QPlatformCursor *globalCursor() { return m_globalCursor; } void destroyGlobalCursor(); 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 b0deabe834..55d5941e5f 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp @@ -43,8 +43,8 @@ QT_BEGIN_NAMESPACE -QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position) - : QEglFSKmsScreen(integration, device, output, position) +QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output) + : QEglFSKmsScreen(integration, device, output) { } 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 7fceae4978..c57f52c6b7 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h @@ -49,8 +49,7 @@ class QEglFSKmsEglDeviceScreen : public QEglFSKmsScreen public: QEglFSKmsEglDeviceScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, - QEglFSKmsOutput output, - QPoint position); + QEglFSKmsOutput output); ~QEglFSKmsEglDeviceScreen(); QPlatformCursor *cursor() const Q_DECL_OVERRIDE; 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 74c7667f1f..842896bbad 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp @@ -159,7 +159,7 @@ static bool parseModeline(const QByteArray &text, drmModeModeInfoPtr mode) return true; } -QEglFSKmsScreen *QEglFSKmsDevice::createScreenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, QPoint pos) +QEglFSKmsScreen *QEglFSKmsDevice::createScreenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, int *virtualIndex) { const QByteArray connectorName = nameForConnector(connector); @@ -192,6 +192,8 @@ QEglFSKmsScreen *QEglFSKmsDevice::createScreenForConnector(drmModeResPtr resourc qWarning("Invalid mode \"%s\" for output %s", mode.constData(), connectorName.constData()); configuration = OutputConfigPreferred; } + if (virtualIndex) + *virtualIndex = userConnectorConfig.value(QStringLiteral("virtualIndex"), INT_MAX).toInt(); const uint32_t crtc_id = resources->crtcs[crtc]; @@ -303,6 +305,7 @@ QEglFSKmsScreen *QEglFSKmsDevice::createScreenForConnector(drmModeResPtr resourc physSize.setHeight(connector->mmHeight); } } + qCDebug(qLcEglfsKmsDebug) << "Physical size is" << physSize << "mm" << "for output" << connectorName; QEglFSKmsOutput output = { QString::fromUtf8(connectorName), @@ -320,7 +323,7 @@ QEglFSKmsScreen *QEglFSKmsDevice::createScreenForConnector(drmModeResPtr resourc m_crtc_allocator |= (1 << output.crtc_id); m_connector_allocator |= (1 << output.connector_id); - return createScreen(m_integration, this, output, pos); + return createScreen(m_integration, this, output); } drmModePropertyPtr QEglFSKmsDevice::connectorProperty(drmModeConnectorPtr connector, const QByteArray &name) @@ -352,6 +355,26 @@ QEglFSKmsDevice::~QEglFSKmsDevice() { } +struct OrderedScreen +{ + OrderedScreen() : screen(nullptr), index(-1) { } + OrderedScreen(QEglFSKmsScreen *screen, int index) : screen(screen), index(index) { } + QEglFSKmsScreen *screen; + int index; +}; + +QDebug operator<<(QDebug dbg, const OrderedScreen &s) +{ + QDebugStateSaver saver(dbg); + dbg.nospace() << "OrderedScreen(" << s.screen << " : " << s.index << ")"; + return dbg; +} + +static bool orderedScreenLessThan(const OrderedScreen &a, const OrderedScreen &b) +{ + return a.index < b.index; +} + void QEglFSKmsDevice::createScreens() { drmModeResPtr resources = drmModeGetResources(m_dri_fd); @@ -360,38 +383,46 @@ void QEglFSKmsDevice::createScreens() return; } - QEglFSKmsScreen *primaryScreen = Q_NULLPTR; - QList siblings; - QPoint pos(0, 0); - QEglFSIntegration *integration = static_cast(QGuiApplicationPrivate::platformIntegration()); + QVector screens; for (int i = 0; i < resources->count_connectors; i++) { drmModeConnectorPtr connector = drmModeGetConnector(m_dri_fd, resources->connectors[i]); if (!connector) continue; - QEglFSKmsScreen *screen = createScreenForConnector(resources, connector, pos); - if (screen) { - integration->addScreen(screen); - - if (m_integration->virtualDesktopLayout() == QEglFSKmsIntegration::VirtualDesktopLayoutVertical) - pos.ry() += screen->geometry().height(); - else - pos.rx() += screen->geometry().width(); - - siblings << screen; - - if (!primaryScreen) - primaryScreen = screen; - } + int virtualIndex; + QEglFSKmsScreen *screen = createScreenForConnector(resources, connector, &virtualIndex); + if (screen) + screens.append(OrderedScreen(screen, virtualIndex)); 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 + s->setVirtualPosition(pos); + if (m_integration->virtualDesktopLayout() == QEglFSKmsIntegration::VirtualDesktopLayoutVertical) + pos.ry() += s->geometry().height(); + else + pos.rx() += s->geometry().width(); + qCDebug(qLcEglfsKmsDebug) << "Adding screen" << s << "to QPA with geometry" << s->geometry(); + qpaIntegration->addScreen(s); + siblings << s; + } + if (!m_integration->separateScreens()) { - // set up a virtual desktop + // enable the virtual desktop Q_FOREACH (QPlatformScreen *screen, siblings) static_cast(screen)->setVirtualSiblings(siblings); } @@ -407,9 +438,9 @@ QString QEglFSKmsDevice::devicePath() const return m_path; } -QEglFSKmsScreen *QEglFSKmsDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position) +QEglFSKmsScreen *QEglFSKmsDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output) { - return new QEglFSKmsScreen(integration, device, output, position); + return new QEglFSKmsScreen(integration, device, output); } void QEglFSKmsDevice::setFd(int fd) 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 6561949780..4aad2e0143 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h @@ -68,8 +68,7 @@ public: protected: virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, - QEglFSKmsOutput output, - QPoint position); + QEglFSKmsOutput output); void setFd(int fd); QEglFSKmsIntegration *m_integration; @@ -80,7 +79,7 @@ protected: quint32 m_connector_allocator; int crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector); - QEglFSKmsScreen *createScreenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, QPoint pos); + QEglFSKmsScreen *createScreenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, int *virtualIndex); drmModePropertyPtr connectorProperty(drmModeConnectorPtr connector, const QByteArray &name); static void pageFlipHandler(int fd, 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 0f64d5b28e..6c30e8f930 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp @@ -201,7 +201,7 @@ void QEglFSKmsIntegration::loadConfig() else if (vdOriString == QLatin1String("vertical")) m_virtualDesktopLayout = VirtualDesktopLayoutVertical; else - qCWarning(qLcEglfsKmsDebug) << "Unknown virtualDesktop value" << vdOriString; + qCWarning(qLcEglfsKmsDebug) << "Unknown virtualDesktopOrientation value" << vdOriString; } const QJsonArray outputs = object.value(QLatin1String("outputs")).toArray(); 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 55417e4525..f690cd668e 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp @@ -71,13 +71,11 @@ private: QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, - QEglFSKmsOutput output, - QPoint position) + QEglFSKmsOutput output) : QEglFSScreen(eglGetDisplay(device->nativeDisplay())) , m_integration(integration) , m_device(device) , m_output(output) - , m_pos(position) , m_powerState(PowerStateOn) , m_interruptHandler(new QEglFSKmsInterruptHandler(this)) { @@ -98,34 +96,19 @@ QEglFSKmsScreen::~QEglFSKmsScreen() delete m_interruptHandler; } +void QEglFSKmsScreen::setVirtualPosition(const QPoint &pos) +{ + m_pos = pos; +} + // Reimplement rawGeometry(), not geometry(). The base class implementation of // geometry() calls rawGeometry() and may apply additional transforms. QRect QEglFSKmsScreen::rawGeometry() const { const int mode = m_output.mode; - QRect r(m_pos.x(), m_pos.y(), - m_output.modes[mode].hdisplay, - m_output.modes[mode].vdisplay); - - static int rotation = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ROTATION"); - switch (rotation) { - case 0: - case 180: - case -180: - break; - case 90: - case -90: { - int h = r.height(); - r.setHeight(r.width()); - r.setWidth(h); - break; - } - default: - qWarning("Invalid rotation %d specified in QT_QPA_EGLFS_ROTATION", rotation); - break; - } - - return r; + return QRect(m_pos.x(), m_pos.y(), + m_output.modes[mode].hdisplay, + m_output.modes[mode].vdisplay); } int QEglFSKmsScreen::depth() const 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 7b424b5382..2b6a0ffe6c 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h @@ -74,11 +74,13 @@ class Q_EGLFS_EXPORT QEglFSKmsScreen : public QEglFSScreen public: QEglFSKmsScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, - QEglFSKmsOutput output, - QPoint position); + QEglFSKmsOutput output); ~QEglFSKmsScreen(); + void setVirtualPosition(const QPoint &pos); + QRect rawGeometry() const Q_DECL_OVERRIDE; + int depth() const Q_DECL_OVERRIDE; QImage::Format format() const Q_DECL_OVERRIDE; -- cgit v1.2.3