From 7ea84cd346424161affbfddf653b16b6f90442f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Tue, 28 Jun 2016 10:20:27 +0200 Subject: [PATCH] [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 --- plugins/platforms/drm/drm_backend.cpp | 42 ++++++++++++++++++--------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/plugins/platforms/drm/drm_backend.cpp b/plugins/platforms/drm/drm_backend.cpp index 2467cce3dd..c15f3f4f44 100644 --- a/plugins/platforms/drm/drm_backend.cpp +++ b/plugins/platforms/drm/drm_backend.cpp @@ -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();