[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kwayland/fredrik/linux-dmabuf] src: Implement zwp_linux_dmabuf_v1
From:       Fredrik_Höglund <null () kde ! org>
Date:       2018-02-13 19:26:22
Message-ID: E1elgDe-0008M8-RZ () code ! kde ! org
[Download RAW message or body]

Git commit 6d0d8f4489872a47cef725b0df31e47567c723c5 by Fredrik Höglund.
Committed on 13/02/2018 at 14:44.
Pushed by fredrik into branch 'fredrik/linux-dmabuf'.

Implement zwp_linux_dmabuf_v1

This interface provides a way for clients to create generic dmabuf-
based wl_buffers.

A  +348  -0    src/client/protocols/linux-dmabuf-unstable-v1.xml
M  +8    -0    src/server/CMakeLists.txt
M  +50   -0    src/server/buffer_interface.cpp
M  +8    -0    src/server/buffer_interface.h
M  +8    -0    src/server/display.cpp
M  +7    -0    src/server/display.h
A  +414  -0    src/server/drm_fourcc.h     [License: BSD X11 (BSD like)]
A  +482  -0    src/server/linuxdmabuf_v1_interface.cpp     [License: BSD]
A  +181  -0    src/server/linuxdmabuf_v1_interface.h     [License: BSD]

https://commits.kde.org/kwayland/6d0d8f4489872a47cef725b0df31e47567c723c5

diff --git a/src/client/protocols/linux-dmabuf-unstable-v1.xml \
b/src/client/protocols/linux-dmabuf-unstable-v1.xml new file mode 100644
index 0000000..154afe2
--- /dev/null
+++ b/src/client/protocols/linux-dmabuf-unstable-v1.xml
@@ -0,0 +1,348 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="linux_dmabuf_unstable_v1">
+
+  <copyright>
+    Copyright  © 2014, 2015 Collabora, Ltd.
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the "Software"),
+    to deal in the Software without restriction, including without limitation
+    the rights to use, copy, modify, merge, publish, distribute, sublicense,
+    and/or sell copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice (including the next
+    paragraph) shall be included in all copies or substantial portions of the
+    Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+    DEALINGS IN THE SOFTWARE.
+  </copyright>
+
+  <interface name="zwp_linux_dmabuf_v1" version="3">
+    <description summary="factory for creating dmabuf-based wl_buffers">
+      Following the interfaces from:
+      https://www.khronos.org/registry/egl/extensions/EXT/EGL_EXT_image_dma_buf_import.txt
 +      and the Linux DRM sub-system's AddFb2 ioctl.
