platforms/drm: keep disconnected DrmConnectors around
This commit is contained in:
parent
a07aae8282
commit
102fb3d5f2
3 changed files with 87 additions and 93 deletions
|
@ -255,40 +255,24 @@ bool DrmGpu::updateOutputs()
|
|||
for (int i = 0; i < resources->count_connectors; ++i) {
|
||||
const uint32_t currentConnector = resources->connectors[i];
|
||||
auto it = std::find_if(m_connectors.constBegin(), m_connectors.constEnd(), [currentConnector] (DrmConnector *c) { return c->id() == currentConnector; });
|
||||
if (it == m_connectors.constEnd()) {
|
||||
auto c = new DrmConnector(this, currentConnector);
|
||||
if (!c->init() || !c->isConnected()) {
|
||||
delete c;
|
||||
DrmConnector *conn = it == m_connectors.constEnd() ? nullptr : *it;
|
||||
if (!conn) {
|
||||
conn = new DrmConnector(this, currentConnector);
|
||||
if (!conn->init()) {
|
||||
delete conn;
|
||||
continue;
|
||||
}
|
||||
m_connectors << c;
|
||||
m_pipelines << c->pipeline();
|
||||
m_connectors << conn;
|
||||
} else {
|
||||
(*it)->updateProperties();
|
||||
if ((*it)->isConnected()) {
|
||||
removedConnectors.removeOne(*it);
|
||||
removedConnectors.removeOne(conn);
|
||||
conn->updateProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto &connector : qAsConst(removedConnectors)) {
|
||||
if (auto output = findOutput(connector->id())) {
|
||||
removeOutput(output);
|
||||
} else if (auto leaseOutput = findLeaseOutput(connector->id())) {
|
||||
removeLeaseOutput(leaseOutput);
|
||||
}
|
||||
m_connectors.removeOne(connector);
|
||||
m_pipelines.removeOne(connector->pipeline());
|
||||
delete connector;
|
||||
}
|
||||
|
||||
// find unused and connected connectors
|
||||
for (const auto &conn : qAsConst(m_connectors)) {
|
||||
auto output = findOutput(conn->id());
|
||||
if (conn->isConnected()) {
|
||||
if (output) {
|
||||
if (auto output = findOutput(conn->id())) {
|
||||
output->updateModes();
|
||||
} else if (!findLeaseOutput(conn->id())) {
|
||||
qCDebug(KWIN_DRM, "New %soutput on GPU %s: %s", conn->isNonDesktop() ? "non-desktop " : "", qPrintable(m_devNode), qPrintable(conn->modelName()));
|
||||
m_pipelines << conn->pipeline();
|
||||
if (conn->isNonDesktop()) {
|
||||
auto leaseOutput = new DrmLeaseOutput(conn->pipeline(), m_leaseDevice);
|
||||
m_leaseOutputs << leaseOutput;
|
||||
|
@ -302,12 +286,21 @@ bool DrmGpu::updateOutputs()
|
|||
Q_EMIT outputAdded(output);
|
||||
}
|
||||
}
|
||||
} else if (output) {
|
||||
} else if (auto output = findOutput(conn->id())) {
|
||||
removeOutput(output);
|
||||
} else if (const auto leaseOutput = findLeaseOutput(conn->id())) {
|
||||
} else if (auto leaseOutput = findLeaseOutput(conn->id())) {
|
||||
removeLeaseOutput(leaseOutput);
|
||||
}
|
||||
}
|
||||
for (const auto &connector : qAsConst(removedConnectors)) {
|
||||
if (auto output = findOutput(connector->id())) {
|
||||
removeOutput(output);
|
||||
} else if (auto leaseOutput = findLeaseOutput(connector->id())) {
|
||||
removeLeaseOutput(leaseOutput);
|
||||
}
|
||||
m_connectors.removeOne(connector);
|
||||
delete connector;
|
||||
}
|
||||
|
||||
// update crtc properties
|
||||
for (const auto &crtc : qAsConst(m_crtcs)) {
|
||||
|
@ -545,6 +538,7 @@ void DrmGpu::removeOutput(DrmOutput *output)
|
|||
{
|
||||
qCDebug(KWIN_DRM) << "Removing output" << output;
|
||||
m_drmOutputs.removeOne(output);
|
||||
m_pipelines.removeOne(output->pipeline());
|
||||
m_outputs.removeOne(output);
|
||||
Q_EMIT outputRemoved(output);
|
||||
delete output;
|
||||
|
@ -666,6 +660,7 @@ void DrmGpu::removeLeaseOutput(DrmLeaseOutput *output)
|
|||
{
|
||||
qCDebug(KWIN_DRM) << "Removing leased output" << output;
|
||||
m_leaseOutputs.removeOne(output);
|
||||
m_pipelines.removeOne(output->pipeline());
|
||||
delete output;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,66 +78,7 @@ quint64 refreshRateForMode(_drmModeModeInfo *m)
|
|||
|
||||
bool DrmConnector::init()
|
||||
{
|
||||
if (!m_conn || !m_conn->count_modes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!initProps()) {
|
||||
return false;
|
||||
}
|
||||
if (const auto &dpms = getProp(PropertyIndex::Dpms)) {
|
||||
dpms->setLegacy();
|
||||
}
|
||||
|
||||
auto underscan = m_props[static_cast<uint32_t>(PropertyIndex::Underscan)];
|
||||
auto vborder = m_props[static_cast<uint32_t>(PropertyIndex::Underscan_vborder)];
|
||||
auto hborder = m_props[static_cast<uint32_t>(PropertyIndex::Underscan_hborder)];
|
||||
if (underscan && vborder && hborder) {
|
||||
underscan->setEnum(vborder->current() > 0 ? UnderscanOptions::On : UnderscanOptions::Off);
|
||||
} else {
|
||||
deleteProp(PropertyIndex::Underscan);
|
||||
deleteProp(PropertyIndex::Underscan_vborder);
|
||||
deleteProp(PropertyIndex::Underscan_hborder);
|
||||
}
|
||||
|
||||
// parse edid
|
||||
auto edidProp = getProp(PropertyIndex::Edid);
|
||||
if (edidProp) {
|
||||
DrmScopedPointer<drmModePropertyBlobRes> blob(drmModeGetPropertyBlob(gpu()->fd(), edidProp->current()));
|
||||
if (blob && blob->data) {
|
||||
m_edid = Edid(blob->data, blob->length);
|
||||
if (!m_edid.isValid()) {
|
||||
qCWarning(KWIN_DRM) << "Couldn't parse EDID for connector" << this;
|
||||
}
|
||||
}
|
||||
deleteProp(PropertyIndex::Edid);
|
||||
} else {
|
||||
qCDebug(KWIN_DRM) << "Could not find edid for connector" << this;
|
||||
}
|
||||
|
||||
// check the physical size
|
||||
if (m_edid.physicalSize().isEmpty()) {
|
||||
m_physicalSize = QSize(m_conn->mmWidth, m_conn->mmHeight);
|
||||
} else {
|
||||
m_physicalSize = m_edid.physicalSize();
|
||||
}
|
||||
|
||||
// the size might be completely borked. E.g. Samsung SyncMaster 2494HS reports 160x90 while in truth it's 520x292
|
||||
// as this information is used to calculate DPI info, it's going to result in everything being huge
|
||||
const QByteArray unknown = QByteArrayLiteral("unknown");
|
||||
KConfigGroup group = kwinApp()->config()->group("EdidOverwrite").group(m_edid.eisaId().isEmpty() ? unknown : m_edid.eisaId())
|
||||
.group(m_edid.monitorName().isEmpty() ? unknown : m_edid.monitorName())
|
||||
.group(m_edid.serialNumber().isEmpty() ? unknown : m_edid.serialNumber());
|
||||
if (group.hasKey("PhysicalSize")) {
|
||||
const QSize overwriteSize = group.readEntry("PhysicalSize", m_physicalSize);
|
||||
qCWarning(KWIN_DRM) << "Overwriting monitor physical size for" << m_edid.eisaId() << "/" << m_edid.monitorName() << "/" << m_edid.serialNumber() << " from " << m_physicalSize << "to " << overwriteSize;
|
||||
m_physicalSize = overwriteSize;
|
||||
}
|
||||
|
||||
// init modes
|
||||
updateModes();
|
||||
|
||||
return true;
|
||||
return m_conn && initProps();
|
||||
}
|
||||
|
||||
bool DrmConnector::isConnected() const
|
||||
|
@ -349,7 +290,62 @@ bool DrmConnector::updateProperties()
|
|||
return false;
|
||||
}
|
||||
m_conn.reset(drmModeGetConnector(gpu()->fd(), id()));
|
||||
return m_conn != nullptr;
|
||||
if (!m_conn) {
|
||||
return false;
|
||||
}
|
||||
if (const auto &dpms = getProp(PropertyIndex::Dpms)) {
|
||||
dpms->setLegacy();
|
||||
}
|
||||
|
||||
auto underscan = m_props[static_cast<uint32_t>(PropertyIndex::Underscan)];
|
||||
auto vborder = m_props[static_cast<uint32_t>(PropertyIndex::Underscan_vborder)];
|
||||
auto hborder = m_props[static_cast<uint32_t>(PropertyIndex::Underscan_hborder)];
|
||||
if (underscan && vborder && hborder) {
|
||||
underscan->setEnum(vborder->current() > 0 ? UnderscanOptions::On : UnderscanOptions::Off);
|
||||
} else {
|
||||
deleteProp(PropertyIndex::Underscan);
|
||||
deleteProp(PropertyIndex::Underscan_vborder);
|
||||
deleteProp(PropertyIndex::Underscan_hborder);
|
||||
}
|
||||
|
||||
// parse edid
|
||||
auto edidProp = getProp(PropertyIndex::Edid);
|
||||
if (edidProp) {
|
||||
DrmScopedPointer<drmModePropertyBlobRes> blob(drmModeGetPropertyBlob(gpu()->fd(), edidProp->current()));
|
||||
if (blob && blob->data) {
|
||||
m_edid = Edid(blob->data, blob->length);
|
||||
if (!m_edid.isValid()) {
|
||||
qCWarning(KWIN_DRM) << "Couldn't parse EDID for connector" << this;
|
||||
}
|
||||
}
|
||||
deleteProp(PropertyIndex::Edid);
|
||||
} else {
|
||||
qCDebug(KWIN_DRM) << "Could not find edid for connector" << this;
|
||||
}
|
||||
|
||||
// check the physical size
|
||||
if (m_edid.physicalSize().isEmpty()) {
|
||||
m_physicalSize = QSize(m_conn->mmWidth, m_conn->mmHeight);
|
||||
} else {
|
||||
m_physicalSize = m_edid.physicalSize();
|
||||
}
|
||||
|
||||
// the size might be completely borked. E.g. Samsung SyncMaster 2494HS reports 160x90 while in truth it's 520x292
|
||||
// as this information is used to calculate DPI info, it's going to result in everything being huge
|
||||
const QByteArray unknown = QByteArrayLiteral("unknown");
|
||||
KConfigGroup group = kwinApp()->config()->group("EdidOverwrite").group(m_edid.eisaId().isEmpty() ? unknown : m_edid.eisaId())
|
||||
.group(m_edid.monitorName().isEmpty() ? unknown : m_edid.monitorName())
|
||||
.group(m_edid.serialNumber().isEmpty() ? unknown : m_edid.serialNumber());
|
||||
if (group.hasKey("PhysicalSize")) {
|
||||
const QSize overwriteSize = group.readEntry("PhysicalSize", m_physicalSize);
|
||||
qCWarning(KWIN_DRM) << "Overwriting monitor physical size for" << m_edid.eisaId() << "/" << m_edid.monitorName() << "/" << m_edid.serialNumber() << " from " << m_physicalSize << "to " << overwriteSize;
|
||||
m_physicalSize = overwriteSize;
|
||||
}
|
||||
|
||||
// init modes
|
||||
updateModes();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QVector<uint32_t> DrmConnector::encoders() const
|
||||
|
|
|
@ -80,7 +80,7 @@ bool DrmOutput::initCursor(const QSize &cursorSize)
|
|||
|
||||
bool DrmOutput::hideCursor()
|
||||
{
|
||||
if (!isEnabled()) {
|
||||
if (!isEnabled() || !m_connector->isConnected()) {
|
||||
return true;
|
||||
}
|
||||
bool visibleBefore = m_pipeline->isCursorVisible();
|
||||
|
@ -97,7 +97,7 @@ bool DrmOutput::hideCursor()
|
|||
|
||||
bool DrmOutput::showCursor()
|
||||
{
|
||||
if (!isEnabled()) {
|
||||
if (!isEnabled() || !m_connector->isConnected()) {
|
||||
return true;
|
||||
}
|
||||
bool visibleBefore = m_pipeline->isCursorVisible();
|
||||
|
@ -126,7 +126,7 @@ static bool isCursorSpriteCompatible(const QImage *buffer, const QImage *sprite)
|
|||
|
||||
bool DrmOutput::updateCursor()
|
||||
{
|
||||
if (!isEnabled()) {
|
||||
if (!isEnabled() || !m_connector->isConnected()) {
|
||||
return true;
|
||||
}
|
||||
const Cursor *cursor = Cursors::self()->currentCursor();
|
||||
|
@ -164,7 +164,7 @@ bool DrmOutput::updateCursor()
|
|||
|
||||
bool DrmOutput::moveCursor()
|
||||
{
|
||||
if (!isEnabled()) {
|
||||
if (!isEnabled() || !m_connector->isConnected()) {
|
||||
return true;
|
||||
}
|
||||
Cursor *cursor = Cursors::self()->currentCursor();
|
||||
|
@ -457,6 +457,9 @@ bool DrmOutput::queueChanges(const WaylandOutputConfig &config)
|
|||
|
||||
void DrmOutput::applyQueuedChanges(const WaylandOutputConfig &config)
|
||||
{
|
||||
if (!m_connector->isConnected()) {
|
||||
return;
|
||||
}
|
||||
Q_EMIT aboutToChange();
|
||||
m_pipeline->applyPendingChanges();
|
||||
|
||||
|
|
Loading…
Reference in a new issue