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>
This commit is contained in:
parent
6e42ed217c
commit
813e4460de
@ -214,7 +214,8 @@ void QEglFSKmsGbmCursor::changeCursor(QCursor *windowCursor, QWindow *window)
|
|||||||
|
|
||||||
Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) {
|
Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) {
|
||||||
QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen);
|
QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen);
|
||||||
|
if (kmsScreen->isCursorOutOfRange())
|
||||||
|
continue;
|
||||||
int status = drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, handle,
|
int status = drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, handle,
|
||||||
m_cursorSize.width(), m_cursorSize.height());
|
m_cursorSize.width(), m_cursorSize.height());
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
@ -232,11 +233,29 @@ void QEglFSKmsGbmCursor::setPos(const QPoint &pos)
|
|||||||
{
|
{
|
||||||
Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) {
|
Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) {
|
||||||
QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen);
|
QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen);
|
||||||
QPoint origin = kmsScreen->geometry().topLeft();
|
const QRect screenGeom = kmsScreen->geometry();
|
||||||
QPoint localPos = pos - origin;
|
const QPoint origin = screenGeom.topLeft();
|
||||||
QPoint adjustedPos = localPos - m_cursorImage.hotspot();
|
const QPoint localPos = pos - origin;
|
||||||
|
const QPoint adjustedLocalPos = localPos - m_cursorImage.hotspot();
|
||||||
|
|
||||||
int ret = drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, adjustedPos.x(), adjustedPos.y());
|
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)
|
if (ret == 0)
|
||||||
m_pos = pos;
|
m_pos = pos;
|
||||||
else
|
else
|
||||||
@ -245,6 +264,7 @@ void QEglFSKmsGbmCursor::setPos(const QPoint &pos)
|
|||||||
kmsScreen->handleCursorMove(pos);
|
kmsScreen->handleCursorMove(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QEglFSKmsGbmCursor::initCursorAtlas()
|
void QEglFSKmsGbmCursor::initCursorAtlas()
|
||||||
{
|
{
|
||||||
|
@ -85,6 +85,8 @@ public:
|
|||||||
|
|
||||||
void updateMouseStatus();
|
void updateMouseStatus();
|
||||||
|
|
||||||
|
void reevaluateVisibilityForScreens() { setPos(pos()); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initCursorAtlas();
|
void initCursorAtlas();
|
||||||
|
|
||||||
|
@ -155,4 +155,14 @@ void QEglFSKmsGbmDevice::registerScreenCloning(QPlatformScreen *screen,
|
|||||||
gbmScreen->initCloning(screenThisScreenClones, screensCloningThisScreen);
|
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
|
QT_END_NAMESPACE
|
||||||
|
@ -70,6 +70,10 @@ public:
|
|||||||
void registerScreenCloning(QPlatformScreen *screen,
|
void registerScreenCloning(QPlatformScreen *screen,
|
||||||
QPlatformScreen *screenThisScreenClones,
|
QPlatformScreen *screenThisScreenClones,
|
||||||
const QVector<QPlatformScreen *> &screensCloningThisScreen) override;
|
const QVector<QPlatformScreen *> &screensCloningThisScreen) override;
|
||||||
|
void registerScreen(QPlatformScreen *screen,
|
||||||
|
bool isPrimary,
|
||||||
|
const QPoint &virtualPos,
|
||||||
|
const QList<QPlatformScreen *> &virtualSiblings) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(QEglFSKmsGbmDevice)
|
Q_DISABLE_COPY(QEglFSKmsGbmDevice)
|
||||||
|
@ -72,6 +72,7 @@ QEglFSKmsScreen::QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output, b
|
|||||||
: QEglFSScreen(static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration())->display())
|
: QEglFSScreen(static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration())->display())
|
||||||
, m_device(device)
|
, m_device(device)
|
||||||
, m_output(output)
|
, m_output(output)
|
||||||
|
, m_cursorOutOfRange(false)
|
||||||
, m_powerState(PowerStateOn)
|
, m_powerState(PowerStateOn)
|
||||||
, m_interruptHandler(new QEglFSKmsInterruptHandler(this))
|
, m_interruptHandler(new QEglFSKmsInterruptHandler(this))
|
||||||
, m_headless(headless)
|
, m_headless(headless)
|
||||||
|
@ -99,12 +99,16 @@ public:
|
|||||||
QPlatformScreen::PowerState powerState() const override;
|
QPlatformScreen::PowerState powerState() const override;
|
||||||
void setPowerState(QPlatformScreen::PowerState state) override;
|
void setPowerState(QPlatformScreen::PowerState state) override;
|
||||||
|
|
||||||
|
bool isCursorOutOfRange() const { return m_cursorOutOfRange; }
|
||||||
|
void setCursorOutOfRange(bool b) { m_cursorOutOfRange = b; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QKmsDevice *m_device;
|
QKmsDevice *m_device;
|
||||||
|
|
||||||
QKmsOutput m_output;
|
QKmsOutput m_output;
|
||||||
QEdidParser m_edid;
|
QEdidParser m_edid;
|
||||||
QPoint m_pos;
|
QPoint m_pos;
|
||||||
|
bool m_cursorOutOfRange;
|
||||||
|
|
||||||
QList<QPlatformScreen *> m_siblings;
|
QList<QPlatformScreen *> m_siblings;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user