[platforms/drm] If mapping a DrmBuffer for a cursor fails, fallback to software cursor

Summary:
So far the drm platform did not verify whether creating and mapping a
DrmBuffer for a cursor works. This could result in a crash in the worst
case.

This change verfies whether mapping the two cursor buffers works, if
not software cursor is enabled. The code is adjusted to ensure that
none of the cursor buffers is accessed in case software cursor are
enabled.

Please note that right now the drm platform's rendering does not
support software cursors. Thus currently this change results in no
cursor at all. This will be addressed by following patches.

BUG: 364740
FIXED-IN: 5.7

Test Plan:
Verfied that it properly falls back to software cursor,
but could not verify that the crash is actually fixed.

Reviewers: #kwin, #plasma_on_wayland

Subscribers: plasma-devel, kwin

Tags: #plasma_on_wayland, #kwin

Differential Revision: https://phabricator.kde.org/D2026
This commit is contained in:
Martin Gräßlin 2016-06-28 10:20:27 +02:00
parent feadcea6ce
commit 7ea84cd346

View file

@ -152,14 +152,16 @@ void DrmBackend::reactivate()
return;
}
m_active = true;
DrmBuffer *c = m_cursor[(m_cursorIndex + 1) % 2];
const QPoint cp = Cursor::pos() - softwareCursorHotspot();
for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) {
DrmOutput *o = *it;
o->pageFlipped();
o->blank();
o->showCursor(c);
o->moveCursor(cp);
if (!usesSoftwareCursor()) {
DrmBuffer *c = m_cursor[(m_cursorIndex + 1) % 2];
const QPoint cp = Cursor::pos() - softwareCursorHotspot();
for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) {
DrmOutput *o = *it;
o->pageFlipped();
o->blank();
o->showCursor(c);
o->moveCursor(cp);
}
}
// restart compositor
m_pageFlipsPending = 0;
@ -473,6 +475,9 @@ void DrmBackend::initCursor()
connect(waylandServer()->seat(), &KWayland::Server::SeatInterface::hasPointerChanged, this,
[this] {
m_cursorEnabled = waylandServer()->seat()->hasPointer();
if (usesSoftwareCursor()) {
return;
}
for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) {
if (m_cursorEnabled) {
(*it)->showCursor(m_cursor[m_cursorIndex]);
@ -494,12 +499,18 @@ void DrmBackend::initCursor()
} else {
cursorSize.setHeight(64);
}
m_cursor[0] = createBuffer(cursorSize);
m_cursor[0]->map(QImage::Format_ARGB32_Premultiplied);
m_cursor[0]->image()->fill(Qt::transparent);
m_cursor[1] = createBuffer(cursorSize);
m_cursor[1]->map(QImage::Format_ARGB32_Premultiplied);
m_cursor[1]->image()->fill(Qt::transparent);
auto createCursor = [this, cursorSize] (int index) {
m_cursor[index] = createBuffer(cursorSize);
if (!m_cursor[index]->map(QImage::Format_ARGB32_Premultiplied)) {
return false;
}
m_cursor[index]->image()->fill(Qt::transparent);
return true;
};
if (!createCursor(0) || !createCursor(1)) {
setSoftWareCursor(true);
return;
}
// now we have screens and can set cursors, so start tracking
connect(this, &DrmBackend::cursorChanged, this, &DrmBackend::updateCursor);
connect(Cursor::self(), &Cursor::posChanged, this, &DrmBackend::moveCursor);
@ -519,6 +530,9 @@ void DrmBackend::setCursor()
void DrmBackend::updateCursor()
{
if (usesSoftwareCursor()) {
return;
}
const QImage &cursorImage = softwareCursor();
if (cursorImage.isNull()) {
hideCursor();