DRM/KMS config: add support for specifying the primary screen

Not having a way to say that a given output should be registered as the
primary screen (meaning it comes first in the QGuiApplication::screens() list,
emits primaryScreenChanged() signal etc.) can be a problem for some systems.

The order of the outputs array in the JSON configuration file is not relevant
in this respect since screens are registered either in the original DRM connector
order, or, when the virtual desktop layout is specified via virtualIndex, in the
order specified by virtualIndex. The primary screen status is independent from this.

Therefore, add a new, optional boolean property: primary. For example, the following
forces the QScreen corresponding to the VGA output to be the primary screen on the
Renesas R-Car H2 board, even though by default it is the HDMI one that happens to
be reported first by the system.

{
    "device": "/dev/dri/card0",
    "outputs": [
        { "name": "HDMI1", "mode": "1280x720" },
        { "name": "VGA1", "mode": "1280x720", "primary": true },
        { "name": "LVDS1", "mode": "off" }
    ]
}

In addition, improve the quality of the logging output.

[ChangeLog][Platform Specific Changes] Added support for specifying the primary screen
in the JSON config file in QT_QPA_EGLFS_KMS_CONFIG when running on DRM/KMS with eglfs.

Task-number: QTBUG-57980
Change-Id: Iba490800dee3b7162c68c4d40b0822f3f6d81b69
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
Laszlo Agocs 2017-01-12 13:54:05 +01:00
parent 8c14429843
commit a0bc9d0027
7 changed files with 31 additions and 13 deletions

View File

@ -204,6 +204,8 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
if (vposComp.count() == 2)
vinfo->virtualPos = QPoint(vposComp[0].trimmed().toInt(), vposComp[1].trimmed().toInt());
}
if (userConnectorConfig.value(QStringLiteral("primary")).toBool())
vinfo->isPrimary = true;
}
const uint32_t crtc_id = resources->crtcs[crtc];
@ -413,8 +415,11 @@ struct OrderedScreen
QDebug operator<<(QDebug dbg, const OrderedScreen &s)
{
QDebugStateSaver saver(dbg);
dbg.nospace() << "OrderedScreen(" << s.screen << " : " << s.vinfo.virtualIndex
<< " / " << s.vinfo.virtualPos << ")";
dbg.nospace() << "OrderedScreen(QPlatformScreen=" << s.screen << " (" << s.screen->name() << ") : "
<< s.vinfo.virtualIndex
<< " / " << s.vinfo.virtualPos
<< " / primary: " << s.vinfo.isPrimary
<< ")";
return dbg;
}
@ -461,13 +466,15 @@ void QKmsDevice::createScreens()
drmModeFreeResources(resources);
// Use stable sort to preserve the original order for outputs with unspecified indices.
// Use stable sort to preserve the original (DRM connector) 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;
int primarySiblingIdx = -1;
for (const OrderedScreen &orderedScreen : screens) {
QPlatformScreen *s = orderedScreen.screen;
@ -482,22 +489,26 @@ void QKmsDevice::createScreens()
} else {
virtualPos = orderedScreen.vinfo.virtualPos;
}
qCDebug(qLcKmsDebug) << "Adding screen" << s << "to QPA with geometry" << s->geometry();
qCDebug(qLcKmsDebug) << "Adding QPlatformScren" << s << "(" << s->name() << ")"
<< "to QPA with geometry" << s->geometry()
<< "and isPrimary=" << orderedScreen.vinfo.isPrimary;
// 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);
if (orderedScreen.vinfo.isPrimary)
primarySiblingIdx = siblings.count() - 1;
} else {
registerScreen(s, virtualPos, QList<QPlatformScreen *>() << s);
registerScreen(s, orderedScreen.vinfo.isPrimary, 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);
registerScreen(siblings[i], i == primarySiblingIdx, virtualPositions[i], siblings);
}
}

View File

@ -120,9 +120,10 @@ class QKmsDevice
{
public:
struct VirtualDesktopInfo {
VirtualDesktopInfo() : virtualIndex(0) { }
VirtualDesktopInfo() : virtualIndex(0), isPrimary(false) { }
int virtualIndex;
QPoint virtualPos;
bool isPrimary;
};
QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path = QString());
@ -142,6 +143,7 @@ public:
protected:
virtual QPlatformScreen *createScreen(const QKmsOutput &output) = 0;
virtual void registerScreen(QPlatformScreen *screen,
bool isPrimary,
const QPoint &virtualPos,
const QList<QPlatformScreen *> &virtualSiblings) = 0;

View File

@ -116,9 +116,9 @@ QEglFSIntegration::QEglFSIntegration()
initResources();
}
void QEglFSIntegration::addScreen(QPlatformScreen *screen)
void QEglFSIntegration::addScreen(QPlatformScreen *screen, bool isPrimary)
{
screenAdded(screen);
screenAdded(screen, isPrimary);
}
void QEglFSIntegration::removeScreen(QPlatformScreen *screen)

View File

@ -103,7 +103,7 @@ public:
QFbVtHandler *vtHandler() { return m_vtHandler.data(); }
void addScreen(QPlatformScreen *screen);
void addScreen(QPlatformScreen *screen, bool isPrimary = false);
void removeScreen(QPlatformScreen *screen);
private:

View File

@ -51,13 +51,14 @@ QEglFSKmsDevice::QEglFSKmsDevice(QKmsScreenConfig *screenConfig, const QString &
}
void QEglFSKmsDevice::registerScreen(QPlatformScreen *screen,
bool isPrimary,
const QPoint &virtualPos,
const QList<QPlatformScreen *> &virtualSiblings)
{
QEglFSKmsScreen *s = static_cast<QEglFSKmsScreen *>(screen);
s->setVirtualPosition(virtualPos);
s->setVirtualSiblings(virtualSiblings);
static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration())->addScreen(s);
static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration())->addScreen(s, isPrimary);
}
QT_END_NAMESPACE

View File

@ -52,6 +52,7 @@ public:
QEglFSKmsDevice(QKmsScreenConfig *screenConfig, const QString &path);
void registerScreen(QPlatformScreen *screen,
bool isPrimary,
const QPoint &virtualPos,
const QList<QPlatformScreen *> &virtualSiblings) override;
};

View File

@ -106,6 +106,7 @@ private:
void *nativeDisplay() const override;
QPlatformScreen *createScreen(const QKmsOutput &output) override;
void registerScreen(QPlatformScreen *screen,
bool isPrimary,
const QPoint &virtualPos,
const QList<QPlatformScreen *> &virtualSiblings) override;
@ -175,10 +176,12 @@ QPlatformScreen *QLinuxFbDevice::createScreen(const QKmsOutput &output)
}
void QLinuxFbDevice::registerScreen(QPlatformScreen *screen,
const QPoint &virtualPos,
const QList<QPlatformScreen *> &virtualSiblings)
bool isPrimary,
const QPoint &virtualPos,
const QList<QPlatformScreen *> &virtualSiblings)
{
Q_UNUSED(screen);
Q_UNUSED(isPrimary);
Q_UNUSED(virtualPos);
Q_UNUSED(virtualSiblings);
Q_UNREACHABLE();