diff --git a/wayland_backend.cpp b/wayland_backend.cpp index 9b8734fa3b..0588ffc1fe 100644 --- a/wayland_backend.cpp +++ b/wayland_backend.cpp @@ -232,7 +232,7 @@ void X11CursorTracker::cursorChanged(uint32_t serial) return; } ShmPool *pool = m_backend->shmPool(); - if (!pool) { + if (!pool->isValid()) { return; } CursorData cursor; @@ -408,7 +408,7 @@ WaylandBackend::WaylandBackend(QObject *parent) , m_surface(new Surface(this)) , m_shellSurface(NULL) , m_seat() - , m_shm() + , m_shm(new ShmPool(this)) , m_connectionThreadObject(nullptr) , m_connectionThread(nullptr) , m_fullscreenShell(new FullscreenShell(this)) @@ -440,7 +440,11 @@ WaylandBackend::WaylandBackend(QObject *parent) } ); connect(m_registry, &Registry::seatAnnounced, this, &WaylandBackend::createSeat); - connect(m_registry, &Registry::shmAnnounced, this, &WaylandBackend::createShm); + connect(m_registry, &Registry::shmAnnounced, this, + [this](quint32 name) { + m_shm->setup(m_registry->bindShm(name, 1)); + } + ); connect(m_registry, &Registry::fullscreenShellAnnounced, this, [this](quint32 name, quint32 version) { m_fullscreenShell->setup(m_registry->bindFullscreenShell(name, version)); @@ -464,7 +468,7 @@ WaylandBackend::~WaylandBackend() } m_registry->release(); m_seat.reset(); - m_shm.reset(); + m_shm->release(); m_connectionThreadObject->deleteLater(); m_connectionThread->quit(); @@ -507,7 +511,7 @@ void WaylandBackend::initConnection() [this]() { emit systemCompositorDied(); m_seat.reset(); - m_shm.reset(); + m_shm->destroy(); destroyOutputs(); if (m_shellSurface) { m_shellSurface->destroy(); @@ -586,14 +590,6 @@ void WaylandBackend::createSurface() } } -void WaylandBackend::createShm(uint32_t name) -{ - m_shm.reset(new ShmPool(m_registry->bindShm(name, 1))); - if (!m_shm->isValid()) { - m_shm.reset(); - } -} - void WaylandBackend::addOutput(wl_output *o) { Output *output = new Output(this); diff --git a/wayland_backend.h b/wayland_backend.h index ba43cb066a..f9b9a3fdb1 100644 --- a/wayland_backend.h +++ b/wayland_backend.h @@ -134,7 +134,6 @@ public: const QList &outputs() const; ShmPool *shmPool(); void createSeat(uint32_t name); - void createShm(uint32_t name); Surface *surface() const; QSize shellSurfaceSize() const; @@ -158,7 +157,7 @@ private: Surface *m_surface; ShellSurface *m_shellSurface; QScopedPointer m_seat; - QScopedPointer m_shm; + ShmPool *m_shm; QList m_outputs; ConnectionThread *m_connectionThreadObject; QThread *m_connectionThread; @@ -212,7 +211,7 @@ wl_compositor *WaylandBackend::compositor() inline ShmPool* WaylandBackend::shmPool() { - return m_shm.data(); + return m_shm; } inline diff --git a/wayland_client/shm_pool.cpp b/wayland_client/shm_pool.cpp index a08f7b7b29..dccdc24c92 100644 --- a/wayland_client/shm_pool.cpp +++ b/wayland_client/shm_pool.cpp @@ -32,30 +32,71 @@ namespace KWin namespace Wayland { -ShmPool::ShmPool(wl_shm *shm) - : m_shm(shm) +ShmPool::ShmPool(QObject *parent) + : QObject(parent) + , m_shm(nullptr) , m_pool(nullptr) , m_poolData(nullptr) , m_size(1024) , m_tmpFile(new QTemporaryFile()) - , m_valid(createPool()) + , m_valid(false) , m_offset(0) { } ShmPool::~ShmPool() +{ + release(); +} + +void ShmPool::release() { qDeleteAll(m_buffers); + m_buffers.clear(); if (m_poolData) { munmap(m_poolData, m_size); + m_poolData = nullptr; } if (m_pool) { wl_shm_pool_destroy(m_pool); + m_pool = nullptr; } if (m_shm) { wl_shm_destroy(m_shm); + m_shm = nullptr; } m_tmpFile->close(); + m_valid = false; + m_offset = 0; +} + +void ShmPool::destroy() +{ + qDeleteAll(m_buffers); + m_buffers.clear(); + if (m_poolData) { + munmap(m_poolData, m_size); + m_poolData = nullptr; + } + if (m_pool) { + free(m_pool); + m_pool = nullptr; + } + if (m_shm) { + free(m_shm); + m_shm = nullptr; + } + m_tmpFile->close(); + m_valid = false; + m_offset = 0; +} + +void ShmPool::setup(wl_shm *shm) +{ + Q_ASSERT(shm); + Q_ASSERT(!m_shm); + m_shm = shm; + m_valid = createPool(); } bool ShmPool::createPool() diff --git a/wayland_client/shm_pool.h b/wayland_client/shm_pool.h index 9b1c8ff314..e0319ec22f 100644 --- a/wayland_client/shm_pool.h +++ b/wayland_client/shm_pool.h @@ -40,9 +40,13 @@ class ShmPool : public QObject { Q_OBJECT public: - ShmPool(wl_shm *shm); - ~ShmPool(); + explicit ShmPool(QObject *parent = nullptr); + virtual ~ShmPool(); bool isValid() const; + void setup(wl_shm *shm); + void release(); + void destroy(); + wl_buffer *createBuffer(const QImage &image); wl_buffer *createBuffer(const QSize &size, int32_t stride, const void *src); void *poolAddress() const;