diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2019-11-11 12:24:31 +0100 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2019-11-14 16:13:30 +0100 |
commit | 813e4460de0316f176d03f19f497e52ddc3c859e (patch) | |
tree | 2f88b000942d56a0cf0cc9882645e8aada288c15 /src | |
parent | 6e42ed217c58341966f41df31f47ed05a1f61a42 (diff) |
eglfs: kms: Fix hw cursor with multiple screens
We used to have the assumption that moving the cursor to an out of
range position is valid and will result in a hidden cursor.
This is apparently not the case. For example, on an RPi4 with Mesa
V3D we get lots of funny artifacts after doing drmModeMoveCursor()
to invalid positions.
To remedy this, start hiding the cursor correctly when the position
is clearly out of the screen's bounds.
Task-number: QTBUG-79924
Change-Id: I3ef7ad0ce928546399443f21452f0b6deadf8036
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src')
6 files changed, 53 insertions, 12 deletions
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp index 4d0cf0c47e..1125bcb390 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp @@ -214,7 +214,8 @@ void QEglFSKmsGbmCursor::changeCursor(QCursor *windowCursor, QWindow *window) Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen); - + if (kmsScreen->isCursorOutOfRange()) + continue; int status = drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, handle, m_cursorSize.width(), m_cursorSize.height()); if (status != 0) @@ -232,17 +233,36 @@ void QEglFSKmsGbmCursor::setPos(const QPoint &pos) { Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen); - QPoint origin = kmsScreen->geometry().topLeft(); - QPoint localPos = pos - origin; - QPoint adjustedPos = localPos - m_cursorImage.hotspot(); - - int ret = drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, adjustedPos.x(), adjustedPos.y()); - if (ret == 0) - m_pos = pos; - else - qWarning("Failed to move cursor on screen %s: %d", kmsScreen->name().toLatin1().constData(), ret); - - kmsScreen->handleCursorMove(pos); + const QRect screenGeom = kmsScreen->geometry(); + const QPoint origin = screenGeom.topLeft(); + const QPoint localPos = pos - origin; + const QPoint adjustedLocalPos = localPos - m_cursorImage.hotspot(); + + if (localPos.x() < 0 || localPos.y() < 0 + || localPos.x() >= screenGeom.width() || localPos.y() >= screenGeom.height()) + { + if (!kmsScreen->isCursorOutOfRange()) { + kmsScreen->setCursorOutOfRange(true); + drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0); + } + } else { + int ret; + if (kmsScreen->isCursorOutOfRange()) { + kmsScreen->setCursorOutOfRange(false); + uint32_t handle = gbm_bo_get_handle(m_bo).u32; + ret = drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, + handle, m_cursorSize.width(), m_cursorSize.height()); + } else { + ret = drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, + adjustedLocalPos.x(), adjustedLocalPos.y()); + } + if (ret == 0) + m_pos = pos; + else + qWarning("Failed to move cursor on screen %s: %d", kmsScreen->name().toLatin1().constData(), ret); + + kmsScreen->handleCursorMove(pos); + } } } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h index d47b579238..5d2dfedba2 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h @@ -85,6 +85,8 @@ public: void updateMouseStatus(); + void reevaluateVisibilityForScreens() { setPos(pos()); } + private: void initCursorAtlas(); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp index 20127ae7f7..f4a69483bd 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp @@ -155,4 +155,14 @@ void QEglFSKmsGbmDevice::registerScreenCloning(QPlatformScreen *screen, gbmScreen->initCloning(screenThisScreenClones, screensCloningThisScreen); } +void QEglFSKmsGbmDevice::registerScreen(QPlatformScreen *screen, + bool isPrimary, + const QPoint &virtualPos, + const QList<QPlatformScreen *> &virtualSiblings) +{ + QEglFSKmsDevice::registerScreen(screen, isPrimary, virtualPos, virtualSiblings); + if (screenConfig()->hwCursor() && m_globalCursor) + m_globalCursor->reevaluateVisibilityForScreens(); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h index 518e2ce58b..f1476f8ffa 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h @@ -70,6 +70,10 @@ public: void registerScreenCloning(QPlatformScreen *screen, QPlatformScreen *screenThisScreenClones, const QVector<QPlatformScreen *> &screensCloningThisScreen) override; + void registerScreen(QPlatformScreen *screen, + bool isPrimary, + const QPoint &virtualPos, + const QList<QPlatformScreen *> &virtualSiblings) override; private: Q_DISABLE_COPY(QEglFSKmsGbmDevice) 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 e5354d97bd..b097f67e93 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp @@ -72,6 +72,7 @@ QEglFSKmsScreen::QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output, b : QEglFSScreen(static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration())->display()) , m_device(device) , m_output(output) + , m_cursorOutOfRange(false) , m_powerState(PowerStateOn) , m_interruptHandler(new QEglFSKmsInterruptHandler(this)) , m_headless(headless) 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 7f395aacb7..93d7e4c1eb 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h @@ -99,12 +99,16 @@ public: QPlatformScreen::PowerState powerState() const override; void setPowerState(QPlatformScreen::PowerState state) override; + bool isCursorOutOfRange() const { return m_cursorOutOfRange; } + void setCursorOutOfRange(bool b) { m_cursorOutOfRange = b; } + protected: QKmsDevice *m_device; QKmsOutput m_output; QEdidParser m_edid; QPoint m_pos; + bool m_cursorOutOfRange; QList<QPlatformScreen *> m_siblings; |