[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [kwin/fredrik/linux-dmabuf] /: wayland: Add support for zwp_linux_dmabuf
From: Fredrik_Höglund <null () kde ! org>
Date: 2018-02-19 15:28:47
Message-ID: E1ennN1-00014D-Sp () code ! kde ! org
[Download RAW message or body]
Git commit 82dcbd654f2966406deebfe492fcb08987b83c1c by Fredrik Höglund.
Committed on 19/02/2018 at 15:25.
Pushed by fredrik into branch 'fredrik/linux-dmabuf'.
wayland: Add support for zwp_linux_dmabuf
M +240 -5 platformsupport/scenes/opengl/abstract_egl_backend.cpp
M +39 -0 platformsupport/scenes/opengl/abstract_egl_backend.h
M +26 -0 platformsupport/scenes/opengl/backend.cpp
M +26 -0 platformsupport/scenes/opengl/backend.h
M +18 -0 plugins/scenes/opengl/scene_opengl.cpp
M +7 -0 plugins/scenes/opengl/scene_opengl.h
M +25 -0 scene.cpp
M +26 -0 scene.h
M +43 -0 wayland_server.cpp
M +5 -0 wayland_server.h
https://commits.kde.org/kwin/82dcbd654f2966406deebfe492fcb08987b83c1c
diff --git a/platformsupport/scenes/opengl/abstract_egl_backend.cpp \
b/platformsupport/scenes/opengl/abstract_egl_backend.cpp index 91729b480..9ddae7481 \
100644
--- a/platformsupport/scenes/opengl/abstract_egl_backend.cpp
+++ b/platformsupport/scenes/opengl/abstract_egl_backend.cpp
@@ -36,6 +36,8 @@ along with this program. If not, see \
<http://www.gnu.org/licenses/>. #include <QOpenGLContext>
#include <QOpenGLFramebufferObject>
+#include <unistd.h>
+
#include <memory>
namespace KWin
@@ -48,6 +50,11 @@ eglBindWaylandDisplayWL_func eglBindWaylandDisplayWL = nullptr;
eglUnbindWaylandDisplayWL_func eglUnbindWaylandDisplayWL = nullptr;
eglQueryWaylandBufferWL_func eglQueryWaylandBufferWL = nullptr;
+typedef EGLBoolean (*eglQueryDmaBufFormatsEXT_func) (EGLDisplay dpy, EGLint \
max_formats, EGLint *formats, EGLint *num_formats); +typedef EGLBoolean \
(*eglQueryDmaBufModifiersEXT_func) (EGLDisplay dpy, EGLint format, EGLint \
max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint \
*num_modifiers); +eglQueryDmaBufFormatsEXT_func eglQueryDmaBufFormatsEXT = nullptr;
+eglQueryDmaBufModifiersEXT_func eglQueryDmaBufModifiersEXT = nullptr;
+
#ifndef EGL_WAYLAND_BUFFER_WL
#define EGL_WAYLAND_BUFFER_WL 0x31D5
#endif
@@ -58,6 +65,45 @@ eglQueryWaylandBufferWL_func eglQueryWaylandBufferWL = nullptr;
#define EGL_WAYLAND_Y_INVERTED_WL 0x31DB
#endif
+#ifndef EGL_EXT_image_dma_buf_import
+#define EGL_LINUX_DMA_BUF_EXT 0x3270
+#define EGL_LINUX_DRM_FOURCC_EXT 0x3271
+#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272
+#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273
+#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274
+#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275
+#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276
+#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277
+#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278
+#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279
+#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A
+#define EGL_YUV_COLOR_SPACE_HINT_EXT 0x327B
+#define EGL_SAMPLE_RANGE_HINT_EXT 0x327C
+#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D
+#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E
+#define EGL_ITU_REC601_EXT 0x327F
+#define EGL_ITU_REC709_EXT 0x3280
+#define EGL_ITU_REC2020_EXT 0x3281
+#define EGL_YUV_FULL_RANGE_EXT 0x3282
+#define EGL_YUV_NARROW_RANGE_EXT 0x3283
+#define EGL_YUV_CHROMA_SITING_0_EXT 0x3284
+#define EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285
+#endif // EGL_EXT_image_dma_buf_import
+
+#ifndef EGL_EXT_image_dma_buf_import_modifiers
+#define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440
+#define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441
+#define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442
+#define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443
+#define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444
+#define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445
+#define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446
+#define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447
+#define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448
+#define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449
+#define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A
+#endif // EGL_EXT_image_dma_buf_import_modifiers
+
AbstractEglBackend::AbstractEglBackend()
: QObject(nullptr)
, OpenGLBackend()
@@ -65,7 +111,12 @@ AbstractEglBackend::AbstractEglBackend()
connect(Compositor::self(), &Compositor::aboutToDestroy, this, \
&AbstractEglBackend::unbindWaylandDisplay); }
-AbstractEglBackend::~AbstractEglBackend() = default;
+AbstractEglBackend::~AbstractEglBackend()
+{
+ for (auto *dmabuf : qAsConst(m_dmabufBuffers)) {
+ dmabuf->destroyImage();
+ }
+}
void AbstractEglBackend::unbindWaylandDisplay()
{
@@ -169,6 +220,13 @@ void AbstractEglBackend::initWayland()
}
}
}
+
+ if (hasExtension(QByteArrayLiteral("EGL_EXT_image_dma_buf_import_modifiers"))) {
+ eglQueryDmaBufFormatsEXT = (eglQueryDmaBufFormatsEXT_func) \
eglGetProcAddress("eglQueryDmaBufFormatsEXT"); + eglQueryDmaBufModifiersEXT = \
(eglQueryDmaBufModifiersEXT_func) eglGetProcAddress("eglQueryDmaBufModifiersEXT"); + \
} +
+ m_haveDmabufImport = \
hasExtension(QByteArrayLiteral("EGL_EXT_image_dma_buf_import")); }
void AbstractEglBackend::initClientExtensions()
@@ -285,6 +343,91 @@ void AbstractEglBackend::setSurface(const EGLSurface &surface)
kwinApp()->platform()->setSceneEglSurface(surface);
}
+void AbstractEglBackend::aboutToDestroy(EglDmabufBuffer *buffer)
+{
+ m_dmabufBuffers.removeOne(buffer);
+}
+
+QVector<uint32_t> AbstractEglBackend::supportedDrmFormats()
+{
+ if (!m_haveDmabufImport || eglQueryDmaBufFormatsEXT == nullptr)
+ return QVector<uint32_t>();
+
+ EGLint count = 0;
+ EGLBoolean success = eglQueryDmaBufFormatsEXT(m_display, 0, NULL, &count);
+
+ if (success && count > 0) {
+ QVector<uint32_t> formats(count);
+ if (eglQueryDmaBufFormatsEXT(m_display, count, (EGLint *) formats.data(), \
&count)) { + return formats;
+ }
+ }
+
+ return QVector<uint32_t>();
+}
+
+QVector<uint64_t> AbstractEglBackend::supportedDrmModifiers(uint32_t format)
+{
+ if (!m_haveDmabufImport || eglQueryDmaBufModifiersEXT == nullptr)
+ return QVector<uint64_t>();
+
+ EGLint count = 0;
+ EGLBoolean success = eglQueryDmaBufModifiersEXT(m_display, format, 0, NULL, \
NULL, &count); +
+ if (success && count > 0) {
+ QVector<uint64_t> modifiers(count);
+ if (eglQueryDmaBufModifiersEXT(m_display, format, count, modifiers.data(), \
NULL, &count)) { + return modifiers;
+ }
+ }
+
+ return QVector<uint64_t>();
+}
+
+KWayland::Server::LinuxDmabuf::Buffer *AbstractEglBackend::importDmabufBuffer(const \
QVector<KWayland::Server::LinuxDmabuf::Plane> &planes, + \
uint32_t format, + \
const QSize &size, + \
KWayland::Server::LinuxDmabuf::Flags flags) +{
+ if (!m_haveDmabufImport)
+ return nullptr;
+
+ // FIXME: Add support for multi-planar images
+ if (planes.count() != 1)
+ return nullptr;
+
+ const EGLint attribs[] = {
+ EGL_WIDTH, size.width(),
+ EGL_HEIGHT, size.height(),
+ EGL_LINUX_DRM_FOURCC_EXT, EGLint(format),
+ EGL_DMA_BUF_PLANE0_FD_EXT, planes[0].fd,
+ EGL_DMA_BUF_PLANE0_OFFSET_EXT, EGLint(planes[0].offset),
+ EGL_DMA_BUF_PLANE0_PITCH_EXT, EGLint(planes[0].stride),
+ EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, EGLint(planes[0].modifier & 0xffffffff),
+ EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, EGLint(planes[0].modifier >> 32),
+ EGL_NONE
+ };
+
+ // Note that the EGLImage does NOT take onwership of the file descriptors
+ EGLImage image = eglCreateImageKHR(m_display, EGL_NO_CONTEXT, \
EGL_LINUX_DMA_BUF_EXT, (EGLClientBuffer) nullptr, attribs); + if (image == \
EGL_NO_IMAGE_KHR) + return nullptr;
+
+ EglDmabufBuffer *buffer = new EglDmabufBuffer(image, planes, format, size, \
flags, this); +
+ // We keep a list of the buffers we have imported so we can clean up the EGL \
images + // from the AbstractEglBackend destructor.
+ m_dmabufBuffers.append(buffer);
+
+ return buffer;
+}
+
+
+
+// --------------------------------------------------------------------
+
+
+
AbstractEglTexture::AbstractEglTexture(SceneOpenGLTexture *texture, \
AbstractEglBackend *backend) : SceneOpenGLTexturePrivate()
, q(texture)
@@ -319,11 +462,13 @@ bool AbstractEglTexture::loadTexture(WindowPixmap *pixmap)
if (auto s = pixmap->surface()) {
s->resetTrackedDamage();
}
- if (buffer->shmBuffer()) {
+ if (buffer->linuxDmabufBuffer()) {
+ return loadDmabufTexture(buffer);
+ } else if (buffer->shmBuffer()) {
return loadShmTexture(buffer);
- } else {
- return loadEglTexture(buffer);
}
+
+ return loadEglTexture(buffer);
}
void AbstractEglTexture::updateTexture(WindowPixmap *pixmap)
@@ -340,12 +485,32 @@ void AbstractEglTexture::updateTexture(WindowPixmap *pixmap)
return;
}
auto s = pixmap->surface();
+ if (EglDmabufBuffer *dmabuf = static_cast<EglDmabufBuffer \
*>(buffer->linuxDmabufBuffer())) { + q->bind();
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES) \
dmabuf->image()); + q->unbind();
+ if (m_image != EGL_NO_IMAGE_KHR) {
+ eglDestroyImageKHR(m_backend->eglDisplay(), m_image);
+ }
+ m_image = EGL_NO_IMAGE_KHR; // The wl_buffer has ownership of the image
+ const bool yInverted = dmabuf->flags() & \
KWayland::Server::LinuxDmabuf::YInverted; + if (m_size != dmabuf->size() || \
yInverted != q->isYInverted()) { + m_size = dmabuf->size();
+ q->setYInverted(yInverted);
+ }
+ if (s) {
+ s->resetTrackedDamage();
+ }
+ return;
+ }
if (!buffer->shmBuffer()) {
q->bind();
EGLImageKHR image = attach(buffer);
q->unbind();
if (image != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(m_backend->eglDisplay(), m_image);
+ if (m_image != EGL_NO_IMAGE_KHR) {
+ eglDestroyImageKHR(m_backend->eglDisplay(), m_image);
+ }
m_image = image;
}
if (s) {
@@ -465,6 +630,30 @@ bool AbstractEglTexture::loadEglTexture(const QPointer< \
KWayland::Server::Buffer return true;
}
+bool AbstractEglTexture::loadDmabufTexture(const QPointer< \
KWayland::Server::BufferInterface > &buffer) +{
+ EglDmabufBuffer *dmabuf = static_cast<EglDmabufBuffer \
*>(buffer->linuxDmabufBuffer()); + if (!dmabuf || dmabuf->image() == \
EGL_NO_IMAGE_KHR) { + qCritical(KWIN_OPENGL) << "Invalid dmabuf-based \
wl_buffer"; + q->discard();
+ return false;
+ }
+
+ assert(m_image == EGL_NO_IMAGE_KHR);
+
+ glGenTextures(1, &m_texture);
+ q->setWrapMode(GL_CLAMP_TO_EDGE);
+ q->setFilter(GL_NEAREST);
+ q->bind();
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES) dmabuf->image());
+ q->unbind();
+
+ m_size = dmabuf->size();
+ q->setYInverted(dmabuf->flags() & KWayland::Server::LinuxDmabuf::YInverted);
+
+ return true;
+}
+
EGLImageKHR AbstractEglTexture::attach(const QPointer< \
KWayland::Server::BufferInterface > &buffer) {
EGLint format, yInverted;
@@ -507,5 +696,51 @@ bool AbstractEglTexture::updateFromFBO(const \
QSharedPointer<QOpenGLFramebufferOb return true;
}
+
+
+// --------------------------------------------------------------------
+
+
+
+EglDmabufBuffer::EglDmabufBuffer(EGLImage image,
+ const QVector<KWayland::Server::LinuxDmabuf::Plane> \
&planes, + uint32_t format,
+ const QSize &size,
+ KWayland::Server::LinuxDmabuf::Flags flags,
+ AbstractEglBackend *backend)
+ : KWayland::Server::LinuxDmabuf::Buffer(format, size),
+ m_backend(backend),
+ m_image(image),
+ m_planes(planes),
+ m_flags(flags)
+{
}
+EglDmabufBuffer::~EglDmabufBuffer()
+{
+ if (m_backend) {
+ m_backend->aboutToDestroy(this);
+
+ assert(m_image != EGL_NO_IMAGE_KHR);
+ eglDestroyImageKHR(m_backend->eglDisplay(), m_image);
+ }
+
+ // 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 EglDmabufBuffer::destroyImage()
+{
+ assert(m_image != EGL_NO_IMAGE_KHR);
+ eglDestroyImageKHR(m_backend->eglDisplay(), m_image);
+ m_image = EGL_NO_IMAGE_KHR;
+ m_backend = nullptr;
+}
+
+
+} // namespace KWin
+
diff --git a/platformsupport/scenes/opengl/abstract_egl_backend.h \
b/platformsupport/scenes/opengl/abstract_egl_backend.h index 50d1a8282..c4084eba5 \
100644
--- a/platformsupport/scenes/opengl/abstract_egl_backend.h
+++ b/platformsupport/scenes/opengl/abstract_egl_backend.h
@@ -23,6 +23,7 @@ along with this program. If not, see \
<http://www.gnu.org/licenses/>. #include "texture.h"
#include <QObject>
+#include <QLinkedList>
#include <epoxy/egl.h>
#include <fixx11h.h>
@@ -39,6 +40,8 @@ class BufferInterface;
namespace KWin
{
+class EglDmabufBuffer;
+
class KWIN_EXPORT AbstractEglBackend : public QObject, public OpenGLBackend
{
Q_OBJECT
@@ -60,6 +63,15 @@ public:
return m_config;
}
+ void aboutToDestroy(EglDmabufBuffer *buffer);
+
+ QVector<uint32_t> supportedDrmFormats() override;
+ QVector<uint64_t> supportedDrmModifiers(uint32_t format) override;
+ KWayland::Server::LinuxDmabuf::Buffer *importDmabufBuffer(const \
QVector<KWayland::Server::LinuxDmabuf::Plane> &planes, + \
uint32_t format, + const \
QSize &size, + \
KWayland::Server::LinuxDmabuf::Flags flags) override; +
protected:
AbstractEglBackend();
void setEglDisplay(const EGLDisplay &display);
@@ -85,6 +97,8 @@ private:
EGLContext m_context = EGL_NO_CONTEXT;
EGLConfig m_config = nullptr;
QList<QByteArray> m_clientExtensions;
+ QLinkedList<EglDmabufBuffer *> m_dmabufBuffers;
+ bool m_haveDmabufImport = false;
};
class KWIN_EXPORT AbstractEglTexture : public SceneOpenGLTexturePrivate
@@ -110,6 +124,7 @@ protected:
private:
bool loadShmTexture(const QPointer<KWayland::Server::BufferInterface> &buffer);
bool loadEglTexture(const QPointer<KWayland::Server::BufferInterface> &buffer);
+ bool loadDmabufTexture(const QPointer< KWayland::Server::BufferInterface > \
&buffer);
EGLImageKHR attach(const QPointer<KWayland::Server::BufferInterface> &buffer);
bool updateFromFBO(const QSharedPointer<QOpenGLFramebufferObject> &fbo);
SceneOpenGLTexture *q;
@@ -117,6 +132,30 @@ private:
EGLImageKHR m_image;
};
+class KWIN_EXPORT EglDmabufBuffer : public KWayland::Server::LinuxDmabuf::Buffer
+{
+public:
+ EglDmabufBuffer(EGLImage image,
+ const QVector<KWayland::Server::LinuxDmabuf::Plane> &planes,
+ uint32_t format,
+ const QSize &size,
+ KWayland::Server::LinuxDmabuf::Flags flags,
+ AbstractEglBackend *backend);
+ ~EglDmabufBuffer() override;
+
+ EGLImage image() const { return m_image; }
+ KWayland::Server::LinuxDmabuf::Flags flags() const { return m_flags; }
+ const QVector<KWayland::Server::LinuxDmabuf::Plane> &planes() const { return \
m_planes; } +
+ void destroyImage();
+
+private:
+ AbstractEglBackend *m_backend;
+ EGLImage m_image;
+ QVector<KWayland::Server::LinuxDmabuf::Plane> m_planes;
+ KWayland::Server::LinuxDmabuf::Flags m_flags;
+};
+
}
#endif
diff --git a/platformsupport/scenes/opengl/backend.cpp \
b/platformsupport/scenes/opengl/backend.cpp index cb0a23d53..872a5798f 100644
--- a/platformsupport/scenes/opengl/backend.cpp
+++ b/platformsupport/scenes/opengl/backend.cpp
@@ -116,4 +116,30 @@ void OpenGLBackend::copyPixels(const QRegion ®ion)
}
}
+QVector<uint32_t> OpenGLBackend::supportedDrmFormats()
+{
+ return QVector<uint32_t>();
+}
+
+QVector<uint64_t> OpenGLBackend::supportedDrmModifiers(uint32_t format)
+{
+ Q_UNUSED(format)
+
+ return QVector<uint64_t>();
+}
+
+KWayland::Server::LinuxDmabuf::Buffer *OpenGLBackend::importDmabufBuffer(const \
QVector<KWayland::Server::LinuxDmabuf::Plane> &planes, + \
uint32_t format, + \
const QSize &size, + \
KWayland::Server::LinuxDmabuf::Flags flags) +{
+ Q_UNUSED(planes)
+ Q_UNUSED(format)
+ Q_UNUSED(size)
+ Q_UNUSED(flags)
+
+ return nullptr;
+}
+
+
}
diff --git a/platformsupport/scenes/opengl/backend.h \
b/platformsupport/scenes/opengl/backend.h index 483c71186..b46764c1f 100644
--- a/platformsupport/scenes/opengl/backend.h
+++ b/platformsupport/scenes/opengl/backend.h
@@ -26,6 +26,8 @@ along with this program. If not, see \
<http://www.gnu.org/licenses/>.
#include <kwin_export.h>
+#include <KWayland/Server/linuxdmabuf_v1_interface.h>
+
namespace KWin
{
class OpenGLBackend;
@@ -197,6 +199,30 @@ public:
*/
void copyPixels(const QRegion ®ion);
+ /**
+ * Returns the list of the DRM format codes supported by the underlying graphics \
stack. + *
+ * The default implementation returns an empty vector.
+ */
+ virtual QVector<uint32_t> supportedDrmFormats();
+
+ /**
+ * Returns the list of the DRM modifiers supported with the given format.
+ *
+ * The default implementation returns an empty vector.
+ */
+ virtual QVector<uint64_t> supportedDrmModifiers(uint32_t format);
+
+ /**
+ * Imports a dmabuf-buffer into the graphics system.
+ *
+ * The default implementation returns nullptr.
+ */
+ virtual KWayland::Server::LinuxDmabuf::Buffer *importDmabufBuffer(const \
QVector<KWayland::Server::LinuxDmabuf::Plane> &planes, + \
uint32_t format, + \
const QSize &size, + \
KWayland::Server::LinuxDmabuf::Flags flags); +
protected:
/**
* @brief Backend specific flushing of frame to screen.
diff --git a/plugins/scenes/opengl/scene_opengl.cpp \
b/plugins/scenes/opengl/scene_opengl.cpp index d225b8e66..c28ed6e68 100644
--- a/plugins/scenes/opengl/scene_opengl.cpp
+++ b/plugins/scenes/opengl/scene_opengl.cpp
@@ -738,6 +738,24 @@ qint64 SceneOpenGL::paint(QRegion damage, ToplevelList \
toplevels) return m_backend->renderTime();
}
+QVector<uint32_t> SceneOpenGL::supportedDrmFormats()
+{
+ return m_backend->supportedDrmFormats();
+}
+
+QVector<uint64_t> SceneOpenGL::supportedDrmModifiers(uint32_t format)
+{
+ return m_backend->supportedDrmModifiers(format);
+}
+
+KWayland::Server::LinuxDmabuf::Buffer *SceneOpenGL::importDmabufBuffer(const \
QVector<KWayland::Server::LinuxDmabuf::Plane> &planes, + \
uint32_t format, + \
const QSize &size, + \
KWayland::Server::LinuxDmabuf::Flags flags) +{
+ return m_backend->importDmabufBuffer(planes, format, size, flags);
+}
+
QMatrix4x4 SceneOpenGL::transformation(int mask, const ScreenPaintData &data) const
{
QMatrix4x4 matrix;
diff --git a/plugins/scenes/opengl/scene_opengl.h \
b/plugins/scenes/opengl/scene_opengl.h index 6453d3b57..2e424e53e 100644
--- a/plugins/scenes/opengl/scene_opengl.h
+++ b/plugins/scenes/opengl/scene_opengl.h
@@ -82,6 +82,13 @@ public:
QVector<QByteArray> openGLPlatformInterfaceExtensions() const override;
+ QVector<uint32_t> supportedDrmFormats() override final;
+ QVector<uint64_t> supportedDrmModifiers(uint32_t format) override final;
+ KWayland::Server::LinuxDmabuf::Buffer *importDmabufBuffer(const \
QVector<KWayland::Server::LinuxDmabuf::Plane> &planes, + \
uint32_t format, + const \
QSize &size, + \
KWayland::Server::LinuxDmabuf::Flags flags = 0) override final; +
static SceneOpenGL *createScene(QObject *parent);
protected:
diff --git a/scene.cpp b/scene.cpp
index a12e97429..5a6030c6f 100644
--- a/scene.cpp
+++ b/scene.cpp
@@ -677,6 +677,31 @@ QVector<QByteArray> Scene::openGLPlatformInterfaceExtensions() \
const return QVector<QByteArray>{};
}
+QVector<uint32_t> Scene::supportedDrmFormats()
+{
+ return QVector<uint32_t>();
+}
+
+QVector<uint64_t> Scene::supportedDrmModifiers(uint32_t format)
+{
+ Q_UNUSED(format)
+
+ return QVector<uint64_t>();
+}
+
+KWayland::Server::LinuxDmabuf::Buffer *Scene::importDmabufBuffer(const \
QVector<KWayland::Server::LinuxDmabuf::Plane> &planes, + \
uint32_t format, + \
const QSize &size, + \
KWayland::Server::LinuxDmabuf::Flags flags) +{
+ Q_UNUSED(planes)
+ Q_UNUSED(format)
+ Q_UNUSED(size)
+ Q_UNUSED(flags)
+
+ return nullptr;
+}
+
//****************************************
// Scene::Window
//****************************************
diff --git a/scene.h b/scene.h
index f7c67c5ca..f1e6b3051 100644
--- a/scene.h
+++ b/scene.h
@@ -25,6 +25,8 @@ along with this program. If not, see \
<http://www.gnu.org/licenses/>. #include "utils.h"
#include "kwineffects.h"
+#include <KWayland/Server/linuxdmabuf_v1_interface.h>
+
#include <QElapsedTimer>
#include <QMatrix4x4>
@@ -184,6 +186,30 @@ public:
**/
virtual QVector<QByteArray> openGLPlatformInterfaceExtensions() const;
+ /**
+ * Returns the DRM formats supported by the underlying graphics stack.
+ *
+ * The default implementation returns an empty vector.
+ */
+ virtual QVector<uint32_t> supportedDrmFormats();
+
+ /**
+ * Returns the DRM modifiers supported with the given format.
+ *
+ * The default implementation returns an empty vector.
+ */
+ virtual QVector<uint64_t> supportedDrmModifiers(uint32_t format);
+
+ /**
+ * Imports a dmabuf-buffer into the graphics system used by the scene.
+ *
+ * The default implementation returns nullptr.
+ */
+ virtual KWayland::Server::LinuxDmabuf::Buffer *importDmabufBuffer(const \
QVector<KWayland::Server::LinuxDmabuf::Plane> &planes, + \
uint32_t format, + \
const QSize &size, + \
KWayland::Server::LinuxDmabuf::Flags flags = 0); +
Q_SIGNALS:
void frameRendered();
void resetCompositing();
diff --git a/wayland_server.cpp b/wayland_server.cpp
index 78ab4c332..365f9a7da 100644
--- a/wayland_server.cpp
+++ b/wayland_server.cpp
@@ -25,6 +25,7 @@ along with this program. If not, see \
<http://www.gnu.org/licenses/>. #include "screens.h"
#include "shell_client.h"
#include "workspace.h"
+#include "scene.h"
// Client
#include <KWayland/Client/connection_thread.h>
@@ -58,6 +59,7 @@ along with this program. If not, see \
<http://www.gnu.org/licenses/>. #include \
<KWayland/Server/outputconfiguration_interface.h> #include \
<KWayland/Server/xdgshell_interface.h> #include \
<KWayland/Server/xdgforeign_interface.h> +#include \
<KWayland/Server/linuxdmabuf_v1_interface.h>
// Qt
#include <QThread>
@@ -78,6 +80,39 @@ namespace KWin
KWIN_SINGLETON_FACTORY(WaylandServer)
+
+class LinuxDmabufBridge : public LinuxDmabufUnstableV1Interface::Bridge
+{
+public:
+ LinuxDmabufBridge() = default;
+ ~LinuxDmabufBridge() = default;
+
+ QVector<uint32_t> supportedFormats() const override final;
+ QVector<uint64_t> supportedModifiers(uint32_t format) const override final;
+ LinuxDmabuf::Buffer *importBuffer(const QVector<LinuxDmabuf::Plane> &planes, \
uint32_t format, const QSize &size, LinuxDmabuf::Flags flags) override final; +};
+
+QVector<uint32_t> LinuxDmabufBridge::supportedFormats() const
+{
+ return Compositor::self()->scene()->supportedDrmFormats();
+}
+
+QVector<uint64_t> LinuxDmabufBridge::supportedModifiers(uint32_t format) const
+{
+ return Compositor::self()->scene()->supportedDrmModifiers(format);
+}
+
+LinuxDmabuf::Buffer *LinuxDmabufBridge::importBuffer(const \
QVector<LinuxDmabuf::Plane> &planes, uint32_t format, const QSize &size, \
LinuxDmabuf::Flags flags) +{
+ return Compositor::self()->scene()->importDmabufBuffer(planes, format, size, \
flags); +}
+
+
+
+// --------------------------------------------------------------------
+
+
+
WaylandServer::WaylandServer(QObject *parent)
: QObject(parent)
{
@@ -90,6 +125,8 @@ WaylandServer::WaylandServer(QObject *parent)
WaylandServer::~WaylandServer()
{
destroyInputMethodConnection();
+ m_linuxDmabuf->setBridge(nullptr);
+ delete m_linuxDmabufBridge;
}
void WaylandServer::destroyInternalConnection()
@@ -359,6 +396,12 @@ bool WaylandServer::init(const QByteArray &socketName, \
InitalizationFlags flags) m_XdgForeign = \
m_display->createXdgForeignInterface(m_display); m_XdgForeign->create();
+ m_linuxDmabufBridge = new LinuxDmabufBridge;
+
+ m_linuxDmabuf = m_display->createLinuxDmabufInterface(m_display);
+ m_linuxDmabuf->setBridge(m_linuxDmabufBridge);
+ m_linuxDmabuf->create();
+
return true;
}
diff --git a/wayland_server.h b/wayland_server.h
index 03ba8c862..fc5cdd0ca 100644
--- a/wayland_server.h
+++ b/wayland_server.h
@@ -60,6 +60,7 @@ class OutputManagementInterface;
class OutputConfigurationInterface;
class XdgShellInterface;
class XdgForeignInterface;
+class LinuxDmabufUnstableV1Interface;
}
}
@@ -70,6 +71,8 @@ class ShellClient;
class AbstractClient;
class Toplevel;
+class LinuxDmabufBridge;
+
class KWIN_EXPORT WaylandServer : public QObject
{
Q_OBJECT
@@ -253,6 +256,8 @@ private:
QHash<KWayland::Server::ClientConnection*, quint16> m_clientIds;
InitalizationFlags m_initFlags;
QVector<KWayland::Server::PlasmaShellSurfaceInterface*> m_plasmaShellSurfaces;
+ KWayland::Server::LinuxDmabufUnstableV1Interface *m_linuxDmabuf;
+ LinuxDmabufBridge *m_linuxDmabufBridge;
KWIN_SINGLETON(WaylandServer)
};
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic