[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 &region)
     }
 }
 
+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 &region);
 
+    /**
+     * 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