+
+      This interface offers ways to create generic dmabuf-based
+      wl_buffers. Immediately after a client binds to this interface,
+      the set of supported formats and format modifiers is sent with
+      'format' and 'modifier' events.
+
+      The following are required from clients:
+
+      - Clients must ensure that either all data in the dma-buf is
+        coherent for all subsequent read access or that coherency is
+        correctly handled by the underlying kernel-side dma-buf
+        implementation.
+
+      - Don't make any more attachments after sending the buffer to the
+        compositor. Making more attachments later increases the risk of
+        the compositor not being able to use (re-import) an existing
+        dmabuf-based wl_buffer.
+
+      The underlying graphics stack must ensure the following:
+
+      - The dmabuf file descriptors relayed to the server will stay valid
+        for the whole lifetime of the wl_buffer. This means the server may
+        at any time use those fds to import the dmabuf into any kernel
+        sub-system that might accept it.
+
+      To create a wl_buffer from one or more dmabufs, a client creates a
+      zwp_linux_dmabuf_params_v1 object with a zwp_linux_dmabuf_v1.create_params
+      request. All planes required by the intended format are added with
+      the 'add' request. Finally, a 'create' or 'create_immed' request is
+      issued, which has the following outcome depending on the import success.
+
+      The 'create' request,
+      - on success, triggers a 'created' event which provides the final
+        wl_buffer to the client.
+      - on failure, triggers a 'failed' event to convey that the server
+        cannot use the dmabufs received from the client.
+
+      For the 'create_immed' request,
+      - on success, the server immediately imports the added dmabufs to
+        create a wl_buffer. No event is sent from the server in this case.
+      - on failure, the server can choose to either:
+        - terminate the client by raising a fatal error.
+        - mark the wl_buffer as failed, and send a 'failed' event to the
+          client. If the client uses a failed wl_buffer as an argument to any
+          request, the behaviour is compositor implementation-defined.
+
+      Warning! The protocol described in this file is experimental and
+      backward incompatible changes may be made. Backward compatible changes
+      may be added together with the corresponding interface version bump.
+      Backward incompatible changes are done by bumping the version number in
+      the protocol and interface names and resetting the interface version.
+      Once the protocol is to be declared stable, the 'z' prefix and the
+      version number in the protocol and interface names are removed and the
+      interface version number is reset.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="unbind the factory">
+        Objects created through this interface, especially wl_buffers, will
+        remain valid.
+      </description>
+    </request>
+
+    <request name="create_params">
+      <description summary="create a temporary object for buffer parameters">
+        This temporary object is used to collect multiple dmabuf handles into
+        a single batch to create a wl_buffer. It can only be used once and
+        should be destroyed after a 'created' or 'failed' event has been
+        received.
+      </description>
+      <arg name="params_id" type="new_id" interface="zwp_linux_buffer_params_v1"
+           summary="the new temporary"/>
+    </request>
+
+    <event name="format">
+      <description summary="supported buffer format">
+        This event advertises one buffer format that the server supports.
+        All the supported formats are advertised once when the client
+        binds to this interface. A roundtrip after binding guarantees
+        that the client has received all supported formats.
+
+        For the definition of the format codes, see the
+        zwp_linux_buffer_params_v1::create request.
+
+        Warning: the 'format' event is likely to be deprecated and replaced
+        with the 'modifier' event introduced in zwp_linux_dmabuf_v1
+        version 3, described below. Please refrain from using the information
+        received from this event.
+      </description>
+      <arg name="format" type="uint" summary="DRM_FORMAT code"/>
+    </event>
+
+    <event name="modifier" since="3">
+      <description summary="supported buffer format modifier">
+        This event advertises the formats that the server supports, along with
+        the modifiers supported for each format. All the supported modifiers
+        for all the supported formats are advertised once when the client
+        binds to this interface. A roundtrip after binding guarantees that
+        the client has received all supported format-modifier pairs.
+
+        For the definition of the format and modifier codes, see the
+        zwp_linux_buffer_params_v1::create request.
+      </description>
+      <arg name="format" type="uint" summary="DRM_FORMAT code"/>
+      <arg name="modifier_hi" type="uint"
+           summary="high 32 bits of layout modifier"/>
+      <arg name="modifier_lo" type="uint"
+           summary="low 32 bits of layout modifier"/>
+    </event>
+  </interface>
+
+  <interface name="zwp_linux_buffer_params_v1" version="3">
+    <description summary="parameters for creating a dmabuf-based wl_buffer">
+      This temporary object is a collection of dmabufs and other
+      parameters that together form a single logical buffer. The temporary
+      object may eventually create one wl_buffer unless cancelled by
+      destroying it before requesting 'create'.
+
+      Single-planar formats only require one dmabuf, however
+      multi-planar formats may require more than one dmabuf. For all
+      formats, an 'add' request must be called once per plane (even if the
+      underlying dmabuf fd is identical).
+
+      You must use consecutive plane indices ('plane_idx' argument for 'add')
+      from zero to the number of planes used by the drm_fourcc format code.
+      All planes required by the format must be given exactly once, but can
+      be given in any order. Each plane index can be set only once.
+    </description>
+
+    <enum name="error">
+      <entry name="already_used" value="0"
+             summary="the dmabuf_batch object has already been used to create a \
wl_buffer"/> +      <entry name="plane_idx" value="1"
+             summary="plane index out of bounds"/>
+      <entry name="plane_set" value="2"
+             summary="the plane index was already set"/>
+      <entry name="incomplete" value="3"
+             summary="missing or too many planes to create a buffer"/>
+      <entry name="invalid_format" value="4"
+             summary="format not supported"/>
+      <entry name="invalid_dimensions" value="5"
+             summary="invalid width or height"/>
+      <entry name="out_of_bounds" value="6"
+             summary="offset + stride * height goes out of dmabuf bounds"/>
+      <entry name="invalid_wl_buffer" value="7"
+             summary="invalid wl_buffer resulted from importing dmabufs via
+               the create_immed request on given buffer_params"/>
+    </enum>
+
+    <request name="destroy" type="destructor">
+      <description summary="delete this object, used or not">
+        Cleans up the temporary data sent to the server for dmabuf-based
+        wl_buffer creation.
+      </description>
+    </request>
+
+    <request name="add">
+      <description summary="add a dmabuf to the temporary set">
+        This request adds one dmabuf to the set in this
+        zwp_linux_buffer_params_v1.
+
+        The 64-bit unsigned value combined from modifier_hi and modifier_lo
+        is the dmabuf layout modifier. DRM AddFB2 ioctl calls this the
+        fb modifier, which is defined in drm_mode.h of Linux UAPI.
+        This is an opaque token. Drivers use this token to express tiling,
+        compression, etc. driver-specific modifications to the base format
+        defined by the DRM fourcc code.
+
+        This request raises the PLANE_IDX error if plane_idx is too large.
+        The error PLANE_SET is raised if attempting to set a plane that
+        was already set.
+      </description>
+      <arg name="fd" type="fd" summary="dmabuf fd"/>
+      <arg name="plane_idx" type="uint" summary="plane index"/>
+      <arg name="offset" type="uint" summary="offset in bytes"/>
+      <arg name="stride" type="uint" summary="stride in bytes"/>
+      <arg name="modifier_hi" type="uint"
+           summary="high 32 bits of layout modifier"/>
+      <arg name="modifier_lo" type="uint"
+           summary="low 32 bits of layout modifier"/>
+    </request>
+
+    <enum name="flags">
+      <entry name="y_invert" value="1" summary="contents are y-inverted"/>
+      <entry name="interlaced" value="2" summary="content is interlaced"/>
+      <entry name="bottom_first" value="4" summary="bottom field first"/>
+    </enum>
+
+    <request name="create">
+      <description summary="create a wl_buffer from the given dmabufs">
+        This asks for creation of a wl_buffer from the added dmabuf
+        buffers. The wl_buffer is not created immediately but returned via
+        the 'created' event if the dmabuf sharing succeeds. The sharing
+        may fail at runtime for reasons a client cannot predict, in
+        which case the 'failed' event is triggered.
+
+        The 'format' argument is a DRM_FORMAT code, as defined by the
+        libdrm's drm_fourcc.h. The Linux kernel's DRM sub-system is the
+        authoritative source on how the format codes should work.
+
+        The 'flags' is a bitfield of the flags defined in enum "flags".
+        'y_invert' means the that the image needs to be y-flipped.
+
+        Flag 'interlaced' means that the frame in the buffer is not
+        progressive as usual, but interlaced. An interlaced buffer as
+        supported here must always contain both top and bottom fields.
+        The top field always begins on the first pixel row. The temporal
+        ordering between the two fields is top field first, unless
+        'bottom_first' is specified. It is undefined whether 'bottom_first'
+        is ignored if 'interlaced' is not set.
+
+        This protocol does not convey any information about field rate,
+        duration, or timing, other than the relative ordering between the
+        two fields in one buffer. A compositor may have to estimate the
+        intended field rate from the incoming buffer rate. It is undefined
+        whether the time of receiving wl_surface.commit with a new buffer
+        attached, applying the wl_surface state, wl_surface.frame callback
+        trigger, presentation, or any other point in the compositor cycle
+        is used to measure the frame or field times. There is no support
+        for detecting missed or late frames/fields/buffers either, and
+        there is no support whatsoever for cooperating with interlaced
+        compositor output.
+
+        The composited image quality resulting from the use of interlaced
+        buffers is explicitly undefined. A compositor may use elaborate
+        hardware features or software to deinterlace and create progressive
+        output frames from a sequence of interlaced input buffers, or it
+        may produce substandard image quality. However, compositors that
+        cannot guarantee reasonable image quality in all cases are recommended
+        to just reject all interlaced buffers.
+
+        Any argument errors, including non-positive width or height,
+        mismatch between the number of planes and the format, bad
+        format, bad offset or stride, may be indicated by fatal protocol
+        errors: INCOMPLETE, INVALID_FORMAT, INVALID_DIMENSIONS,
+        OUT_OF_BOUNDS.
+
+        Dmabuf import errors in the server that are not obvious client
+        bugs are returned via the 'failed' event as non-fatal. This
+        allows attempting dmabuf sharing and falling back in the client
+        if it fails.
+
+        This request can be sent only once in the object's lifetime, after
+        which the only legal request is destroy. This object should be
+        destroyed after issuing a 'create' request. Attempting to use this
+        object after issuing 'create' raises ALREADY_USED protocol error.
+
+        It is not mandatory to issue 'create'. If a client wants to
+        cancel the buffer creation, it can just destroy this object.
+      </description>
+      <arg name="width" type="int" summary="base plane width in pixels"/>
+      <arg name="height" type="int" summary="base plane height in pixels"/>
+      <arg name="format" type="uint" summary="DRM_FORMAT code"/>
+      <arg name="flags" type="uint" summary="see enum flags"/>
+    </request>
+
+    <event name="created">
+      <description summary="buffer creation succeeded">
+        This event indicates that the attempted buffer creation was
+        successful. It provides the new wl_buffer referencing the dmabuf(s).
+
+        Upon receiving this event, the client should destroy the
+        zlinux_dmabuf_params object.
+      </description>
+      <arg name="buffer" type="new_id" interface="wl_buffer"
+           summary="the newly created wl_buffer"/>
+    </event>
+
+    <event name="failed">
+      <description summary="buffer creation failed">
+        This event indicates that the attempted buffer creation has
+        failed. It usually means that one of the dmabuf constraints
+        has not been fulfilled.
+
+        Upon receiving this event, the client should destroy the
+        zlinux_buffer_params object.
+      </description>
+    </event>
+
+    <request name="create_immed" since="2">
+      <description summary="immediately create a wl_buffer from the given
+                     dmabufs">
+        This asks for immediate creation of a wl_buffer by importing the
+        added dmabufs.
+
+        In case of import success, no event is sent from the server, and the
+        wl_buffer is ready to be used by the client.
+
+        Upon import failure, either of the following may happen, as seen fit
+        by the implementation:
+        - the client is terminated with one of the following fatal protocol
+          errors:
+          - INCOMPLETE, INVALID_FORMAT, INVALID_DIMENSIONS, OUT_OF_BOUNDS,
+            in case of argument errors such as mismatch between the number
+            of planes and the format, bad format, non-positive width or
+            height, or bad offset or stride.
+          - INVALID_WL_BUFFER, in case the cause for failure is unknown or
+            plaform specific.
+        - the server creates an invalid wl_buffer, marks it as failed and
+          sends a 'failed' event to the client. The result of using this
+          invalid wl_buffer as an argument in any request by the client is
+          defined by the compositor implementation.
+
+        This takes the same arguments as a 'create' request, and obeys the
+        same restrictions.
+      </description>
+      <arg name="buffer_id" type="new_id" interface="wl_buffer"
+           summary="id for the newly created wl_buffer"/>
+      <arg name="width" type="int" summary="base plane width in pixels"/>
+      <arg name="height" type="int" summary="base plane height in pixels"/>
+      <arg name="format" type="uint" summary="DRM_FORMAT code"/>
+      <arg name="flags" type="uint" summary="see enum flags"/>
+    </request>
+
+  </interface>
+
+</protocol>
diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt
index adf047b..684da5b 100644
--- a/src/server/CMakeLists.txt
+++ b/src/server/CMakeLists.txt
@@ -53,6 +53,7 @@ set(SERVER_LIB_SRCS
     xdgforeign_v2_interface.cpp
     xdgforeign_interface.cpp
     xdgshell_v6_interface.cpp
+    linuxdmabuf_v1_interface.cpp
 )
 
 ecm_add_wayland_server_protocol(SERVER_LIB_SRCS
@@ -174,6 +175,11 @@ ecm_add_wayland_server_protocol(SERVER_LIB_SRCS
     BASENAME server_decoration_palette
 )
 
+ecm_add_wayland_server_protocol(SERVER_LIB_SRCS
+    PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/linux-dmabuf-unstable-v1.xml
 +    BASENAME linux-dmabuf-unstable-v1
+)
+
 set(SERVER_GENERATED_SRCS
     ${CMAKE_CURRENT_BINARY_DIR}/wayland-output-management-client-protocol.h
     ${CMAKE_CURRENT_BINARY_DIR}/wayland-output-management-server-protocol.h
@@ -221,6 +227,7 @@ set(SERVER_GENERATED_SRCS
     ${CMAKE_CURRENT_BINARY_DIR}/wayland-xdg-foreign-unstable-v2-server-protocol.h
     ${CMAKE_CURRENT_BINARY_DIR}/wayland-idle-inhibit-unstable-v1-client-protocol.h
     ${CMAKE_CURRENT_BINARY_DIR}/wayland-idle-inhibit-unstable-v1-server-protocol.h
+    ${CMAKE_CURRENT_BINARY_DIR}/wayland-linux-dmabuf-unstable-v1-server-protocol.h
 )
 
 set_source_files_properties(${SERVER_GENERATED_SRCS} PROPERTIES SKIP_AUTOMOC ON)
@@ -299,6 +306,7 @@ set(SERVER_LIB_HEADERS
   touch_interface.h
   xdgshell_interface.h
   xdgforeign_interface.h
+  linuxdmabuf_v1_interface.h
 )
 
 install(FILES
diff --git a/src/server/buffer_interface.cpp b/src/server/buffer_interface.cpp
index 71c5a97..84252a2 100644
--- a/src/server/buffer_interface.cpp
+++ b/src/server/buffer_interface.cpp
@@ -21,12 +21,15 @@ License along with this library.  If not, see \
<http://www.gnu.org/licenses/>.  #include "display.h"
 #include "logging_p.h"
 #include "surface_interface.h"
+#include "linuxdmabuf_v1_interface.h"
 // Wayland
 #include <wayland-server.h>
 // EGL
 #include <EGL/egl.h>
 #include <QtGui/qopengl.h>
 
+#include "drm_fourcc.h"
+
 namespace KWayland
 {
 namespace Server
@@ -47,6 +50,7 @@ public:
     QImage createImage();
     wl_resource *buffer;
     wl_shm_buffer *shmBuffer;
+    LinuxDmabuf::Buffer *dmabufBuffer;
     SurfaceInterface *surface;
     int refCount;
     QSize size;
@@ -103,11 +107,15 @@ void BufferInterface::Private::imageBufferCleanupHandler(void \
*info)  BufferInterface::Private::Private(BufferInterface *q, wl_resource *resource, \
SurfaceInterface *parent)  : buffer(resource)
     , shmBuffer(wl_shm_buffer_get(resource))
+    , dmabufBuffer(nullptr)
     , surface(parent)
     , refCount(0)
     , alpha(false)
     , q(q)
 {
+    if (!shmBuffer && wl_resource_instance_of(resource, &wl_buffer_interface, \
LinuxDmabufUnstableV1Interface::bufferImplementation())) { +        dmabufBuffer = \
static_cast<LinuxDmabuf::Buffer *>(wl_resource_get_user_data(resource)); +    }
     s_buffers << this;
     listener.notify = destroyListenerCallback;
     listener.link.prev = nullptr;
@@ -125,6 +133,43 @@ BufferInterface::Private::Private(BufferInterface *q, \
wl_resource *resource, Sur  alpha = false;
             break;
         }
+    } else if (dmabufBuffer) {
+        switch (dmabufBuffer->format()) {
+        case DRM_FORMAT_ARGB4444:
+        case DRM_FORMAT_ABGR4444:
+        case DRM_FORMAT_RGBA4444:
+        case DRM_FORMAT_BGRA4444:
+
+        case DRM_FORMAT_ARGB1555:
+        case DRM_FORMAT_ABGR1555:
+        case DRM_FORMAT_RGBA5551:
+        case DRM_FORMAT_BGRA5551:
+
+        case DRM_FORMAT_ARGB8888:
+        case DRM_FORMAT_ABGR8888:
+        case DRM_FORMAT_RGBA8888:
+        case DRM_FORMAT_BGRA8888:
+
+        case DRM_FORMAT_ARGB2101010:
+        case DRM_FORMAT_ABGR2101010:
+        case DRM_FORMAT_RGBA1010102:
+        case DRM_FORMAT_BGRA1010102:
+
+        case DRM_FORMAT_XRGB8888_A8:
+        case DRM_FORMAT_XBGR8888_A8:
+        case DRM_FORMAT_RGBX8888_A8:
+        case DRM_FORMAT_BGRX8888_A8:
+        case DRM_FORMAT_RGB888_A8:
+        case DRM_FORMAT_BGR888_A8:
+        case DRM_FORMAT_RGB565_A8:
+        case DRM_FORMAT_BGR565_A8:
+            alpha = true;
+            break;
+        default:
+            alpha = false;
+            break;
+        }
+        size = dmabufBuffer->size();
     } else if (parent) {
         EGLDisplay eglDisplay = parent->global()->display()->eglDisplay();
         static bool resolved = false;
@@ -275,6 +320,11 @@ wl_shm_buffer *BufferInterface::shmBuffer()
     return d->shmBuffer;
 }
 
+LinuxDmabuf::Buffer *BufferInterface::linuxDmabufBuffer()
+{
+    return d->dmabufBuffer;
+}
+
 wl_resource *BufferInterface::resource() const
 {
     return d->buffer;
diff --git a/src/server/buffer_interface.h b/src/server/buffer_interface.h
index 1a764e1..8214e36 100644
--- a/src/server/buffer_interface.h
+++ b/src/server/buffer_interface.h
@@ -34,6 +34,10 @@ namespace Server
 {
 class SurfaceInterface;
 
+namespace LinuxDmabuf
+{
+    class Buffer;
+}
 
 /**
  * @brief Reference counted representation of a Wayland buffer on Server side.
@@ -104,6 +108,10 @@ public:
      * @returns The native wl_shm_buffer if the BufferInterface represents a shared \
                memory buffer, otherwise @c nullptr.
      **/
     wl_shm_buffer *shmBuffer();
+    /**
+     * Returns a pointer to the LinuxDmabuf::Buffer when the buffer is a dmabuf \
buffer, and nullptr otherwise. +     */
+    LinuxDmabuf::Buffer *linuxDmabufBuffer();
     /**
      * @returns the native wl_resource wrapped by this BufferInterface.
      **/
diff --git a/src/server/display.cpp b/src/server/display.cpp
index 391db06..ef54237 100644
--- a/src/server/display.cpp
+++ b/src/server/display.cpp
@@ -49,6 +49,7 @@ License along with this library.  If not, see \
<http://www.gnu.org/licenses/>.  #include "xdgshell_v6_interface_p.h"
 #include "appmenu_interface.h"
 #include "server_decoration_palette_interface.h"
+#include "linuxdmabuf_v1_interface.h"
 
 #include <QCoreApplication>
 #include <QDebug>
@@ -449,6 +450,13 @@ ServerSideDecorationPaletteManagerInterface \
*Display::createServerSideDecoration  return b;
 }
 
+LinuxDmabufUnstableV1Interface *Display::createLinuxDmabufInterface(QObject *parent)
+{
+    auto b = new LinuxDmabufUnstableV1Interface(this, parent);
+    connect(this, &Display::aboutToTerminate, b, [this, b] { delete b; });
+    return b;
+}
+
 void Display::createShm()
 {
     Q_ASSERT(d->display);
diff --git a/src/server/display.h b/src/server/display.h
index 69e03b7..da77d44 100644
--- a/src/server/display.h
+++ b/src/server/display.h
@@ -85,6 +85,7 @@ class PointerConstraintsInterface;
 class XdgForeignInterface;
 class AppMenuManagerInterface;
 class ServerSideDecorationPaletteManagerInterface;
+class LinuxDmabufUnstableV1Interface;
 
 /**
  * @brief Class holding the Wayland server display loop.
@@ -256,6 +257,12 @@ public:
      **/
     ServerSideDecorationPaletteManagerInterface \
*createServerSideDecorationPaletteManager(QObject *parent = nullptr);  
+    /**
+     * Creates the LinuxDmabufUnstableV1Interface in interface @p version.
+     *
+     * @returns A pointer to the created interface
+     **/
+    LinuxDmabufUnstableV1Interface *createLinuxDmabufInterface(QObject *parent = \
nullptr);  
     /**
      * Gets the ClientConnection for the given @p client.
diff --git a/src/server/drm_fourcc.h b/src/server/drm_fourcc.h
new file mode 100644
index 0000000..70d492a
--- /dev/null
+++ b/src/server/drm_fourcc.h
@@ -0,0 +1,414 @@
+/*
+ * Copyright 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef DRM_FOURCC_H
+#define DRM_FOURCC_H
+
+//#include "drm.h"
+
+// These typedefs are copied from drm.h
+typedef uint32_t __u32;
+typedef uint64_t __u64;
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \
+				 ((__u32)(c) << 16) | ((__u32)(d) << 24))
+
+#define DRM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little \
endian */ +
+/* color index */
+#define DRM_FORMAT_C8		fourcc_code('C', '8', ' ', ' ') /* [7:0] C */
+
+/* 8 bpp Red */
+#define DRM_FORMAT_R8		fourcc_code('R', '8', ' ', ' ') /* [7:0] R */
+
+/* 16 bpp Red */
+#define DRM_FORMAT_R16		fourcc_code('R', '1', '6', ' ') /* [15:0] R little endian */
+
+/* 16 bpp RG */
+#define DRM_FORMAT_RG88		fourcc_code('R', 'G', '8', '8') /* [15:0] R:G 8:8 little \
endian */ +#define DRM_FORMAT_GR88		fourcc_code('G', 'R', '8', '8') /* [15:0] G:R 8:8 \
little endian */ +
+/* 32 bpp RG */
+#define DRM_FORMAT_RG1616	fourcc_code('R', 'G', '3', '2') /* [31:0] R:G 16:16 little \
endian */ +#define DRM_FORMAT_GR1616	fourcc_code('G', 'R', '3', '2') /* [31:0] G:R \
16:16 little endian */ +
+/* 8 bpp RGB */
+#define DRM_FORMAT_RGB332	fourcc_code('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */
+#define DRM_FORMAT_BGR233	fourcc_code('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */
+
+/* 16 bpp RGB */
+#define DRM_FORMAT_XRGB4444	fourcc_code('X', 'R', '1', '2') /* [15:0] x:R:G:B \
4:4:4:4 little endian */ +#define DRM_FORMAT_XBGR4444	fourcc_code('X', 'B', '1', '2') \
/* [15:0] x:B:G:R 4:4:4:4 little endian */ +#define \
DRM_FORMAT_RGBX4444	fourcc_code('R', 'X', '1', '2') /* [15:0] R:G:B:x 4:4:4:4 little \
endian */ +#define DRM_FORMAT_BGRX4444	fourcc_code('B', 'X', '1', '2') /* [15:0] \
B:G:R:x 4:4:4:4 little endian */ +
+#define DRM_FORMAT_ARGB4444	fourcc_code('A', 'R', '1', '2') /* [15:0] A:R:G:B \
4:4:4:4 little endian */ +#define DRM_FORMAT_ABGR4444	fourcc_code('A', 'B', '1', '2') \
/* [15:0] A:B:G:R 4:4:4:4 little endian */ +#define \
DRM_FORMAT_RGBA4444	fourcc_code('R', 'A', '1', '2') /* [15:0] R:G:B:A 4:4:4:4 little \
endian */ +#define DRM_FORMAT_BGRA4444	fourcc_code('B', 'A', '1', '2') /* [15:0] \
B:G:R:A 4:4:4:4 little endian */ +
+#define DRM_FORMAT_XRGB1555	fourcc_code('X', 'R', '1', '5') /* [15:0] x:R:G:B \
1:5:5:5 little endian */ +#define DRM_FORMAT_XBGR1555	fourcc_code('X', 'B', '1', '5') \
/* [15:0] x:B:G:R 1:5:5:5 little endian */ +#define \
DRM_FORMAT_RGBX5551	fourcc_code('R', 'X', '1', '5') /* [15:0] R:G:B:x 5:5:5:1 little \
endian */ +#define DRM_FORMAT_BGRX5551	fourcc_code('B', 'X', '1', '5') /* [15:0] \
B:G:R:x 5:5:5:1 little endian */ +
+#define DRM_FORMAT_ARGB1555	fourcc_code('A', 'R', '1', '5') /* [15:0] A:R:G:B \
1:5:5:5 little endian */ +#define DRM_FORMAT_ABGR1555	fourcc_code('A', 'B', '1', '5') \
/* [15:0] A:B:G:R 1:5:5:5 little endian */ +#define \
DRM_FORMAT_RGBA5551	fourcc_code('R', 'A', '1', '5') /* [15:0] R:G:B:A 5:5:5:1 little \
endian */ +#define DRM_FORMAT_BGRA5551	fourcc_code('B', 'A', '1', '5') /* [15:0] \
B:G:R:A 5:5:5:1 little endian */ +
+#define DRM_FORMAT_RGB565	fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 \
little endian */ +#define DRM_FORMAT_BGR565	fourcc_code('B', 'G', '1', '6') /* [15:0] \
B:G:R 5:6:5 little endian */ +
+/* 24 bpp RGB */
+#define DRM_FORMAT_RGB888	fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little \
endian */ +#define DRM_FORMAT_BGR888	fourcc_code('B', 'G', '2', '4') /* [23:0] B:G:R \
little endian */ +
+/* 32 bpp RGB */
+#define DRM_FORMAT_XRGB8888	fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B \
8:8:8:8 little endian */ +#define DRM_FORMAT_XBGR8888	fourcc_code('X', 'B', '2', '4') \
/* [31:0] x:B:G:R 8:8:8:8 little endian */ +#define \
DRM_FORMAT_RGBX8888	fourcc_code('R', 'X', '2', '4') /* [31:0] R:G:B:x 8:8:8:8 little \
endian */ +#define DRM_FORMAT_BGRX8888	fourcc_code('B', 'X', '2', '4') /* [31:0] \
B:G:R:x 8:8:8:8 little endian */ +
+#define DRM_FORMAT_ARGB8888	fourcc_code('A', 'R', '2', '4') /* [31:0] A:R:G:B \
8:8:8:8 little endian */ +#define DRM_FORMAT_ABGR8888	fourcc_code('A', 'B', '2', '4') \
/* [31:0] A:B:G:R 8:8:8:8 little endian */ +#define \
DRM_FORMAT_RGBA8888	fourcc_code('R', 'A', '2', '4') /* [31:0] R:G:B:A 8:8:8:8 little \
endian */ +#define DRM_FORMAT_BGRA8888	fourcc_code('B', 'A', '2', '4') /* [31:0] \
B:G:R:A 8:8:8:8 little endian */ +
+#define DRM_FORMAT_XRGB2101010	fourcc_code('X', 'R', '3', '0') /* [31:0] x:R:G:B \
2:10:10:10 little endian */ +#define DRM_FORMAT_XBGR2101010	fourcc_code('X', 'B', \
'3', '0') /* [31:0] x:B:G:R 2:10:10:10 little endian */ +#define \
DRM_FORMAT_RGBX1010102	fourcc_code('R', 'X', '3', '0') /* [31:0] R:G:B:x 10:10:10:2 \
little endian */ +#define DRM_FORMAT_BGRX1010102	fourcc_code('B', 'X', '3', '0') /* \
[31:0] B:G:R:x 10:10:10:2 little endian */ +
+#define DRM_FORMAT_ARGB2101010	fourcc_code('A', 'R', '3', '0') /* [31:0] A:R:G:B \
2:10:10:10 little endian */ +#define DRM_FORMAT_ABGR2101010	fourcc_code('A', 'B', \
'3', '0') /* [31:0] A:B:G:R 2:10:10:10 little endian */ +#define \
DRM_FORMAT_RGBA1010102	fourcc_code('R', 'A', '3', '0') /* [31:0] R:G:B:A 10:10:10:2 \
little endian */ +#define DRM_FORMAT_BGRA1010102	fourcc_code('B', 'A', '3', '0') /* \
[31:0] B:G:R:A 10:10:10:2 little endian */ +
+/* packed YCbCr */
+#define DRM_FORMAT_YUYV		fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 \
8:8:8:8 little endian */ +#define DRM_FORMAT_YVYU		fourcc_code('Y', 'V', 'Y', 'U') /* \
[31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */ +#define \
DRM_FORMAT_UYVY		fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 \
little endian */ +#define DRM_FORMAT_VYUY		fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] \
Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */ +
+#define DRM_FORMAT_AYUV		fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 \
little endian */ +
+/*
+ * 2 plane RGB + A
+ * index 0 = RGB plane, same format as the corresponding non _A8 format has
+ * index 1 = A plane, [7:0] A
+ */
+#define DRM_FORMAT_XRGB8888_A8	fourcc_code('X', 'R', 'A', '8')
+#define DRM_FORMAT_XBGR8888_A8	fourcc_code('X', 'B', 'A', '8')
+#define DRM_FORMAT_RGBX8888_A8	fourcc_code('R', 'X', 'A', '8')
+#define DRM_FORMAT_BGRX8888_A8	fourcc_code('B', 'X', 'A', '8')
+#define DRM_FORMAT_RGB888_A8	fourcc_code('R', '8', 'A', '8')
+#define DRM_FORMAT_BGR888_A8	fourcc_code('B', '8', 'A', '8')
+#define DRM_FORMAT_RGB565_A8	fourcc_code('R', '5', 'A', '8')
+#define DRM_FORMAT_BGR565_A8	fourcc_code('B', '5', 'A', '8')
+
+/*
+ * 2 plane YCbCr
+ * index 0 = Y plane, [7:0] Y
+ * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
+ * or
+ * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
+ */
+#define DRM_FORMAT_NV12		fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb \
plane */ +#define DRM_FORMAT_NV21		fourcc_code('N', 'V', '2', '1') /* 2x2 subsampled \
Cb:Cr plane */ +#define DRM_FORMAT_NV16		fourcc_code('N', 'V', '1', '6') /* 2x1 \
subsampled Cr:Cb plane */ +#define DRM_FORMAT_NV61		fourcc_code('N', 'V', '6', '1') \
/* 2x1 subsampled Cb:Cr plane */ +#define DRM_FORMAT_NV24		fourcc_code('N', 'V', '2', \
'4') /* non-subsampled Cr:Cb plane */ +#define DRM_FORMAT_NV42		fourcc_code('N', 'V', \
'4', '2') /* non-subsampled Cb:Cr plane */ +
+/*
+ * 3 plane YCbCr
+ * index 0: Y plane, [7:0] Y
+ * index 1: Cb plane, [7:0] Cb
+ * index 2: Cr plane, [7:0] Cr
+ * or
+ * index 1: Cr plane, [7:0] Cr
+ * index 2: Cb plane, [7:0] Cb
+ */
+#define DRM_FORMAT_YUV410	fourcc_code('Y', 'U', 'V', '9') /* 4x4 subsampled Cb (1) \
and Cr (2) planes */ +#define DRM_FORMAT_YVU410	fourcc_code('Y', 'V', 'U', '9') /* \
4x4 subsampled Cr (1) and Cb (2) planes */ +#define \
DRM_FORMAT_YUV411	fourcc_code('Y', 'U', '1', '1') /* 4x1 subsampled Cb (1) and Cr (2) \
planes */ +#define DRM_FORMAT_YVU411	fourcc_code('Y', 'V', '1', '1') /* 4x1 \
subsampled Cr (1) and Cb (2) planes */ +#define DRM_FORMAT_YUV420	fourcc_code('Y', \
'U', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */ +#define \
DRM_FORMAT_YVU420	fourcc_code('Y', 'V', '1', '2') /* 2x2 subsampled Cr (1) and Cb (2) \
planes */ +#define DRM_FORMAT_YUV422	fourcc_code('Y', 'U', '1', '6') /* 2x1 \
subsampled Cb (1) and Cr (2) planes */ +#define DRM_FORMAT_YVU422	fourcc_code('Y', \
'V', '1', '6') /* 2x1 subsampled Cr (1) and Cb (2) planes */ +#define \
DRM_FORMAT_YUV444	fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) \
planes */ +#define DRM_FORMAT_YVU444	fourcc_code('Y', 'V', '2', '4') /* \
non-subsampled Cr (1) and Cb (2) planes */ +
+
+/*
+ * Format Modifiers:
+ *
+ * Format modifiers describe, typically, a re-ordering or modification
+ * of the data in a plane of an FB.  This can be used to express tiled/
+ * swizzled formats, or compression, or a combination of the two.
+ *
+ * The upper 8 bits of the format modifier are a vendor-id as assigned
+ * below.  The lower 56 bits are assigned as vendor sees fit.
+ */
+
+/* Vendor Ids: */
+#define DRM_FORMAT_MOD_NONE           0
+#define DRM_FORMAT_MOD_VENDOR_NONE    0
+#define DRM_FORMAT_MOD_VENDOR_INTEL   0x01
+#define DRM_FORMAT_MOD_VENDOR_AMD     0x02
+#define DRM_FORMAT_MOD_VENDOR_NV      0x03
+#define DRM_FORMAT_MOD_VENDOR_SAMSUNG 0x04
+#define DRM_FORMAT_MOD_VENDOR_QCOM    0x05
+#define DRM_FORMAT_MOD_VENDOR_VIVANTE 0x06
+#define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07
+/* add more to the end as needed */
+
+#define DRM_FORMAT_RESERVED	      ((1ULL << 56) - 1)
+
+#define fourcc_mod_code(vendor, val) \
+	((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL))
+
+/*
+ * Format Modifier tokens:
+ *
+ * When adding a new token please document the layout with a code comment,
+ * similar to the fourcc codes above. drm_fourcc.h is considered the
+ * authoritative source for all of these.
+ */
+
+/*
+ * Invalid Modifier
+ *
+ * This modifier can be used as a sentinel to terminate the format modifiers
+ * list, or to initialize a variable with an invalid modifier. It might also be
+ * used to report an error back to userspace for certain APIs.
+ */
+#define DRM_FORMAT_MOD_INVALID	fourcc_mod_code(NONE, DRM_FORMAT_RESERVED)
+
+/*
+ * Linear Layout
+ *
+ * Just plain linear layout. Note that this is different from no specifying any
+ * modifier (e.g. not setting DRM_MODE_FB_MODIFIERS in the DRM_ADDFB2 ioctl),
+ * which tells the driver to also take driver-internal information into account
+ * and so might actually result in a tiled framebuffer.
+ */
+#define DRM_FORMAT_MOD_LINEAR	fourcc_mod_code(NONE, 0)
+
+/* Intel framebuffer modifiers */
+
+/*
+ * Intel X-tiling layout
+ *
+ * This is a tiled layout using 4Kb tiles (except on gen2 where the tiles 2Kb)
+ * in row-major layout. Within the tile bytes are laid out row-major, with
+ * a platform-dependent stride. On top of that the memory can apply
+ * platform-depending swizzling of some higher address bits into bit6.
+ *
+ * This format is highly platforms specific and not useful for cross-driver
+ * sharing. It exists since on a given platform it does uniquely identify the
+ * layout in a simple way for i915-specific userspace.
+ */
+#define I915_FORMAT_MOD_X_TILED	fourcc_mod_code(INTEL, 1)
+
+/*
+ * Intel Y-tiling layout
+ *
+ * This is a tiled layout using 4Kb tiles (except on gen2 where the tiles 2Kb)
+ * in row-major layout. Within the tile bytes are laid out in OWORD (16 bytes)
+ * chunks column-major, with a platform-dependent height. On top of that the
+ * memory can apply platform-depending swizzling of some higher address bits
+ * into bit6.
+ *
+ * This format is highly platforms specific and not useful for cross-driver
+ * sharing. It exists since on a given platform it does uniquely identify the
+ * layout in a simple way for i915-specific userspace.
+ */
+#define I915_FORMAT_MOD_Y_TILED	fourcc_mod_code(INTEL, 2)
+
+/*
+ * Intel Yf-tiling layout
+ *
+ * This is a tiled layout using 4Kb tiles in row-major layout.
+ * Within the tile pixels are laid out in 16 256 byte units / sub-tiles which
+ * are arranged in four groups (two wide, two high) with column-major layout.
+ * Each group therefore consits out of four 256 byte units, which are also laid
+ * out as 2x2 column-major.
+ * 256 byte units are made out of four 64 byte blocks of pixels, producing
+ * either a square block or a 2:1 unit.
+ * 64 byte blocks of pixels contain four pixel rows of 16 bytes, where the width
+ * in pixel depends on the pixel depth.
+ */
+#define I915_FORMAT_MOD_Yf_TILED fourcc_mod_code(INTEL, 3)
+
+/*
+ * Intel color control surface (CCS) for render compression
+ *
+ * The framebuffer format must be one of the 8:8:8:8 RGB formats.
+ * The main surface will be plane index 0 and must be Y/Yf-tiled,
+ * the CCS will be plane index 1.
+ *
+ * Each CCS tile matches a 1024x512 pixel area of the main surface.
+ * To match certain aspects of the 3D hardware the CCS is
+ * considered to be made up of normal 128Bx32 Y tiles, Thus
+ * the CCS pitch must be specified in multiples of 128 bytes.
+ *
+ * In reality the CCS tile appears to be a 64Bx64 Y tile, composed
+ * of QWORD (8 bytes) chunks instead of OWORD (16 bytes) chunks.
+ * But that fact is not relevant unless the memory is accessed
+ * directly.
+ */
+#define I915_FORMAT_MOD_Y_TILED_CCS	fourcc_mod_code(INTEL, 4)
+#define I915_FORMAT_MOD_Yf_TILED_CCS	fourcc_mod_code(INTEL, 5)
+
+/*
+ * Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks
+ *
+ * Macroblocks are laid in a Z-shape, and each pixel data is following the
+ * standard NV12 style.
+ * As for NV12, an image is the result of two frame buffers: one for Y,
+ * one for the interleaved Cb/Cr components (1/2 the height of the Y buffer).
+ * Alignment requirements are (for each buffer):
+ * - multiple of 128 pixels for the width
+ * - multiple of  32 pixels for the height
+ *
+ * For more information: see https://linuxtv.org/downloads/v4l-dvb-apis/re32.html
+ */
+#define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE	fourcc_mod_code(SAMSUNG, 1)
+
+/* Vivante framebuffer modifiers */
+
+/*
+ * Vivante 4x4 tiling layout
+ *
+ * This is a simple tiled layout using tiles of 4x4 pixels in a row-major
+ * layout.
+ */
+#define DRM_FORMAT_MOD_VIVANTE_TILED		fourcc_mod_code(VIVANTE, 1)
+
+/*
+ * Vivante 64x64 super-tiling layout
+ *
+ * This is a tiled layout using 64x64 pixel super-tiles, where each super-tile
+ * contains 8x4 groups of 2x4 tiles of 4x4 pixels (like above) each, all in row-
+ * major layout.
+ *
+ * For more information: see
+ * https://github.com/etnaviv/etna_viv/blob/master/doc/hardware.md#texture-tiling
+ */
+#define DRM_FORMAT_MOD_VIVANTE_SUPER_TILED	fourcc_mod_code(VIVANTE, 2)
+
+/*
+ * Vivante 4x4 tiling layout for dual-pipe
+ *
+ * Same as the 4x4 tiling layout, except every second 4x4 pixel tile starts at a
+ * different base address. Offsets from the base addresses are therefore halved
+ * compared to the non-split tiled layout.
+ */
+#define DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED	fourcc_mod_code(VIVANTE, 3)
+
+/*
+ * Vivante 64x64 super-tiling layout for dual-pipe
+ *
+ * Same as the 64x64 super-tiling layout, except every second 4x4 pixel tile
+ * starts at a different base address. Offsets from the base addresses are
+ * therefore halved compared to the non-split super-tiled layout.
+ */
+#define DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED fourcc_mod_code(VIVANTE, 4)
+
+/* NVIDIA Tegra frame buffer modifiers */
+
+/*
+ * Some modifiers take parameters, for example the number of vertical GOBs in
+ * a block. Reserve the lower 32 bits for parameters
+ */
+#define __fourcc_mod_tegra_mode_shift 32
+#define fourcc_mod_tegra_code(val, params) \
+	fourcc_mod_code(NV, ((((__u64)val) << __fourcc_mod_tegra_mode_shift) | params))
+#define fourcc_mod_tegra_mod(m) \
+	(m & ~((1ULL << __fourcc_mod_tegra_mode_shift) - 1))
+#define fourcc_mod_tegra_param(m) \
+	(m & ((1ULL << __fourcc_mod_tegra_mode_shift) - 1))
+
+/*
+ * Tegra Tiled Layout, used by Tegra 2, 3 and 4.
+ *
+ * Pixels are arranged in simple tiles of 16 x 16 bytes.
+ */
+#define NV_FORMAT_MOD_TEGRA_TILED fourcc_mod_tegra_code(1, 0)
+
+/*
+ * Tegra 16Bx2 Block Linear layout, used by TK1/TX1
+ *
+ * Pixels are arranged in 64x8 Groups Of Bytes (GOBs). GOBs are then stacked
+ * vertically by a power of 2 (1 to 32 GOBs) to form a block.
+ *
+ * Within a GOB, data is ordered as 16B x 2 lines sectors laid in Z-shape.
+ *
+ * Parameter 'v' is the log2 encoding of the number of GOBs stacked vertically.
+ * Valid values are:
+ *
+ * 0 == ONE_GOB
+ * 1 == TWO_GOBS
+ * 2 == FOUR_GOBS
+ * 3 == EIGHT_GOBS
+ * 4 == SIXTEEN_GOBS
+ * 5 == THIRTYTWO_GOBS
+ *
+ * Chapter 20 "Pixel Memory Formats" of the Tegra X1 TRM describes this format
+ * in full detail.
+ */
+#define NV_FORMAT_MOD_TEGRA_16BX2_BLOCK(v) fourcc_mod_tegra_code(2, v)
+
+/*
+ * Broadcom VC4 "T" format
+ *
+ * This is the primary layout that the V3D GPU can texture from (it
+ * can't do linear).  The T format has:
+ *
+ * - 64b utiles of pixels in a raster-order grid according to cpp.  It's 4x4
+ *   pixels at 32 bit depth.
+ *
+ * - 1k subtiles made of a 4x4 raster-order grid of 64b utiles (so usually
+ *   16x16 pixels).
+ *
+ * - 4k tiles made of a 2x2 grid of 1k subtiles (so usually 32x32 pixels).  On
+ *   even 4k tile rows, they're arranged as (BL, TL, TR, BR), and on odd rows
+ *   they're (TR, BR, BL, TL), where bottom left is start of memory.
+ *
+ * - an image made of 4k tiles in rows either left-to-right (even rows of 4k
+ *   tiles) or right-to-left (odd rows of 4k tiles).
+ */
+#define DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED fourcc_mod_code(BROADCOM, 1)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* DRM_FOURCC_H */
diff --git a/src/server/linuxdmabuf_v1_interface.cpp \
b/src/server/linuxdmabuf_v1_interface.cpp new file mode 100644
index 0000000..c5fa147
--- /dev/null
+++ b/src/server/linuxdmabuf_v1_interface.cpp
@@ -0,0 +1,482 @@
+/********************************************************************
+Copyright  © 2018 Fredrik Höglund <fredrik@kde.org>
+
+Based on the libweston implementation,
+Copyright  © 2014, 2015 Collabora, Ltd.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) version 3, or any
+later version accepted by the membership of KDE e.V. (or its
+successor approved by the membership of KDE e.V.), which shall
+act as a proxy defined in Section 6 of version 3 of the license.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+
+#include <KWayland/Server/kwaylandserver_export.h>
+#include "linuxdmabuf_v1_interface.h"
+#include "wayland-linux-dmabuf-unstable-v1-server-protocol.h"
+#include "wayland-server-protocol.h"
+#include "global_p.h"
+
+#include "drm_fourcc.h"
+
+#include <QVector>
+
+#include <unistd.h>
+#include <assert.h>
+
+#include <array>
+
+
+namespace KWayland
+{
+
+namespace Server
+{
+
+
+class LinuxDmabufParams
+{
+public:
+    LinuxDmabufParams(LinuxDmabufUnstableV1Interface *dmabufInterface, wl_client \
*client, uint32_t version, uint32_t id); +    ~LinuxDmabufParams();
+
+    template <typename... Args>
+    void postError(uint32_t code, const char *msg, Args... args) {
+        wl_resource_post_error(m_resource, code, msg, args...);
+    }
+
+    void postNoMemory() { wl_resource_post_no_memory(m_resource); }
+
+    wl_resource *resource() const { return m_resource; }
+
+    void add(int fd, uint32_t plane_idx, uint32_t offset, uint32_t stride, uint64_t \
modifier); +    void create(wl_client *client, uint32_t bufferId, const QSize &size, \
uint32_t format, uint32_t flags); +
+    static void destroy(wl_client *client, wl_resource *resource);
+    static void add(wl_client *client, wl_resource *resource, int fd, uint32_t \
plane_idx, uint32_t offset, uint32_t stride, uint32_t modifier_hi, uint32_t \
modifier_lo); +    static void create(wl_client *client, wl_resource *resource, int \
width, int height, uint32_t format, uint32_t flags); +    static void \
createImmed(wl_client *client, wl_resource *resource, uint32_t new_id, int width, int \
height, uint32_t format, uint32_t flags); +
+private:
+    static const struct zwp_linux_buffer_params_v1_interface s_interface;
+
+    wl_resource *m_resource;
+    LinuxDmabufUnstableV1Interface *m_dmabufInterface;
+    std::array<LinuxDmabuf::Plane, 4> m_planes;
+    size_t m_planeCount = 0;
+    bool m_bufferCreated = false;
+};
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+const struct zwp_linux_buffer_params_v1_interface LinuxDmabufParams::s_interface = {
+    destroy,
+    add,
+    create,
+    createImmed
+};
+#endif
+
+
+LinuxDmabufParams::LinuxDmabufParams(LinuxDmabufUnstableV1Interface \
*dmabufInterface, wl_client *client, uint32_t version, uint32_t id) +    : \
m_dmabufInterface(dmabufInterface) +{
+    m_resource = wl_resource_create(client, &zwp_linux_buffer_params_v1_interface, \
version, id); +    if (!m_resource) {
+        return;
+    }
+
+    wl_resource_set_implementation(m_resource, &s_interface, this,
+                                   [](wl_resource *resource) {
+                                       delete static_cast<LinuxDmabufParams \
*>(wl_resource_get_user_data(resource)); +                                   });
+
+    for (auto &plane : m_planes) {
+        plane.fd = -1;
+        plane.offset = 0;
+        plane.stride = 0;
+        plane.modifier = 0;
+    }
+}
+
+
+LinuxDmabufParams::~LinuxDmabufParams()
+{
+    // Close the file descriptors
+    for (auto &plane : m_planes) {
+        if (plane.fd != -1) {
+            ::close(plane.fd);
+        }
+    }
+}
+
+
+void LinuxDmabufParams::create(wl_client *client, uint32_t bufferId, const QSize \
&size, uint32_t format, uint32_t flags) +{
+    // Validate the parameters
+    // -----------------------
+    const uint32_t width = size.width();
+    const uint32_t height = size.height();
+
+    if (m_bufferCreated) {
+        postError(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED,
+                  "params was already used to create a wl_buffer");
+        return;
+    }
+
+    if (m_planeCount == 0) {
+        postError(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE,
+                  "no dmabuf has been added to the params");
+        return;
+    }
+
+    // Check for holes in the dmabufs set (e.g. [0, 1, 3])
+    for (uint32_t i = 0; i < m_planeCount; i++) {
+        if (m_planes[i].fd != -1)
+            continue;
+
+        postError(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE,
+                  "no dmabuf has been added for plane %i", i);
+        return;
+    }
+
+    if (width < 1 || height < 1) {
+        postError(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_DIMENSIONS,
+                  "invalid width %d or height %d", width, height);
+        return;
+    }
+
+    for (uint32_t i = 0; i < m_planeCount; i++) {
+        auto &plane = m_planes[i];
+
+        if (uint64_t(plane.offset) + plane.stride > UINT32_MAX) {
+            postError(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
+                      "size overflow for plane %i", i);
+            return;
+        }
+
+        if (i == 0 && uint64_t(plane.offset) + plane.stride * height > UINT32_MAX) {
+            postError(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
+                      "size overflow for plane %i", i);
+            return;
+        }
+
+        // Don't report an error as it might be caused by the kernel not supporting \
seeking on dmabuf +        off_t size = ::lseek(plane.fd, 0, SEEK_END);
+        if (size == -1)
+            continue;
+
+        if (plane.offset >= size) {
+            postError(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
+                      "invalid offset %i for plane %i",
+                      plane.offset, i);
+            return;
+        }
+
+        if (plane.offset + plane.stride > size) {
+            postError(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
+                      "invalid stride %i for plane %i",
+                      plane.stride, i);
+            return;
+        }
+
+        // Only valid for first plane as other planes might be
+        // sub-sampled according to fourcc format
+        if (i == 0 && plane.offset + plane.stride * height > size) {
+            postError(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
+                      "invalid buffer stride or height for plane %i", i);
+            return;
+        }
+    }
+
+
+    // Import the buffer
+    // -----------------
+    QVector<LinuxDmabuf::Plane> planes;
+    planes.reserve(m_planeCount);
+    for (uint32_t i = 0; i < m_planeCount; i++)
+        planes << m_planes[i];
+
+    LinuxDmabuf::Buffer *buffer = m_dmabufInterface->bridge()->importBuffer(planes, \
format, size, (LinuxDmabuf::Flags) flags); +    if (buffer) {
+        // The buffer has ownership of the file descriptors now
+        for (auto &plane : m_planes) {
+            plane.fd = -1;
+        }
+
+        wl_resource *resource = wl_resource_create(client, &wl_buffer_interface, 1, \
bufferId); +        if (!resource ) {
+            postNoMemory();
+            delete buffer;
+            return;
+        }
+
+        wl_resource_set_implementation(resource, \
m_dmabufInterface->bufferImplementation(), buffer, +                                  \
[](wl_resource *resource) { // Destructor +                                           \
delete static_cast<LinuxDmabuf::Buffer *>(wl_resource_get_user_data(resource)); +     \
}); +
+        // XXX Do we need this?
+        //buffer->setResource(resource);
+
+        // Send a 'created' event when the request is not for an immediate import, \
i.e. bufferId is zero +        if (bufferId == 0) {
+            zwp_linux_buffer_params_v1_send_created(m_resource, resource);
+        }
+
+        m_bufferCreated = true;
+    } else {
+        if (bufferId == 0) {
+            zwp_linux_buffer_params_v1_send_failed(m_resource);
+        } else {
+            // since the behavior is left implementation defined by the
+            // protocol in case of create_immed failure due to an unknown cause,
+            // we choose to treat it as a fatal error and immediately kill the
+            // client instead of creating an invalid handle and waiting for it
+            // to be used.
+            postError(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_WL_BUFFER,
+                      "importing the supplied dmabufs failed");
+        }
+    }
+}
+
+
+void LinuxDmabufParams::add(int fd, uint32_t plane_idx, uint32_t offset, uint32_t \
stride, uint64_t modifier) +{
+    if (m_bufferCreated) {
+        postError(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED,
+                  "params was already used to create a wl_buffer");
+        ::close(fd);
+        return;
+    }
+
+    if (plane_idx >= m_planes.size()) {
+        postError(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX,
+                  "plane index %u is too high", plane_idx);
+        ::close(fd);
+        return;
+    }
+
+    auto &plane = m_planes[plane_idx];
+
+    if (plane.fd != -1) {
+        postError(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_SET,
+                  "a dmabuf has already been added for plane %u",
+                   plane_idx);
+        ::close(fd);
+        return;
+    }
+
+    plane.fd = fd;
+    plane.offset = offset;
+    plane.stride = stride;
+    plane.modifier = modifier;
+
+    m_planeCount++;
+}
+
+
+
+// --------------------------------------------------------------------
+
+
+
+void LinuxDmabufParams::destroy(wl_client *client, wl_resource *resource)
+{
+    Q_UNUSED(client)
+    wl_resource_destroy(resource);
+}
+
+
+void LinuxDmabufParams::add(wl_client *client, wl_resource *resource,
+                            int fd, uint32_t plane_idx,
+                            uint32_t offset, uint32_t stride,
+                            uint32_t modifier_hi, uint32_t modifier_lo)
+{
+    Q_UNUSED(client)
+
+    LinuxDmabufParams *params = static_cast<LinuxDmabufParams \
*>(wl_resource_get_user_data(resource)); +    assert(params->m_resource == resource);
+    params->add(fd, plane_idx, offset, stride, (uint64_t(modifier_hi) << 32) | \
modifier_lo); +}
+
+
+void LinuxDmabufParams::create(wl_client *client, wl_resource *resource,
+                               int width, int height, uint32_t format, uint32_t \
flags) +{
+    Q_UNUSED(client)
+
+    LinuxDmabufParams *params = static_cast<LinuxDmabufParams \
*>(wl_resource_get_user_data(resource)); +    assert(params->m_resource == resource);
+    params->create(client, 0, QSize(width, height), format, flags);
+}
+
+
+void LinuxDmabufParams::createImmed(wl_client *client, wl_resource *resource,
+                                    uint32_t new_id, int width, int height,
+                                    uint32_t format, uint32_t flags)
+{
+    Q_UNUSED(client)
+
+    LinuxDmabufParams *params = static_cast<LinuxDmabufParams \
*>(wl_resource_get_user_data(resource)); +    assert(params->m_resource == resource);
+    params->create(client, new_id, QSize(width, height), format, flags);
+}
+
+
+
+// --------------------------------------------------------------------
+
+
+
+class LinuxDmabufUnstableV1Interface::Private : public Global::Private
+{
+public:
+    Private(LinuxDmabufUnstableV1Interface *q, Display *display);
+    ~Private();
+
+    static const struct wl_buffer_interface *bufferImplementation() { return \
&s_bufferImplementation; } +    LinuxDmabufUnstableV1Interface::Bridge *bridge;
+    LinuxDmabufUnstableV1Interface * const q;
+    static const uint32_t s_version;
+
+    void bind(wl_client *client, uint32_t version, uint32_t id) override final;
+    void createParams(wl_client *client, wl_resource *resource, uint32_t id);
+
+    static void unbind(wl_client *client, wl_resource *resource);
+    static void createParamsCallback(wl_client *client, wl_resource *resource, \
uint32_t id); +
+private:
+    static const struct zwp_linux_dmabuf_v1_interface s_implementation;
+    static const struct wl_buffer_interface s_bufferImplementation;
+};
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+const struct zwp_linux_dmabuf_v1_interface \
LinuxDmabufUnstableV1Interface::Private::s_implementation = { +    [](wl_client *, \
wl_resource *resource) { wl_resource_destroy(resource); }, // unbind +    \
createParamsCallback +};
+
+
+const struct wl_buffer_interface \
LinuxDmabufUnstableV1Interface::Private::s_bufferImplementation = { +    [](wl_client \
*, wl_resource *resource) { wl_resource_destroy(resource); } // destroy +};
+
+const uint32_t LinuxDmabufUnstableV1Interface::Private::s_version = 3;
+#endif
+
+
+LinuxDmabufUnstableV1Interface::Private::Private(LinuxDmabufUnstableV1Interface *q, \
Display *display) +    : Global::Private(display, &zwp_linux_dmabuf_v1_interface, \
s_version), +      q(q)
+{
+}
+
+
+LinuxDmabufUnstableV1Interface::Private::~Private()
+{
+}
+
+
+void LinuxDmabufUnstableV1Interface::Private::bind(wl_client *client, uint32_t \
version, uint32_t id) +{
+    wl_resource *resource = wl_resource_create(client, \
&zwp_linux_dmabuf_v1_interface, std::min(s_version, version), id); +    if \
(!resource) { +        wl_client_post_no_memory(client);
+        return;
+    }
+
+    wl_resource_set_implementation(resource, &s_implementation, this, nullptr);
+
+    // Send formats & modifiers
+    // ------------------------
+    const QVector<uint32_t> formats = bridge->supportedFormats();
+    for (uint32_t format : formats) {
+        QVector<uint64_t> modifiers = bridge->supportedModifiers(format);
+        if (modifiers.isEmpty()) {
+            modifiers << DRM_FORMAT_MOD_INVALID;
+        }
+
+        for (uint64_t modifier : qAsConst(modifiers)) {
+            if (version >= ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) {
+                const uint32_t modifier_lo = modifier & 0xFFFFFFFF;
+                const uint32_t modifier_hi = modifier >> 32;
+                zwp_linux_dmabuf_v1_send_modifier(resource, format, modifier_hi, \
modifier_lo); +            } else if (modifier == DRM_FORMAT_MOD_LINEAR || modifier \
== DRM_FORMAT_MOD_INVALID) { +                \
zwp_linux_dmabuf_v1_send_format(resource, format); +            }
+        }
+    }
+}
+
+
+void LinuxDmabufUnstableV1Interface::Private::createParams(wl_client *client, \
wl_resource *resource, uint32_t id) +{
+    LinuxDmabufParams *params = new LinuxDmabufParams(q, client, \
wl_resource_get_version(resource), id); +    if (!params->resource()) {
+        wl_resource_post_no_memory(resource);
+        delete params;
+    }
+}
+
+
+void LinuxDmabufUnstableV1Interface::Private::createParamsCallback(wl_client \
*client, wl_resource *resource, uint32_t id) +{
+    LinuxDmabufUnstableV1Interface::Private *global = \
static_cast<LinuxDmabufUnstableV1Interface::Private \
*>(wl_resource_get_user_data(resource)); +    global->createParams(client, resource, \
id); +}
+
+
+
+// --------------------------------------------------------------------
+
+
+
+LinuxDmabufUnstableV1Interface::LinuxDmabufUnstableV1Interface(Display *display, \
QObject *parent) +    : Global(new Private(this, display), parent)
+{
+}
+
+
+LinuxDmabufUnstableV1Interface::~LinuxDmabufUnstableV1Interface()
+{
+}
+
+
+void LinuxDmabufUnstableV1Interface::setBridge(LinuxDmabufUnstableV1Interface::Bridge \
*bridge) +{
+    d_func()->bridge = bridge;
+}
+
+
+LinuxDmabufUnstableV1Interface::Bridge *LinuxDmabufUnstableV1Interface::bridge() \
const +{
+    return d_func()->bridge;
+}
+
+
+const struct wl_buffer_interface \
*LinuxDmabufUnstableV1Interface::bufferImplementation() +{
+    return LinuxDmabufUnstableV1Interface::Private::bufferImplementation();
+}
+
+
+LinuxDmabufUnstableV1Interface::Private *LinuxDmabufUnstableV1Interface::d_func() \
const +{
+    return reinterpret_cast<Private*>(d.data());
+}
+
+
+} // namespace Server
+} // namespace Wayland
diff --git a/src/server/linuxdmabuf_v1_interface.h \
b/src/server/linuxdmabuf_v1_interface.h new file mode 100644
index 0000000..ecbd82d
--- /dev/null
+++ b/src/server/linuxdmabuf_v1_interface.h
@@ -0,0 +1,181 @@
+/********************************************************************
+Copyright  © 2018 Fredrik Höglund <fredrik@kde.org>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) version 3, or any
+later version accepted by the membership of KDE e.V. (or its
+successor approved by the membership of KDE e.V.), which shall
+act as a proxy defined in Section 6 of version 3 of the license.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+
+#ifndef WAYLAND_SERVER_LINUXDMABUF_INTERFACE_H
+#define WAYLAND_SERVER_LINUXDMABUF_INTERFACE_H
+
+#include <KWayland/Server/kwaylandserver_export.h>
+#include "global.h"
+#include "resource.h"
+
+#include <QSize>
+
+
+struct wl_buffer_interface;
+
+namespace KWayland
+{
+
+namespace Server
+{
+
+namespace LinuxDmabuf
+{
+    enum Flag {
+        YInverted        = (1 << 0), /// Contents are y-inverted
+        Interlaced       = (1 << 1), /// Content is interlaced
+        BottomFieldFirst = (1 << 2)  /// Bottom field first
+    };
+
+    Q_DECLARE_FLAGS(Flags, Flag)
+
+    /**
+     * Represents a plane in the buffer
+     */
+    struct Plane {
+        int fd;              /// The dmabuf file descriptor
+        uint32_t offset;     /// The offset from the start of buffer
+        uint32_t stride;     /// The distance from the start of a row to the next \
row in bytes +        uint64_t modifier;   /// The layout modifier
+    };
+
+    /**
+     * The base class for linux-dmabuf buffers
+     *
+     * Compositors should reimplement this class to store objects specific
+     * to the underlying graphics stack.
+     */
+    class Buffer {
+    public:
+        /**
+         * Creates a new Buffer.
+         */
+        Buffer(uint32_t format, const QSize &size) : m_format(format), m_size(size) \
{} +
+        /**
+         * Destroys the Buffer.
+         */
+        virtual ~Buffer() = default;
+
+        /**
+         * Returns the DRM format code for the buffer.
+         */
+        uint32_t format() const { return m_format; }
+
+        /**
+         * Returns the size of the buffer.
+         */
+        QSize size() const { return m_size; }
+
+    private:
+        uint32_t m_format;
+        QSize m_size;
+    };
+}
+
+
+/**
+ * Represents the global zpw_linux_dmabuf_v1 interface.
+ *
+ * This interface provides a way for clients to create generic dmabuf based \
wl_buffers. + */
+class KWAYLANDSERVER_EXPORT LinuxDmabufUnstableV1Interface : public Global
+{
+    Q_OBJECT
+
+public:
+    /**
+     * The Bridge class provides an interface from the LinuxDmabufInterface to the \
compositor +     */
+    class Bridge {
+    public:
+        Bridge() = default;
+        virtual ~Bridge() = default;
+
+        /**
+         * Returns the DRM format codes supported by the compositor.
+         */
+        virtual QVector<uint32_t> supportedFormats() const = 0;
+
+        /**
+         * Returns the layout-modifiers supported for the given DRM format code.
+         */
+        virtual QVector<uint64_t> supportedModifiers(uint32_t format) const = 0;
+
+        /**
+         * Imports a linux-dmabuf buffer into the compositor.
+         *
+         * The returned buffer takes ownership of the file descriptor for each \
plane. +         * Note that it is the responsibility of the caller to close the file \
descriptors +         * when the import fails.
+         *
+         * @return The imported buffer on success, and nullptr otherwise.
+         */
+        virtual LinuxDmabuf::Buffer *importBuffer(const QVector<LinuxDmabuf::Plane> \
&planes, +                                                  uint32_t format,
+                                                  const QSize &size,
+                                                  LinuxDmabuf::Flags flags) = 0;
+    };
+
+    /**
+     * Destroys the LinuxDmabufUnstableV1Interface.
+     */
+    virtual ~LinuxDmabufUnstableV1Interface();
+
+    /**
+     * Sets the compositor bridge for the dmabuf interface.
+     */
+    void setBridge(Bridge *bridge);
+
+    /**
+     * Returns the compositor bridge for the dmabuf interface.
+     */
+    Bridge *bridge() const;
+
+    /**
+     * Returns the LinuxDmabufInterface for the given resource.
+     **/
+    static LinuxDmabufUnstableV1Interface *get(wl_resource *native);
+
+    /**
+     * Returns a pointer to the wl_buffer implementation for imported dmabufs.
+     */
+    static const struct wl_buffer_interface *bufferImplementation();
+
+private:
+    /**
+     * @internal
+     */
+    explicit LinuxDmabufUnstableV1Interface(Display *display, QObject *parent = \
nullptr); +    friend class Display;
+
+private:
+    class Private;
+    Private *d_func() const;
+};
+
+
+} // namespace Server
+} // namespace KWayland
+
+Q_DECLARE_METATYPE(KWayland::Server::LinuxDmabufUnstableV1Interface*)
+Q_DECLARE_OPERATORS_FOR_FLAGS(KWayland::Server::LinuxDmabuf::Flags)
+
+#endif // WAYLAND_SERVER_LINUXDMABUF_INTERFACE_H


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic