Dmabuf recovery on EGL reset

Summary:
The EGL platform might go away at any time through reconfiguration or because
of a graphic error. KWin then resets the graphics. The dmabuf implementation
must respect that and recover from a graphics reset by recreating all EGL
images for existing buffer.

This assumes that we won't change our graphics API mid-session and that
supported plane and modifier configuration stays constant.

In practise we remember all current dmabufs in a single map and only remove
them if the client did destroy the resource.

BUG: 411980
CCBUG: 413403
FIXED-IN: 5.17.2

Test Plan: Applied screenedge configuration without crash.

Reviewers: #kwin, zzag

Reviewed By: #kwin, zzag

Subscribers: fvogt, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D24954
This commit is contained in:
Roman Gilg 2019-10-26 05:40:01 +02:00
parent a151edd29b
commit 7459aabcac
9 changed files with 270 additions and 100 deletions

View file

@ -441,6 +441,7 @@ set(kwin_KDEINIT_SRCS
libinput/device.cpp libinput/device.cpp
libinput/events.cpp libinput/events.cpp
libinput/libinput_logging.cpp libinput/libinput_logging.cpp
linux_dmabuf.cpp
logind.cpp logind.cpp
main.cpp main.cpp
manage.cpp manage.cpp

88
linux_dmabuf.cpp Normal file
View file

@ -0,0 +1,88 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright © 2019 Roman Gilg <subdiff@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "linux_dmabuf.h"
#include "wayland_server.h"
#include <unistd.h>
namespace KWin
{
DmabufBuffer::DmabufBuffer(const QVector<Plane> &planes,
uint32_t format,
const QSize &size,
Flags flags)
: KWayland::Server::LinuxDmabufUnstableV1Buffer(format, size)
, m_planes(planes)
, m_format(format)
, m_size(size)
, m_flags(flags)
{
waylandServer()->addLinuxDmabufBuffer(this);
}
DmabufBuffer::~DmabufBuffer()
{
// Close all open file descriptors
for (int i = 0; i < m_planes.count(); i++) {
if (m_planes[i].fd != -1)
::close(m_planes[i].fd);
m_planes[i].fd = -1;
}
if (waylandServer()) {
waylandServer()->removeLinuxDmabufBuffer(this);
}
}
LinuxDmabuf::LinuxDmabuf()
: KWayland::Server::LinuxDmabufUnstableV1Interface::Impl()
{
Q_ASSERT(waylandServer());
waylandServer()->linuxDmabuf()->setImpl(this);
}
LinuxDmabuf::~LinuxDmabuf()
{
waylandServer()->linuxDmabuf()->setImpl(nullptr);
}
using Plane = KWayland::Server::LinuxDmabufUnstableV1Interface::Plane;
using Flags = KWayland::Server::LinuxDmabufUnstableV1Interface::Flags;
KWayland::Server::LinuxDmabufUnstableV1Buffer* LinuxDmabuf::importBuffer(const QVector<Plane> &planes,
uint32_t format,
const QSize &size,
Flags flags)
{
Q_UNUSED(planes)
Q_UNUSED(format)
Q_UNUSED(size)
Q_UNUSED(flags)
return nullptr;
}
void LinuxDmabuf::setSupportedFormatsAndModifiers(QHash<uint32_t, QSet<uint64_t> > &set)
{
waylandServer()->linuxDmabuf()->setSupportedFormatsWithModifiers(set);
}
}

74
linux_dmabuf.h Normal file
View file

@ -0,0 +1,74 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright © 2019 Roman Gilg <subdiff@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#pragma once
#include <kwin_export.h>
#include <KWayland/Server/linuxdmabuf_v1_interface.h>
#include <QVector>
namespace KWin
{
class KWIN_EXPORT DmabufBuffer : public KWayland::Server::LinuxDmabufUnstableV1Buffer
{
public:
using Plane = KWayland::Server::LinuxDmabufUnstableV1Interface::Plane;
using Flags = KWayland::Server::LinuxDmabufUnstableV1Interface::Flags;
DmabufBuffer(const QVector<Plane> &planes,
uint32_t format,
const QSize &size,
Flags flags);
~DmabufBuffer() override;
const QVector<Plane> &planes() const { return m_planes; }
uint32_t format() const { return m_format; }
QSize size() const { return m_size; }
Flags flags() const { return m_flags; }
private:
QVector<Plane> m_planes;
uint32_t m_format;
QSize m_size;
Flags m_flags;
};
class KWIN_EXPORT LinuxDmabuf : public KWayland::Server::LinuxDmabufUnstableV1Interface::Impl
{
public:
using Plane = KWayland::Server::LinuxDmabufUnstableV1Interface::Plane;
using Flags = KWayland::Server::LinuxDmabufUnstableV1Interface::Flags;
explicit LinuxDmabuf();
~LinuxDmabuf();
KWayland::Server::LinuxDmabufUnstableV1Buffer *importBuffer(const QVector<Plane> &planes,
uint32_t format,
const QSize &size,
Flags flags) override;
protected:
void setSupportedFormatsAndModifiers(QHash<uint32_t, QSet<uint64_t> > &set);
};
}

View file

@ -1,7 +1,7 @@
set(SCENE_OPENGL_BACKEND_SRCS set(SCENE_OPENGL_BACKEND_SRCS
abstract_egl_backend.cpp abstract_egl_backend.cpp
backend.cpp backend.cpp
linux_dmabuf.cpp egl_dmabuf.cpp
swap_profiler.cpp swap_profiler.cpp
texture.cpp texture.cpp
) )

View file

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/ *********************************************************************/
#include "abstract_egl_backend.h" #include "abstract_egl_backend.h"
#include "linux_dmabuf.h" #include "egl_dmabuf.h"
#include "texture.h" #include "texture.h"
#include "composite.h" #include "composite.h"
#include "egl_context_attribute_builder.h" #include "egl_context_attribute_builder.h"
@ -171,7 +171,7 @@ void AbstractEglBackend::initWayland()
} }
} }
LinuxDmabuf::factory(this); EglDmabuf::factory(this);
} }
void AbstractEglBackend::initClientExtensions() void AbstractEglBackend::initClientExtensions()
@ -377,7 +377,7 @@ void AbstractEglTexture::updateTexture(WindowPixmap *pixmap)
return; return;
} }
auto s = pixmap->surface(); auto s = pixmap->surface();
if (DmabufBuffer *dmabuf = static_cast<DmabufBuffer *>(buffer->linuxDmabufBuffer())) { if (EglDmabufBuffer *dmabuf = static_cast<EglDmabufBuffer *>(buffer->linuxDmabufBuffer())) {
q->bind(); q->bind();
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES) dmabuf->images()[0]); //TODO glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES) dmabuf->images()[0]); //TODO
q->unbind(); q->unbind();
@ -532,7 +532,7 @@ bool AbstractEglTexture::loadEglTexture(const QPointer< KWayland::Server::Buffer
bool AbstractEglTexture::loadDmabufTexture(const QPointer< KWayland::Server::BufferInterface > &buffer) bool AbstractEglTexture::loadDmabufTexture(const QPointer< KWayland::Server::BufferInterface > &buffer)
{ {
DmabufBuffer *dmabuf = static_cast<DmabufBuffer *>(buffer->linuxDmabufBuffer()); auto *dmabuf = static_cast<EglDmabufBuffer *>(buffer->linuxDmabufBuffer());
if (!dmabuf || dmabuf->images()[0] == EGL_NO_IMAGE_KHR) { if (!dmabuf || dmabuf->images()[0] == EGL_NO_IMAGE_KHR) {
qCritical(KWIN_OPENGL) << "Invalid dmabuf-based wl_buffer"; qCritical(KWIN_OPENGL) << "Invalid dmabuf-based wl_buffer";
q->discard(); q->discard();

View file

@ -18,13 +18,11 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/ *********************************************************************/
#include "linux_dmabuf.h" #include "egl_dmabuf.h"
#include "drm_fourcc.h" #include "drm_fourcc.h"
#include "../../../wayland_server.h" #include "../../../wayland_server.h"
#include <KWayland/Server/display.h>
#include <unistd.h> #include <unistd.h>
#include <EGL/eglmesaext.h> #include <EGL/eglmesaext.h>
@ -173,67 +171,59 @@ YuvFormat yuvFormats[] = {
} }
}; };
DmabufBuffer::DmabufBuffer(EGLImage image, EglDmabufBuffer::EglDmabufBuffer(EGLImage image,
const QVector<Plane> &planes, const QVector<Plane> &planes,
uint32_t format, uint32_t format,
const QSize &size, const QSize &size,
Flags flags, Flags flags,
LinuxDmabuf *interfaceImpl) EglDmabuf *interfaceImpl)
: DmabufBuffer(planes, format, size, flags, interfaceImpl) : EglDmabufBuffer(planes, format, size, flags, interfaceImpl)
{ {
m_importType = ImportType::Direct; m_importType = ImportType::Direct;
addImage(image); addImage(image);
} }
DmabufBuffer::DmabufBuffer(const QVector<Plane> &planes, EglDmabufBuffer::EglDmabufBuffer(const QVector<Plane> &planes,
uint32_t format, uint32_t format,
const QSize &size, const QSize &size,
Flags flags, Flags flags,
LinuxDmabuf *interfaceImpl) EglDmabuf *interfaceImpl)
: KWayland::Server::LinuxDmabufUnstableV1Buffer(format, size) : DmabufBuffer(planes, format, size, flags)
, m_planes(planes)
, m_flags(flags)
, m_interfaceImpl(interfaceImpl) , m_interfaceImpl(interfaceImpl)
{ {
m_importType = ImportType::Conversion; m_importType = ImportType::Conversion;
} }
DmabufBuffer::~DmabufBuffer() EglDmabufBuffer::~EglDmabufBuffer()
{ {
if (m_interfaceImpl) { removeImages();
m_interfaceImpl->removeBuffer(this);
removeImages();
}
// Close all open file descriptors
for (int i = 0; i < m_planes.count(); i++) {
if (m_planes[i].fd != -1)
::close(m_planes[i].fd);
m_planes[i].fd = -1;
}
} }
void DmabufBuffer::addImage(EGLImage image) void EglDmabufBuffer::setInterfaceImplementation(EglDmabuf *interfaceImpl)
{
m_interfaceImpl = interfaceImpl;
}
void EglDmabufBuffer::addImage(EGLImage image)
{ {
m_images << image; m_images << image;
} }
void DmabufBuffer::removeImages() void EglDmabufBuffer::removeImages()
{ {
for (auto image : m_images) { for (auto image : m_images) {
eglDestroyImageKHR(m_interfaceImpl->m_backend->eglDisplay(), image); eglDestroyImageKHR(m_interfaceImpl->m_backend->eglDisplay(), image);
} }
m_images.clear(); m_images.clear();
m_interfaceImpl = nullptr;
} }
using Plane = KWayland::Server::LinuxDmabufUnstableV1Interface::Plane; using Plane = KWayland::Server::LinuxDmabufUnstableV1Interface::Plane;
using Flags = KWayland::Server::LinuxDmabufUnstableV1Interface::Flags; using Flags = KWayland::Server::LinuxDmabufUnstableV1Interface::Flags;
EGLImage LinuxDmabuf::createImage(const QVector<Plane> &planes, EGLImage EglDmabuf::createImage(const QVector<Plane> &planes,
uint32_t format, uint32_t format,
const QSize &size) const QSize &size)
{ {
const bool hasModifiers = eglQueryDmaBufModifiersEXT != nullptr && const bool hasModifiers = eglQueryDmaBufModifiersEXT != nullptr &&
planes[0].modifier != DRM_FORMAT_MOD_INVALID; planes[0].modifier != DRM_FORMAT_MOD_INVALID;
@ -306,16 +296,16 @@ EGLImage LinuxDmabuf::createImage(const QVector<Plane> &planes,
return image; return image;
} }
KWayland::Server::LinuxDmabufUnstableV1Buffer* LinuxDmabuf::importBuffer(const QVector<Plane> &planes, KWayland::Server::LinuxDmabufUnstableV1Buffer* EglDmabuf::importBuffer(const QVector<Plane> &planes,
uint32_t format, uint32_t format,
const QSize &size, const QSize &size,
Flags flags) Flags flags)
{ {
Q_ASSERT(planes.count() > 0); Q_ASSERT(planes.count() > 0);
// Try first to import as a single image // Try first to import as a single image
if (auto *img = createImage(planes, format, size)) { if (auto *img = createImage(planes, format, size)) {
return new DmabufBuffer(img, planes, format, size, flags, this); return new EglDmabufBuffer(img, planes, format, size, flags, this);
} }
// TODO: to enable this we must be able to store multiple textures per window pixmap // TODO: to enable this we must be able to store multiple textures per window pixmap
@ -326,10 +316,10 @@ KWayland::Server::LinuxDmabufUnstableV1Buffer* LinuxDmabuf::importBuffer(const Q
return nullptr; return nullptr;
} }
KWayland::Server::LinuxDmabufUnstableV1Buffer* LinuxDmabuf::yuvImport(const QVector<Plane> &planes, KWayland::Server::LinuxDmabufUnstableV1Buffer* EglDmabuf::yuvImport(const QVector<Plane> &planes,
uint32_t format, uint32_t format,
const QSize &size, const QSize &size,
Flags flags) Flags flags)
{ {
YuvFormat yuvFormat; YuvFormat yuvFormat;
for (YuvFormat f : yuvFormats) { for (YuvFormat f : yuvFormats) {
@ -345,7 +335,7 @@ KWayland::Server::LinuxDmabufUnstableV1Buffer* LinuxDmabuf::yuvImport(const QVec
return nullptr; return nullptr;
} }
auto *buf = new DmabufBuffer(planes, format, size, flags, this); auto *buf = new EglDmabufBuffer(planes, format, size, flags, this);
for (int i = 0; i < yuvFormat.outputPlanes; i++) { for (int i = 0; i < yuvFormat.outputPlanes; i++) {
int planeIndex = yuvFormat.planes[i].planeIndex; int planeIndex = yuvFormat.planes[i].planeIndex;
@ -371,7 +361,7 @@ KWayland::Server::LinuxDmabufUnstableV1Buffer* LinuxDmabuf::yuvImport(const QVec
return buf; return buf;
} }
LinuxDmabuf* LinuxDmabuf::factory(AbstractEglBackend *backend) EglDmabuf* EglDmabuf::factory(AbstractEglBackend *backend)
{ {
if (!backend->hasExtension(QByteArrayLiteral("EGL_EXT_image_dma_buf_import"))) { if (!backend->hasExtension(QByteArrayLiteral("EGL_EXT_image_dma_buf_import"))) {
return nullptr; return nullptr;
@ -386,30 +376,29 @@ LinuxDmabuf* LinuxDmabuf::factory(AbstractEglBackend *backend)
return nullptr; return nullptr;
} }
return new LinuxDmabuf(backend); return new EglDmabuf(backend);
} }
LinuxDmabuf::LinuxDmabuf(AbstractEglBackend *backend) EglDmabuf::EglDmabuf(AbstractEglBackend *backend)
: KWayland::Server::LinuxDmabufUnstableV1Interface::Impl() : LinuxDmabuf()
, m_backend(backend) , m_backend(backend)
{ {
Q_ASSERT(waylandServer()); auto prevBuffersSet = waylandServer()->linuxDmabufBuffers();
m_interface = waylandServer()->display()->createLinuxDmabufInterface(backend); for (auto *buffer : prevBuffersSet) {
setSupportedFormatsAndModifiers(); auto *buf = static_cast<EglDmabufBuffer*>(buffer);
m_interface->setImpl(this); buf->setInterfaceImplementation(this);
m_interface->create(); buf->addImage(createImage(buf->planes(), buf->format(), buf->size()));
}
LinuxDmabuf::~LinuxDmabuf()
{
for (auto *dmabuf : qAsConst(m_buffers)) {
dmabuf->removeImages();
} }
setSupportedFormatsAndModifiers();
} }
void LinuxDmabuf::removeBuffer(DmabufBuffer *buffer) EglDmabuf::~EglDmabuf()
{ {
m_buffers.remove(buffer); auto curBuffers = waylandServer()->linuxDmabufBuffers();
for (auto *buffer : curBuffers) {
auto *buf = static_cast<EglDmabufBuffer*>(buffer);
buf->removeImages();
}
} }
const uint32_t s_multiPlaneFormats[] = { const uint32_t s_multiPlaneFormats[] = {
@ -457,7 +446,7 @@ void filterFormatsWithMultiplePlanes(QVector<uint32_t> &formats)
} }
} }
void LinuxDmabuf::setSupportedFormatsAndModifiers() void EglDmabuf::setSupportedFormatsAndModifiers()
{ {
const EGLDisplay eglDisplay = m_backend->eglDisplay(); const EGLDisplay eglDisplay = m_backend->eglDisplay();
EGLint count = 0; EGLint count = 0;
@ -498,7 +487,7 @@ void LinuxDmabuf::setSupportedFormatsAndModifiers()
set.insert(format, QSet<uint64_t>()); set.insert(format, QSet<uint64_t>());
} }
m_interface->setSupportedFormatsWithModifiers(set); LinuxDmabuf::setSupportedFormatsAndModifiers(set);
} }
} }

View file

@ -20,17 +20,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/ *********************************************************************/
#pragma once #pragma once
#include "abstract_egl_backend.h" #include "../../../linux_dmabuf.h"
#include <KWayland/Server/linuxdmabuf_v1_interface.h> #include "abstract_egl_backend.h"
#include <QVector> #include <QVector>
namespace KWin namespace KWin
{ {
class LinuxDmabuf; class EglDmabuf;
class DmabufBuffer : public KWayland::Server::LinuxDmabufUnstableV1Buffer class EglDmabufBuffer : public DmabufBuffer
{ {
public: public:
using Plane = KWayland::Server::LinuxDmabufUnstableV1Interface::Plane; using Plane = KWayland::Server::LinuxDmabufUnstableV1Interface::Plane;
@ -41,46 +41,43 @@ public:
Conversion Conversion
}; };
DmabufBuffer(EGLImage image, EglDmabufBuffer(EGLImage image,
const QVector<Plane> &planes, const QVector<Plane> &planes,
uint32_t format, uint32_t format,
const QSize &size, const QSize &size,
Flags flags, Flags flags,
LinuxDmabuf *interfaceImpl); EglDmabuf *interfaceImpl);
DmabufBuffer(const QVector<Plane> &planes, EglDmabufBuffer(const QVector<Plane> &planes,
uint32_t format, uint32_t format,
const QSize &size, const QSize &size,
Flags flags, Flags flags,
LinuxDmabuf *interfaceImpl); EglDmabuf *interfaceImpl);
~DmabufBuffer() override; ~EglDmabufBuffer() override;
void setInterfaceImplementation(EglDmabuf *interfaceImpl);
void addImage(EGLImage image); void addImage(EGLImage image);
void removeImages(); void removeImages();
QVector<EGLImage> images() const { return m_images; } QVector<EGLImage> images() const { return m_images; }
Flags flags() const { return m_flags; }
const QVector<Plane> &planes() const { return m_planes; }
private: private:
QVector<EGLImage> m_images; QVector<EGLImage> m_images;
QVector<Plane> m_planes; EglDmabuf *m_interfaceImpl;
Flags m_flags;
LinuxDmabuf *m_interfaceImpl;
ImportType m_importType; ImportType m_importType;
}; };
class LinuxDmabuf : public KWayland::Server::LinuxDmabufUnstableV1Interface::Impl class EglDmabuf : public LinuxDmabuf
{ {
public: public:
using Plane = KWayland::Server::LinuxDmabufUnstableV1Interface::Plane; using Plane = KWayland::Server::LinuxDmabufUnstableV1Interface::Plane;
using Flags = KWayland::Server::LinuxDmabufUnstableV1Interface::Flags; using Flags = KWayland::Server::LinuxDmabufUnstableV1Interface::Flags;
static LinuxDmabuf* factory(AbstractEglBackend *backend); static EglDmabuf* factory(AbstractEglBackend *backend);
explicit LinuxDmabuf(AbstractEglBackend *backend); explicit EglDmabuf(AbstractEglBackend *backend);
~LinuxDmabuf(); ~EglDmabuf();
KWayland::Server::LinuxDmabufUnstableV1Buffer *importBuffer(const QVector<Plane> &planes, KWayland::Server::LinuxDmabufUnstableV1Buffer *importBuffer(const QVector<Plane> &planes,
uint32_t format, uint32_t format,
@ -92,20 +89,16 @@ private:
uint32_t format, uint32_t format,
const QSize &size); const QSize &size);
KWayland::Server::LinuxDmabufUnstableV1Buffer *yuvImport(const QVector<Plane> &planes, KWayland::Server::LinuxDmabufUnstableV1Buffer *yuvImport(const QVector<Plane> &planes,
uint32_t format, uint32_t format,
const QSize &size, const QSize &size,
Flags flags); Flags flags);
void removeBuffer(DmabufBuffer *buffer);
void setSupportedFormatsAndModifiers(); void setSupportedFormatsAndModifiers();
KWayland::Server::LinuxDmabufUnstableV1Interface *m_interface;
QSet<DmabufBuffer*> m_buffers;
AbstractEglBackend *m_backend; AbstractEglBackend *m_backend;
friend class DmabufBuffer; friend class EglDmabufBuffer;
}; };
} }

View file

@ -45,6 +45,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <KWayland/Server/dpms_interface.h> #include <KWayland/Server/dpms_interface.h>
#include <KWayland/Server/idle_interface.h> #include <KWayland/Server/idle_interface.h>
#include <KWayland/Server/idleinhibit_interface.h> #include <KWayland/Server/idleinhibit_interface.h>
#include <KWayland/Server/linuxdmabuf_v1_interface.h>
#include <KWayland/Server/output_interface.h> #include <KWayland/Server/output_interface.h>
#include <KWayland/Server/plasmashell_interface.h> #include <KWayland/Server/plasmashell_interface.h>
#include <KWayland/Server/plasmavirtualdesktop_interface.h> #include <KWayland/Server/plasmavirtualdesktop_interface.h>
@ -471,6 +472,15 @@ bool WaylandServer::init(const QByteArray &socketName, InitalizationFlags flags)
return true; return true;
} }
KWayland::Server::LinuxDmabufUnstableV1Interface *WaylandServer::linuxDmabuf()
{
if (!m_linuxDmabuf) {
m_linuxDmabuf = m_display->createLinuxDmabufInterface(m_display);
m_linuxDmabuf->create();
}
return m_linuxDmabuf;
}
SurfaceInterface *WaylandServer::findForeignTransientForSurface(SurfaceInterface *surface) SurfaceInterface *WaylandServer::findForeignTransientForSurface(SurfaceInterface *surface)
{ {
return m_XdgForeign->transientFor(surface); return m_XdgForeign->transientFor(surface);

View file

@ -68,6 +68,8 @@ class XdgShellInterface;
class XdgForeignInterface; class XdgForeignInterface;
class XdgOutputManagerInterface; class XdgOutputManagerInterface;
class KeyStateInterface; class KeyStateInterface;
class LinuxDmabufUnstableV1Interface;
class LinuxDmabufUnstableV1Buffer;
} }
} }
@ -122,6 +124,7 @@ public:
KWayland::Server::XdgOutputManagerInterface *xdgOutputManager() const { KWayland::Server::XdgOutputManagerInterface *xdgOutputManager() const {
return m_xdgOutputManager; return m_xdgOutputManager;
} }
KWayland::Server::LinuxDmabufUnstableV1Interface *linuxDmabuf();
QList<ShellClient*> clients() const { QList<ShellClient*> clients() const {
return m_clients; return m_clients;
@ -224,6 +227,16 @@ public:
void simulateUserActivity(); void simulateUserActivity();
void updateKeyState(KWin::Xkb::LEDs leds); void updateKeyState(KWin::Xkb::LEDs leds);
QSet<KWayland::Server::LinuxDmabufUnstableV1Buffer*> linuxDmabufBuffers() const {
return m_linuxDmabufBuffers;
}
void addLinuxDmabufBuffer(KWayland::Server::LinuxDmabufUnstableV1Buffer *buffer) {
m_linuxDmabufBuffers << buffer;
}
void removeLinuxDmabufBuffer(KWayland::Server::LinuxDmabufUnstableV1Buffer *buffer) {
m_linuxDmabufBuffers.remove(buffer);
}
Q_SIGNALS: Q_SIGNALS:
void shellClientAdded(KWin::ShellClient*); void shellClientAdded(KWin::ShellClient*);
void shellClientRemoved(KWin::ShellClient*); void shellClientRemoved(KWin::ShellClient*);
@ -256,6 +269,8 @@ private:
KWayland::Server::IdleInterface *m_idle = nullptr; KWayland::Server::IdleInterface *m_idle = nullptr;
KWayland::Server::XdgOutputManagerInterface *m_xdgOutputManager = nullptr; KWayland::Server::XdgOutputManagerInterface *m_xdgOutputManager = nullptr;
KWayland::Server::XdgDecorationManagerInterface *m_xdgDecorationManager = nullptr; KWayland::Server::XdgDecorationManagerInterface *m_xdgDecorationManager = nullptr;
KWayland::Server::LinuxDmabufUnstableV1Interface *m_linuxDmabuf = nullptr;
QSet<KWayland::Server::LinuxDmabufUnstableV1Buffer*> m_linuxDmabufBuffers;
struct { struct {
KWayland::Server::ClientConnection *client = nullptr; KWayland::Server::ClientConnection *client = nullptr;
QMetaObject::Connection destroyConnection; QMetaObject::Connection destroyConnection;