[platforms/drm] Properly handle case that mapping the blank buffer fails

Summary:
If it's not possible to create a buffer to blank the output, KWin won't
be able to render to the output. In that case the output should not be
added to the list of outputs.

To support this DrmOutput::blank and DrmOutput::init return bool to
indicate whether they succeeded. DrmBackend handles this situation and
doesn't add the output to the list of outputs if init failed.

If after init there are no outputs KWin is in a state where it won't
be functional. Thus the platform emits the initFailed signal to
terminate.

BUG: 365242
FIXED-IN: 5.7.2

Test Plan: No hardware to reproduce the condition

Reviewers: #kwin, #plasma_on_wayland

Subscribers: plasma-devel, kwin

Tags: #plasma_on_wayland, #kwin

Differential Revision: https://phabricator.kde.org/D2135
icc-effect-5.14.5
Martin Gräßlin 2016-07-11 11:26:03 +02:00
parent aaf8ce16df
commit cd9a0afafa
3 changed files with 26 additions and 9 deletions

View File

@ -237,6 +237,11 @@ void DrmBackend::openDrm()
);
m_drmId = device->sysNum();
queryResources();
if (m_outputs.isEmpty()) {
qCWarning(KWIN_DRM) << "No outputs, cannot render, will terminate now";
emit initFailed();
return;
}
// setup udevMonitor
if (m_udevMonitor) {
@ -315,7 +320,11 @@ void DrmBackend::queryResources()
drmOutput->m_mode = connector->modes[0];
}
drmOutput->m_connector = connector->connector_id;
drmOutput->init(connector.data());
if (!drmOutput->init(connector.data())) {
qCWarning(KWIN_DRM) << "Failed to create output for connector " << connector->connector_id;
delete drmOutput;
continue;
}
qCDebug(KWIN_DRM) << "Found new output with uuid" << drmOutput->uuid();
connectedOutputs << drmOutput;
}
@ -339,7 +348,9 @@ void DrmBackend::queryResources()
}
m_outputs = connectedOutputs;
readOutputsConfiguration();
emit screensQueried();
if (!m_outputs.isEmpty()) {
emit screensQueried();
}
}
void DrmBackend::readOutputsConfiguration()

View File

@ -180,13 +180,15 @@ static DrmOutput::DpmsMode fromWaylandDpmsMode(KWayland::Server::OutputInterface
}
}
void DrmOutput::init(drmModeConnector *connector)
bool DrmOutput::init(drmModeConnector *connector)
{
initEdid(connector);
initDpms(connector);
initUuid();
m_savedCrtc.reset(drmModeGetCrtc(m_backend->fd(), m_crtcId));
blank();
if (!blank()) {
return false;
}
setDpms(DpmsMode::On);
if (!m_waylandOutput.isNull()) {
delete m_waylandOutput.data();
@ -287,6 +289,7 @@ void DrmOutput::init(drmModeConnector *connector)
m_waylandOutput->create();
qCDebug(KWIN_DRM) << "Created OutputDevice";
m_waylandOutputDevice->create();
return true;
}
void DrmOutput::initUuid()
@ -318,14 +321,17 @@ bool DrmOutput::isCurrentMode(const drmModeModeInfo *mode) const
&& qstrcmp(mode->name, m_mode.name) == 0;
}
void DrmOutput::blank()
bool DrmOutput::blank()
{
if (!m_blackBuffer) {
m_blackBuffer = m_backend->createBuffer(size());
m_blackBuffer->map();
if (!m_blackBuffer->map()) {
cleanupBlackBuffer();
return false;
}
m_blackBuffer->image()->fill(Qt::black);
}
setMode(m_blackBuffer);
return setMode(m_blackBuffer);
}
bool DrmOutput::setMode(DrmBuffer *buffer)

View File

@ -61,9 +61,9 @@ public:
void moveCursor(const QPoint &globalPos);
bool present(DrmBuffer *buffer);
void pageFlipped();
void init(drmModeConnector *connector);
bool init(drmModeConnector *connector);
void restoreSaved();
void blank();
bool blank();
/**
* This sets the changes and tests them against the DRM output