[mutter] native: Consolidate DRM buffer management to MetaDrmBuffer types



commit 84bde805fe34611c3a4d1cef1dfd30221b33dcc3
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Tue Sep 29 09:40:53 2020 +0200

    native: Consolidate DRM buffer management to MetaDrmBuffer types
    
    This commit consolidates DRM buffer management to the MetaDrmBuffer
    types, where the base type handles the common functionality (such as
    managing the framebuffer id using drmModeAdd*/RMFb()), and the sub types
    their corresponding type specific behavior.
    
    This means that drmModeAdd*/RmFB() handling is moved from meta-gpu-kms.c
    to meta-drm-buffer.c; dumb buffer allocation/management from
    meta-renderer-native.c.
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>

 src/backends/native/meta-drm-buffer-dumb.c    | 297 ++++++++++++++++++++++-
 src/backends/native/meta-drm-buffer-dumb.h    |  14 +-
 src/backends/native/meta-drm-buffer-gbm.c     |  80 +++---
 src/backends/native/meta-drm-buffer-gbm.h     |   6 +-
 src/backends/native/meta-drm-buffer-import.c  |  88 ++++---
 src/backends/native/meta-drm-buffer-import.h  |   7 +-
 src/backends/native/meta-drm-buffer-private.h |  60 +++++
 src/backends/native/meta-drm-buffer.c         | 307 ++++++++++++++++++++++-
 src/backends/native/meta-drm-buffer.h         |  15 +-
 src/backends/native/meta-gpu-kms.c            |  74 ------
 src/backends/native/meta-gpu-kms.h            |  17 --
 src/backends/native/meta-renderer-native.c    | 335 +++++++-------------------
 src/meson.build                               |   1 +
 src/wayland/meta-wayland-buffer.c             |   4 +-
 src/wayland/meta-wayland-dma-buf.c            |   4 +-
 15 files changed, 877 insertions(+), 432 deletions(-)
---
diff --git a/src/backends/native/meta-drm-buffer-dumb.c b/src/backends/native/meta-drm-buffer-dumb.c
index ccf5747f5d..373eb5c735 100644
--- a/src/backends/native/meta-drm-buffer-dumb.c
+++ b/src/backends/native/meta-drm-buffer-dumb.c
@@ -25,41 +25,322 @@
 
 #include "backends/native/meta-drm-buffer-dumb.h"
 
+#include <xf86drm.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include "backends/native/meta-kms-device-private.h"
+#include "backends/native/meta-kms-impl-device.h"
+#include "backends/native/meta-kms-private.h"
+
 struct _MetaDrmBufferDumb
 {
   MetaDrmBuffer parent;
 
-  uint32_t fb_id;
+  uint32_t handle;
+  void *map;
+  uint64_t map_size;
+  int width;
+  int height;
+  int stride_bytes;
+  uint32_t drm_format;
+  int dmabuf_fd;
 };
 
 G_DEFINE_TYPE (MetaDrmBufferDumb, meta_drm_buffer_dumb, META_TYPE_DRM_BUFFER)
 
+static int
+meta_drm_buffer_dumb_get_width (MetaDrmBuffer *buffer)
+{
+  MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (buffer);
+
+  return buffer_dumb->width;
+}
+
+static int
+meta_drm_buffer_dumb_get_height (MetaDrmBuffer *buffer)
+{
+  MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (buffer);
+
+  return buffer_dumb->height;
+}
+
+static int
+meta_drm_buffer_dumb_get_stride (MetaDrmBuffer *buffer)
+{
+  MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (buffer);
+
+  return buffer_dumb->stride_bytes;
+}
+
+static uint32_t
+meta_drm_buffer_dumb_get_format (MetaDrmBuffer *buffer)
+{
+  MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (buffer);
+
+  return buffer_dumb->drm_format;
+}
+
+typedef struct
+{
+  MetaDrmBufferDumb *buffer_dumb;
+
+  int out_dmabuf_fd;
+} HandleToFdData;
+
+static gpointer
+handle_to_fd_in_impl (MetaKmsImpl  *impl,
+                      gpointer      user_data,
+                      GError      **error)
+{
+  HandleToFdData *data = user_data;
+  MetaDrmBufferDumb *buffer_dumb = data->buffer_dumb;
+  MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_dumb);
+  MetaKmsDevice *device = meta_drm_buffer_get_device (buffer);
+  MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
+  int fd;
+  int ret;
+  int dmabuf_fd;
+
+  fd = meta_kms_impl_device_get_fd (impl_device);
+
+  ret = drmPrimeHandleToFD (fd, buffer_dumb->handle, DRM_CLOEXEC,
+                            &dmabuf_fd);
+  if (ret)
+    {
+      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
+                   "drmPrimeHandleToFd: %s", g_strerror (-ret));
+      return GINT_TO_POINTER (FALSE);
+    }
+
+  data->out_dmabuf_fd = dmabuf_fd;
+
+  return GINT_TO_POINTER (TRUE);
+}
+
+int
+meta_drm_buffer_dumb_ensure_dmabuf_fd (MetaDrmBufferDumb  *buffer_dumb,
+                                       GError            **error)
+{
+  MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_dumb);
+  MetaKmsDevice *device = meta_drm_buffer_get_device (buffer);
+  HandleToFdData data;
+
+  if (buffer_dumb->dmabuf_fd != -1)
+    return buffer_dumb->dmabuf_fd;
+
+  data = (HandleToFdData) {
+    .buffer_dumb = buffer_dumb,
+  };
+
+  if (!meta_kms_run_impl_task_sync (meta_kms_device_get_kms (device),
+                                   handle_to_fd_in_impl,
+                                   &data,
+                                   error))
+    return -1;
+
+  buffer_dumb->dmabuf_fd = data.out_dmabuf_fd;
+  return buffer_dumb->dmabuf_fd;
+}
+
+void *
+meta_drm_buffer_dumb_get_data (MetaDrmBufferDumb *buffer_dumb)
+{
+  return buffer_dumb->map;
+}
+
+typedef struct
+{
+  MetaDrmBufferDumb *buffer_dumb;
+  int width;
+  int height;
+  uint32_t format;
+} InitDumbData;
+
+static gpointer
+init_dumb_buffer_in_impl (MetaKmsImpl  *impl,
+                          gpointer      user_data,
+                          GError      **error)
+{
+  InitDumbData *data = user_data;
+  MetaDrmBufferDumb *buffer_dumb = data->buffer_dumb;
+  MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_dumb);
+  MetaKmsDevice *device = meta_drm_buffer_get_device (buffer);
+  MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
+  int fd;
+  struct drm_mode_create_dumb create_arg;
+  struct drm_mode_destroy_dumb destroy_arg;
+  struct drm_mode_map_dumb map_arg;
+  void *map;
+  MetaDrmFbArgs fb_args;
+
+  fd = meta_kms_impl_device_get_fd (impl_device);
+
+  create_arg = (struct drm_mode_create_dumb) {
+    .bpp = 32, /* RGBX8888 */
+    .width = data->width,
+    .height = data->height
+  };
+  if (drmIoctl (fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg) != 0)
+    {
+      g_set_error (error, G_IO_ERROR,
+                   G_IO_ERROR_FAILED,
+                   "Failed to create dumb drm buffer: %s",
+                   g_strerror (errno));
+      goto err_ioctl;
+    }
+
+  fb_args = (MetaDrmFbArgs) {
+    .width = data->width,
+    .height = data->height,
+    .format = data->format,
+    .handles = { create_arg.handle },
+    .strides = { create_arg.pitch },
+  };
+  if (!meta_drm_buffer_ensure_fb_id (buffer, FALSE, &fb_args, error))
+    goto err_add_fb;
+
+  map_arg = (struct drm_mode_map_dumb) {
+    .handle = create_arg.handle
+  };
+  if (drmIoctl (fd, DRM_IOCTL_MODE_MAP_DUMB,
+                &map_arg) != 0)
+    {
+      g_set_error (error, G_IO_ERROR,
+                   G_IO_ERROR_FAILED,
+                   "Failed to map dumb drm buffer: %s",
+                   g_strerror (errno));
+      goto err_map_dumb;
+    }
+
+  map = mmap (NULL, create_arg.size, PROT_WRITE, MAP_SHARED,
+              fd, map_arg.offset);
+  if (map == MAP_FAILED)
+    {
+      g_set_error (error, G_IO_ERROR,
+                   G_IO_ERROR_FAILED,
+                   "Failed to mmap dumb drm buffer memory: %s",
+                   g_strerror (errno));
+      goto err_mmap;
+    }
+
+  buffer_dumb->handle = create_arg.handle;
+  buffer_dumb->map = map;
+  buffer_dumb->map_size = create_arg.size;
+  buffer_dumb->width = data->width;
+  buffer_dumb->height = data->height;
+  buffer_dumb->stride_bytes = create_arg.pitch;
+  buffer_dumb->drm_format = data->format;
+
+  return FALSE;
+
+err_mmap:
+err_map_dumb:
+err_add_fb:
+  destroy_arg = (struct drm_mode_destroy_dumb) {
+    .handle = create_arg.handle
+  };
+  drmIoctl (fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
+
+err_ioctl:
+  return FALSE;
+}
+
 MetaDrmBufferDumb *
-meta_drm_buffer_dumb_new (uint32_t dumb_fb_id)
+meta_drm_buffer_dumb_new (MetaKmsDevice  *device,
+                          int             width,
+                          int             height,
+                          uint32_t        format,
+                          GError        **error)
 {
   MetaDrmBufferDumb *buffer_dumb;
+  InitDumbData data;
+
+  buffer_dumb = g_object_new (META_TYPE_DRM_BUFFER_DUMB,
+                              "device", device,
+                              NULL);
+
+  data = (InitDumbData) {
+    .buffer_dumb = buffer_dumb,
+    .width = width,
+    .height = height,
+    .format = format,
+  };
 
-  buffer_dumb = g_object_new (META_TYPE_DRM_BUFFER_DUMB, NULL);
-  buffer_dumb->fb_id = dumb_fb_id;
+  if (meta_kms_run_impl_task_sync (meta_kms_device_get_kms (device),
+                                   init_dumb_buffer_in_impl,
+                                   &data,
+                                   error))
+    {
+      g_object_unref (buffer_dumb);
+      return NULL;
+    }
 
   return buffer_dumb;
 }
 
-static uint32_t
-meta_drm_buffer_dumb_get_fb_id (MetaDrmBuffer *buffer)
+static gpointer
+destroy_dumb_in_impl (MetaKmsImpl  *impl,
+                      gpointer      user_data,
+                      GError      **error)
 {
-  return META_DRM_BUFFER_DUMB (buffer)->fb_id;
+  MetaDrmBufferDumb *buffer_dumb = user_data;
+  MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_dumb);
+  MetaKmsDevice *device = meta_drm_buffer_get_device (buffer);
+  MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
+  int fd;
+  struct drm_mode_destroy_dumb destroy_arg;
+
+  fd = meta_kms_impl_device_get_fd (impl_device);
+
+  munmap (buffer_dumb->map, buffer_dumb->map_size);
+
+  destroy_arg = (struct drm_mode_destroy_dumb) {
+    .handle = buffer_dumb->handle
+  };
+  drmIoctl (fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
+
+  if (buffer_dumb->dmabuf_fd != -1)
+    close (buffer_dumb->dmabuf_fd);
+
+  return GINT_TO_POINTER (TRUE);
+}
+
+static void
+meta_drm_buffer_dumb_finalize (GObject *object)
+{
+  MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (object);
+
+  if (buffer_dumb->handle)
+    {
+      MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_dumb);
+      MetaKmsDevice *device = meta_drm_buffer_get_device (buffer);
+
+      meta_kms_run_impl_task_sync (meta_kms_device_get_kms (device),
+                                   destroy_dumb_in_impl,
+                                   buffer_dumb,
+                                   NULL);
+    }
+
+  G_OBJECT_CLASS (meta_drm_buffer_dumb_parent_class)->finalize (object);
 }
 
 static void
 meta_drm_buffer_dumb_init (MetaDrmBufferDumb *buffer_dumb)
 {
+  buffer_dumb->dmabuf_fd = -1;
 }
 
 static void
 meta_drm_buffer_dumb_class_init (MetaDrmBufferDumbClass *klass)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
   MetaDrmBufferClass *buffer_class = META_DRM_BUFFER_CLASS (klass);
 
-  buffer_class->get_fb_id = meta_drm_buffer_dumb_get_fb_id;
+  object_class->finalize = meta_drm_buffer_dumb_finalize;
+
+  buffer_class->get_width = meta_drm_buffer_dumb_get_width;
+  buffer_class->get_height = meta_drm_buffer_dumb_get_height;
+  buffer_class->get_stride = meta_drm_buffer_dumb_get_stride;
+  buffer_class->get_format = meta_drm_buffer_dumb_get_format;
 }
diff --git a/src/backends/native/meta-drm-buffer-dumb.h b/src/backends/native/meta-drm-buffer-dumb.h
index f8b733f889..2d3e27c927 100644
--- a/src/backends/native/meta-drm-buffer-dumb.h
+++ b/src/backends/native/meta-drm-buffer-dumb.h
@@ -22,7 +22,8 @@
 #ifndef META_DRM_BUFFER_DUMB_H
 #define META_DRM_BUFFER_DUMB_H
 
-#include "backends/native/meta-drm-buffer.h"
+#include "backends/native/meta-drm-buffer-private.h"
+#include "backends/native/meta-kms-device.h"
 
 #define META_TYPE_DRM_BUFFER_DUMB (meta_drm_buffer_dumb_get_type ())
 G_DECLARE_FINAL_TYPE (MetaDrmBufferDumb,
@@ -30,6 +31,15 @@ G_DECLARE_FINAL_TYPE (MetaDrmBufferDumb,
                       META, DRM_BUFFER_DUMB,
                       MetaDrmBuffer)
 
-MetaDrmBufferDumb * meta_drm_buffer_dumb_new (uint32_t dumb_fb_id);
+MetaDrmBufferDumb * meta_drm_buffer_dumb_new (MetaKmsDevice  *device,
+                                              int             width,
+                                              int             height,
+                                              uint32_t        format,
+                                              GError        **error);
+
+int meta_drm_buffer_dumb_ensure_dmabuf_fd (MetaDrmBufferDumb  *buffer_dumb,
+                                           GError            **error);
+
+void * meta_drm_buffer_dumb_get_data (MetaDrmBufferDumb *buffer_dumb);
 
 #endif /* META_DRM_BUFFER_DUMB_H */
diff --git a/src/backends/native/meta-drm-buffer-gbm.c b/src/backends/native/meta-drm-buffer-gbm.c
index 7acd97bc4c..48ee9eb048 100644
--- a/src/backends/native/meta-drm-buffer-gbm.c
+++ b/src/backends/native/meta-drm-buffer-gbm.c
@@ -23,7 +23,6 @@
 
 #include "config.h"
 
-#include "backends/native/meta-cogl-utils.h"
 #include "backends/native/meta-drm-buffer-gbm.h"
 
 #include <drm_fourcc.h>
@@ -31,18 +30,16 @@
 #include <xf86drm.h>
 #include <xf86drmMode.h>
 
-#define INVALID_FB_ID 0U
+#include "backends/native/meta-drm-buffer-private.h"
+#include "backends/native/meta-cogl-utils.h"
 
 struct _MetaDrmBufferGbm
 {
   MetaDrmBuffer parent;
 
-  MetaGpuKms *gpu_kms;
-
   struct gbm_surface *surface;
 
   struct gbm_bo *bo;
-  uint32_t fb_id;
 };
 
 static void
@@ -58,13 +55,45 @@ meta_drm_buffer_gbm_get_bo (MetaDrmBufferGbm *buffer_gbm)
   return buffer_gbm->bo;
 }
 
+static int
+meta_drm_buffer_gbm_get_width (MetaDrmBuffer *buffer)
+{
+  MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer);
+
+  return gbm_bo_get_width (buffer_gbm->bo);
+}
+
+static int
+meta_drm_buffer_gbm_get_height (MetaDrmBuffer *buffer)
+{
+  MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer);
+
+  return gbm_bo_get_height (buffer_gbm->bo);
+}
+
+static int
+meta_drm_buffer_gbm_get_stride (MetaDrmBuffer *buffer)
+{
+  MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer);
+
+  return gbm_bo_get_stride (buffer_gbm->bo);
+}
+
+static uint32_t
+meta_drm_buffer_gbm_get_format (MetaDrmBuffer *buffer)
+{
+  MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer);
+
+  return gbm_bo_get_format (buffer_gbm->bo);
+}
+
 static gboolean
 init_fb_id (MetaDrmBufferGbm  *buffer_gbm,
             struct gbm_bo     *bo,
             gboolean           use_modifiers,
             GError           **error)
 {
-  MetaGpuKmsFBArgs fb_args = { 0, };
+  MetaDrmFbArgs fb_args = { 0, };
 
   if (gbm_bo_get_handle_for_plane (bo, 0).s32 == -1)
     {
@@ -91,10 +120,8 @@ init_fb_id (MetaDrmBufferGbm  *buffer_gbm,
   fb_args.height = gbm_bo_get_height (bo);
   fb_args.format = gbm_bo_get_format (bo);
 
-  if (!meta_gpu_kms_add_fb (buffer_gbm->gpu_kms,
-                            use_modifiers,
-                            &fb_args,
-                            &buffer_gbm->fb_id, error))
+  if (!meta_drm_buffer_ensure_fb_id (META_DRM_BUFFER (buffer_gbm),
+                                     use_modifiers, &fb_args, error))
     return FALSE;
 
   return TRUE;
@@ -119,15 +146,16 @@ lock_front_buffer (MetaDrmBufferGbm  *buffer_gbm,
 }
 
 MetaDrmBufferGbm *
-meta_drm_buffer_gbm_new_lock_front (MetaGpuKms          *gpu_kms,
+meta_drm_buffer_gbm_new_lock_front (MetaKmsDevice       *device,
                                     struct gbm_surface  *gbm_surface,
                                     gboolean             use_modifiers,
                                     GError             **error)
 {
   MetaDrmBufferGbm *buffer_gbm;
 
-  buffer_gbm = g_object_new (META_TYPE_DRM_BUFFER_GBM, NULL);
-  buffer_gbm->gpu_kms = gpu_kms;
+  buffer_gbm = g_object_new (META_TYPE_DRM_BUFFER_GBM,
+                             "device", device,
+                             NULL);
   buffer_gbm->surface = gbm_surface;
 
   if (!lock_front_buffer (buffer_gbm, use_modifiers, error))
@@ -140,15 +168,16 @@ meta_drm_buffer_gbm_new_lock_front (MetaGpuKms          *gpu_kms,
 }
 
 MetaDrmBufferGbm *
-meta_drm_buffer_gbm_new_take (MetaGpuKms     *gpu_kms,
+meta_drm_buffer_gbm_new_take (MetaKmsDevice  *device,
                               struct gbm_bo  *bo,
                               gboolean        use_modifiers,
                               GError        **error)
 {
   MetaDrmBufferGbm *buffer_gbm;
 
-  buffer_gbm = g_object_new (META_TYPE_DRM_BUFFER_GBM, NULL);
-  buffer_gbm->gpu_kms = gpu_kms;
+  buffer_gbm = g_object_new (META_TYPE_DRM_BUFFER_GBM,
+                             "device", device,
+                             NULL);
 
   if (!init_fb_id (buffer_gbm, bo, use_modifiers, error))
     {
@@ -161,12 +190,6 @@ meta_drm_buffer_gbm_new_take (MetaGpuKms     *gpu_kms,
   return buffer_gbm;
 }
 
-static uint32_t
-meta_drm_buffer_gbm_get_fb_id (MetaDrmBuffer *buffer)
-{
-  return META_DRM_BUFFER_GBM (buffer)->fb_id;
-}
-
 static gboolean
 meta_drm_buffer_gbm_blit_to_framebuffer (CoglScanout      *scanout,
                                          CoglFramebuffer  *framebuffer,
@@ -308,14 +331,6 @@ meta_drm_buffer_gbm_finalize (GObject *object)
 {
   MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (object);
 
-  if (buffer_gbm->fb_id != INVALID_FB_ID)
-    {
-      int kms_fd;
-
-      kms_fd = meta_gpu_kms_get_fd (buffer_gbm->gpu_kms);
-      drmModeRmFB (kms_fd, buffer_gbm->fb_id);
-    }
-
   if (buffer_gbm->bo)
     {
       if (buffer_gbm->surface)
@@ -340,5 +355,8 @@ meta_drm_buffer_gbm_class_init (MetaDrmBufferGbmClass *klass)
 
   object_class->finalize = meta_drm_buffer_gbm_finalize;
 
-  buffer_class->get_fb_id = meta_drm_buffer_gbm_get_fb_id;
+  buffer_class->get_width = meta_drm_buffer_gbm_get_width;
+  buffer_class->get_height = meta_drm_buffer_gbm_get_height;
+  buffer_class->get_stride = meta_drm_buffer_gbm_get_stride;
+  buffer_class->get_format = meta_drm_buffer_gbm_get_format;
 }
diff --git a/src/backends/native/meta-drm-buffer-gbm.h b/src/backends/native/meta-drm-buffer-gbm.h
index b46925ecc9..43d7e2d8a0 100644
--- a/src/backends/native/meta-drm-buffer-gbm.h
+++ b/src/backends/native/meta-drm-buffer-gbm.h
@@ -24,7 +24,7 @@
 
 #include <gbm.h>
 
-#include "backends/native/meta-drm-buffer.h"
+#include "backends/native/meta-drm-buffer-private.h"
 #include "backends/native/meta-gpu-kms.h"
 
 #define META_TYPE_DRM_BUFFER_GBM (meta_drm_buffer_gbm_get_type ())
@@ -33,13 +33,13 @@ G_DECLARE_FINAL_TYPE (MetaDrmBufferGbm,
                       META, DRM_BUFFER_GBM,
                       MetaDrmBuffer)
 
-MetaDrmBufferGbm * meta_drm_buffer_gbm_new_lock_front (MetaGpuKms          *gpu_kms,
+MetaDrmBufferGbm * meta_drm_buffer_gbm_new_lock_front (MetaKmsDevice       *device,
                                                        struct gbm_surface  *gbm_surface,
                                                        gboolean             use_modifiers,
                                                        GError             **error);
 
 
-MetaDrmBufferGbm * meta_drm_buffer_gbm_new_take (MetaGpuKms     *gpu_kms,
+MetaDrmBufferGbm * meta_drm_buffer_gbm_new_take (MetaKmsDevice  *device,
                                                  struct gbm_bo  *gbm_bo,
                                                  gboolean        use_modifiers,
                                                  GError        **error);
diff --git a/src/backends/native/meta-drm-buffer-import.c b/src/backends/native/meta-drm-buffer-import.c
index b9d0e21d23..1e5a382461 100644
--- a/src/backends/native/meta-drm-buffer-import.c
+++ b/src/backends/native/meta-drm-buffer-import.c
@@ -34,22 +34,48 @@
 #include "backends/native/meta-kms-utils.h"
 #include "backends/native/meta-renderer-native.h"
 
-#define INVALID_FB_ID 0U
-
 struct _MetaDrmBufferImport
 {
   MetaDrmBuffer parent;
 
-  MetaGpuKms *gpu_kms;
-
   MetaDrmBufferGbm *importee;
-
-  uint32_t fb_id;
 };
 
 G_DEFINE_TYPE (MetaDrmBufferImport, meta_drm_buffer_import,
                META_TYPE_DRM_BUFFER)
 
+static int
+meta_drm_buffer_import_get_width (MetaDrmBuffer *buffer)
+{
+  MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (buffer);
+
+  return meta_drm_buffer_get_width (META_DRM_BUFFER (buffer_import->importee));
+}
+
+static int
+meta_drm_buffer_import_get_height (MetaDrmBuffer *buffer)
+{
+  MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (buffer);
+
+  return meta_drm_buffer_get_height (META_DRM_BUFFER (buffer_import->importee));
+}
+
+static int
+meta_drm_buffer_import_get_stride (MetaDrmBuffer *buffer)
+{
+  MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (buffer);
+
+  return meta_drm_buffer_get_stride (META_DRM_BUFFER (buffer_import->importee));
+}
+
+static uint32_t
+meta_drm_buffer_import_get_format (MetaDrmBuffer *buffer)
+{
+  MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (buffer);
+
+  return meta_drm_buffer_get_format (META_DRM_BUFFER (buffer_import->importee));
+}
+
 static struct gbm_bo *
 dmabuf_to_gbm_bo (struct gbm_device *importer,
                   int                dmabuf_fd,
@@ -74,19 +100,15 @@ dmabuf_to_gbm_bo (struct gbm_device *importer,
 
 static gboolean
 import_gbm_buffer (MetaDrmBufferImport  *buffer_import,
+                   struct gbm_device    *importer,
                    GError              **error)
 {
-  MetaGpuKmsFBArgs fb_args = { 0, };
+  MetaDrmFbArgs fb_args = { 0, };
   struct gbm_bo *primary_bo;
-  struct gbm_device *importer;
   struct gbm_bo *imported_bo;
   int dmabuf_fd;
   gboolean ret;
 
-  g_assert (buffer_import->fb_id == INVALID_FB_ID);
-
-  importer = meta_gbm_device_from_gpu (buffer_import->gpu_kms);
-
   primary_bo = meta_drm_buffer_gbm_get_bo (buffer_import->importee);
 
   dmabuf_fd = gbm_bo_get_fd (primary_bo);
@@ -122,11 +144,10 @@ import_gbm_buffer (MetaDrmBufferImport  *buffer_import,
 
   fb_args.handles[0] = gbm_bo_get_handle (imported_bo).u32;
 
-  ret = meta_gpu_kms_add_fb (buffer_import->gpu_kms,
-                             FALSE /* use_modifiers */,
-                             &fb_args,
-                             &buffer_import->fb_id,
-                             error);
+  ret = meta_drm_buffer_ensure_fb_id (META_DRM_BUFFER (buffer_import),
+                                      FALSE /* use_modifiers */,
+                                      &fb_args,
+                                      error);
 
   gbm_bo_destroy (imported_bo);
 
@@ -137,17 +158,19 @@ out_close:
 }
 
 MetaDrmBufferImport *
-meta_drm_buffer_import_new (MetaGpuKms        *gpu_kms,
-                            MetaDrmBufferGbm  *buffer_gbm,
-                            GError           **error)
+meta_drm_buffer_import_new (MetaKmsDevice      *device,
+                            struct gbm_device  *gbm_device,
+                            MetaDrmBufferGbm   *buffer_gbm,
+                            GError            **error)
 {
   MetaDrmBufferImport *buffer_import;
 
-  buffer_import = g_object_new (META_TYPE_DRM_BUFFER_IMPORT, NULL);
-  buffer_import->gpu_kms = gpu_kms;
+  buffer_import = g_object_new (META_TYPE_DRM_BUFFER_IMPORT,
+                                "device", device,
+                                NULL);
   g_set_object (&buffer_import->importee, buffer_gbm);
 
-  if (!import_gbm_buffer (buffer_import, error))
+  if (!import_gbm_buffer (buffer_import, gbm_device, error))
     {
       g_object_unref (buffer_import);
       return NULL;
@@ -156,25 +179,11 @@ meta_drm_buffer_import_new (MetaGpuKms        *gpu_kms,
   return buffer_import;
 }
 
-static uint32_t
-meta_drm_buffer_import_get_fb_id (MetaDrmBuffer *buffer)
-{
-  return META_DRM_BUFFER_IMPORT (buffer)->fb_id;
-}
-
 static void
 meta_drm_buffer_import_finalize (GObject *object)
 {
   MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (object);
 
-  if (buffer_import->fb_id != INVALID_FB_ID)
-    {
-      int kms_fd;
-
-      kms_fd = meta_gpu_kms_get_fd (buffer_import->gpu_kms);
-      drmModeRmFB (kms_fd, buffer_import->fb_id);
-    }
-
   g_clear_object (&buffer_import->importee);
 
   G_OBJECT_CLASS (meta_drm_buffer_import_parent_class)->finalize (object);
@@ -193,5 +202,8 @@ meta_drm_buffer_import_class_init (MetaDrmBufferImportClass *klass)
 
   object_class->finalize = meta_drm_buffer_import_finalize;
 
-  buffer_class->get_fb_id = meta_drm_buffer_import_get_fb_id;
+  buffer_class->get_width = meta_drm_buffer_import_get_width;
+  buffer_class->get_height = meta_drm_buffer_import_get_height;
+  buffer_class->get_stride = meta_drm_buffer_import_get_stride;
+  buffer_class->get_format = meta_drm_buffer_import_get_format;
 }
diff --git a/src/backends/native/meta-drm-buffer-import.h b/src/backends/native/meta-drm-buffer-import.h
index 2c0962e5f4..48c9bd1903 100644
--- a/src/backends/native/meta-drm-buffer-import.h
+++ b/src/backends/native/meta-drm-buffer-import.h
@@ -47,8 +47,9 @@ G_DECLARE_FINAL_TYPE (MetaDrmBufferImport,
  * The import has a high chance of failing under normal operating
  * conditions and needs to be handled with fallbacks to something else.
  */
-MetaDrmBufferImport * meta_drm_buffer_import_new (MetaGpuKms        *gpu_kms,
-                                                  MetaDrmBufferGbm  *buffer_gbm,
-                                                  GError           **error);
+MetaDrmBufferImport * meta_drm_buffer_import_new (MetaKmsDevice      *device,
+                                                  struct gbm_device  *gbm_device,
+                                                  MetaDrmBufferGbm   *buffer_gbm,
+                                                  GError            **error);
 
 #endif /* META_DRM_BUFFER_IMPORT_H */
diff --git a/src/backends/native/meta-drm-buffer-private.h b/src/backends/native/meta-drm-buffer-private.h
new file mode 100644
index 0000000000..2c77eb9579
--- /dev/null
+++ b/src/backends/native/meta-drm-buffer-private.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 Canonical Ltd.
+ * Copyright (C) 2019-2020 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef META_DRM_BUFFER_PRIVATE_H
+#define META_DRM_BUFFER_PRIVATE_H
+
+#include "backends/native/meta-drm-buffer.h"
+#include "backends/native/meta-kms-device.h"
+
+typedef struct _MetaDrmFbArgs
+{
+  uint32_t width;
+  uint32_t height;
+  uint32_t format;
+  uint32_t handles[4];
+  uint32_t offsets[4];
+  uint32_t strides[4];
+  uint64_t modifiers[4];
+} MetaDrmFbArgs;
+
+struct _MetaDrmBufferClass
+{
+  GObjectClass parent_class;
+
+  int (* get_width) (MetaDrmBuffer *buffer);
+  int (* get_height) (MetaDrmBuffer *buffer);
+  int (* get_stride) (MetaDrmBuffer *buffer);
+  uint32_t (* get_format) (MetaDrmBuffer *buffer);
+};
+
+MetaKmsDevice * meta_drm_buffer_get_device (MetaDrmBuffer *buffer);
+
+gboolean meta_drm_buffer_ensure_fb_id (MetaDrmBuffer        *buffer,
+                                       gboolean              use_modifiers,
+                                       const MetaDrmFbArgs  *fb_args,
+                                       GError              **error);
+
+gboolean meta_drm_buffer_ensure_fb_in_impl (MetaDrmBuffer        *buffer,
+                                            gboolean              use_modifiers,
+                                            const MetaDrmFbArgs  *fb_args,
+                                            GError              **error);
+
+#endif /* META_DRM_BUFFER_PRIVATE_H */
diff --git a/src/backends/native/meta-drm-buffer.c b/src/backends/native/meta-drm-buffer.c
index 85b520825d..81a36196e5 100644
--- a/src/backends/native/meta-drm-buffer.c
+++ b/src/backends/native/meta-drm-buffer.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2011 Intel Corporation.
- * Copyright (C) 2016 Red Hat
+ * Copyright (C) 2016-2020 Red Hat
  * Copyright (C) 2018 DisplayLink (UK) Ltd.
  * Copyright (C) 2018 Canonical Ltd.
  *
@@ -24,14 +24,298 @@
 
 #include "config.h"
 
-#include "backends/native/meta-drm-buffer.h"
+#include "backends/native/meta-drm-buffer-private.h"
 
-G_DEFINE_ABSTRACT_TYPE (MetaDrmBuffer, meta_drm_buffer, G_TYPE_OBJECT)
+#include <drm_fourcc.h>
+
+#include "backends/native/meta-kms-device-private.h"
+#include "backends/native/meta-kms-impl-device.h"
+#include "backends/native/meta-kms-utils.h"
+#include "backends/native/meta-kms-private.h"
+
+#define INVALID_FB_ID 0U
+
+enum
+{
+  PROP_0,
+
+  PROP_DEVICE,
+
+  N_PROPS
+};
+
+static GParamSpec *obj_props[N_PROPS];
+
+typedef struct _MetaDrmBufferPrivate
+{
+  MetaKmsDevice *device;
+  uint32_t fb_id;
+} MetaDrmBufferPrivate;
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaDrmBuffer, meta_drm_buffer,
+                                     G_TYPE_OBJECT)
+
+MetaKmsDevice *
+meta_drm_buffer_get_device (MetaDrmBuffer *buffer)
+{
+  MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer);
+
+  return priv->device;
+}
+
+gboolean
+meta_drm_buffer_ensure_fb_in_impl (MetaDrmBuffer        *buffer,
+                                   gboolean              use_modifiers,
+                                   const MetaDrmFbArgs  *fb_args,
+                                   GError              **error)
+{
+  MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer);
+  MetaKmsDevice *device = priv->device;
+  MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
+  int fd;
+  MetaDrmFormatBuf tmp;
+  uint32_t fb_id;
+
+  fd = meta_kms_impl_device_get_fd (impl_device);
+
+  if (use_modifiers && fb_args->modifiers[0] != DRM_FORMAT_MOD_INVALID)
+    {
+      if (drmModeAddFB2WithModifiers (fd,
+                                      fb_args->width,
+                                      fb_args->height,
+                                      fb_args->format,
+                                      fb_args->handles,
+                                      fb_args->strides,
+                                      fb_args->offsets,
+                                      fb_args->modifiers,
+                                      &fb_id,
+                                      DRM_MODE_FB_MODIFIERS))
+        {
+          g_set_error (error,
+                       G_IO_ERROR,
+                       g_io_error_from_errno (errno),
+                       "drmModeAddFB2WithModifiers failed: %s",
+                       g_strerror (errno));
+          return FALSE;
+        }
+    }
+  else if (drmModeAddFB2 (fd,
+                          fb_args->width,
+                          fb_args->height,
+                          fb_args->format,
+                          fb_args->handles,
+                          fb_args->strides,
+                          fb_args->offsets,
+                          &fb_id,
+                          0))
+    {
+      if (fb_args->format != DRM_FORMAT_XRGB8888)
+        {
+          g_set_error (error,
+                       G_IO_ERROR,
+                       G_IO_ERROR_FAILED,
+                       "drmModeAddFB does not support format '%s' (0x%x)",
+                       meta_drm_format_to_string (&tmp, fb_args->format),
+                       fb_args->format);
+          return FALSE;
+        }
+
+      if (drmModeAddFB (fd,
+                        fb_args->width,
+                        fb_args->height,
+                        24,
+                        32,
+                        fb_args->strides[0],
+                        fb_args->handles[0],
+                        &fb_id))
+        {
+          g_set_error (error,
+                       G_IO_ERROR,
+                       g_io_error_from_errno (errno),
+                       "drmModeAddFB failed: %s",
+                       g_strerror (errno));
+          return FALSE;
+        }
+    }
+
+  priv->fb_id = fb_id;
+
+  return TRUE;
+}
+
+typedef struct
+{
+  MetaDrmBuffer *buffer;
+  gboolean use_modifiers;
+  MetaDrmFbArgs fb_args;
+} AddFbData;
+
+static gpointer
+add_fb_in_impl (MetaKmsImpl  *impl,
+                gpointer      user_data,
+                GError      **error)
+{
+  AddFbData *data = user_data;
+
+  if (meta_drm_buffer_ensure_fb_in_impl (data->buffer,
+                                         data->use_modifiers,
+                                         &data->fb_args,
+                                         error))
+    return GINT_TO_POINTER (TRUE);
+  else
+    return GINT_TO_POINTER (FALSE);
+}
+
+gboolean
+meta_drm_buffer_ensure_fb_id (MetaDrmBuffer        *buffer,
+                              gboolean              use_modifiers,
+                              const MetaDrmFbArgs  *fb_args,
+                              GError              **error)
+{
+  MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer);
+  AddFbData data;
+
+  data = (AddFbData) {
+    .buffer = buffer,
+    .use_modifiers = use_modifiers,
+    .fb_args = *fb_args,
+  };
+
+  if (!meta_kms_run_impl_task_sync (meta_kms_device_get_kms (priv->device),
+                                    add_fb_in_impl,
+                                    &data,
+                                    error))
+    return FALSE;
+
+  return TRUE;
+}
+
+typedef struct
+{
+  MetaKmsDevice *device;
+  uint32_t fb_id;
+} RmFbData;
+
+static gpointer
+rm_fb_in_impl (MetaKmsImpl  *impl,
+               gpointer      user_data,
+               GError      **error)
+{
+  RmFbData *data = user_data;
+  MetaKmsDevice *device = data->device;
+  MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
+  uint32_t fb_id = data->fb_id;
+  int fd;
+  int ret;
+
+  fd = meta_kms_impl_device_get_fd (impl_device);
+  ret = drmModeRmFB (fd, fb_id);
+  if (ret != 0)
+    g_warning ("drmModeRmFB: %s", g_strerror (-ret));
+
+  return GINT_TO_POINTER (TRUE);
+}
+
+static void
+meta_drm_buffer_release_fb_id (MetaDrmBuffer *buffer)
+{
+  MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer);
+  RmFbData data;
+
+  data = (RmFbData) {
+    .device = priv->device,
+    .fb_id = priv->fb_id,
+  };
+
+  meta_kms_run_impl_task_sync (meta_kms_device_get_kms (priv->device),
+                               rm_fb_in_impl,
+                               &data,
+                               NULL);
+  priv->fb_id = 0;
+}
 
 uint32_t
 meta_drm_buffer_get_fb_id (MetaDrmBuffer *buffer)
 {
-  return META_DRM_BUFFER_GET_CLASS (buffer)->get_fb_id (buffer);
+  MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer);
+
+  return priv->fb_id;
+}
+
+int
+meta_drm_buffer_get_width (MetaDrmBuffer *buffer)
+{
+  return META_DRM_BUFFER_GET_CLASS (buffer)->get_width (buffer);
+}
+
+int
+meta_drm_buffer_get_height (MetaDrmBuffer *buffer)
+{
+  return META_DRM_BUFFER_GET_CLASS (buffer)->get_height (buffer);
+}
+
+int
+meta_drm_buffer_get_stride (MetaDrmBuffer *buffer)
+{
+  return META_DRM_BUFFER_GET_CLASS (buffer)->get_stride (buffer);
+}
+
+uint32_t
+meta_drm_buffer_get_format (MetaDrmBuffer *buffer)
+{
+  return META_DRM_BUFFER_GET_CLASS (buffer)->get_format (buffer);
+}
+
+static void
+meta_drm_buffer_get_property (GObject    *object,
+                              guint       prop_id,
+                              GValue     *value,
+                              GParamSpec *pspec)
+{
+  MetaDrmBuffer *buffer = META_DRM_BUFFER (object);
+  MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer);
+
+  switch (prop_id)
+    {
+    case PROP_DEVICE:
+      g_value_set_object (value, priv->device);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+meta_drm_buffer_set_property (GObject      *object,
+                              guint         prop_id,
+                              const GValue *value,
+                              GParamSpec   *pspec)
+{
+  MetaDrmBuffer *buffer = META_DRM_BUFFER (object);
+  MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer);
+
+  switch (prop_id)
+    {
+    case PROP_DEVICE:
+      priv->device = g_value_get_object (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+meta_drm_buffer_finalize (GObject *object)
+{
+  MetaDrmBuffer *buffer = META_DRM_BUFFER (object);
+  MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer);
+
+  if (priv->fb_id != INVALID_FB_ID)
+    meta_drm_buffer_release_fb_id (buffer);
+
+  G_OBJECT_CLASS (meta_drm_buffer_parent_class)->finalize (object);
 }
 
 static void
@@ -42,4 +326,19 @@ meta_drm_buffer_init (MetaDrmBuffer *buffer)
 static void
 meta_drm_buffer_class_init (MetaDrmBufferClass *klass)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->get_property = meta_drm_buffer_get_property;
+  object_class->set_property = meta_drm_buffer_set_property;
+  object_class->finalize = meta_drm_buffer_finalize;
+
+  obj_props[PROP_DEVICE] =
+    g_param_spec_object ("device",
+                         "device",
+                         "MetaKmsDevice",
+                         META_TYPE_KMS_DEVICE,
+                         G_PARAM_READWRITE |
+                         G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_STATIC_STRINGS);
+  g_object_class_install_properties (object_class, N_PROPS, obj_props);
 }
diff --git a/src/backends/native/meta-drm-buffer.h b/src/backends/native/meta-drm-buffer.h
index 94873ed40a..1647d399e7 100644
--- a/src/backends/native/meta-drm-buffer.h
+++ b/src/backends/native/meta-drm-buffer.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2018 Canonical Ltd.
+ * Copyright (C) 2019-2020 Red Hat Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -31,16 +32,14 @@ G_DECLARE_DERIVABLE_TYPE (MetaDrmBuffer,
                           META, DRM_BUFFER,
                           GObject)
 
-struct _MetaDrmBufferClass
-{
-  GObjectClass parent_class;
+uint32_t meta_drm_buffer_get_fb_id (MetaDrmBuffer *buffer);
 
-  uint32_t (* get_fb_id) (MetaDrmBuffer *buffer);
-};
+int meta_drm_buffer_get_width (MetaDrmBuffer *buffer);
 
-MetaDrmBuffer *
-meta_drm_buffer_new_from_dumb (uint32_t dumb_fb_id);
+int meta_drm_buffer_get_height (MetaDrmBuffer *buffer);
 
-uint32_t meta_drm_buffer_get_fb_id (MetaDrmBuffer *buffer);
+int meta_drm_buffer_get_stride (MetaDrmBuffer *buffer);
+
+uint32_t meta_drm_buffer_get_format (MetaDrmBuffer *buffer);
 
 #endif /* META_DRM_BUFFER_H */
diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c
index f156cb0561..dbf76abede 100644
--- a/src/backends/native/meta-gpu-kms.c
+++ b/src/backends/native/meta-gpu-kms.c
@@ -64,80 +64,6 @@ struct _MetaGpuKms
 
 G_DEFINE_TYPE (MetaGpuKms, meta_gpu_kms, META_TYPE_GPU)
 
-gboolean
-meta_gpu_kms_add_fb (MetaGpuKms              *gpu_kms,
-                     gboolean                 use_modifiers,
-                     const MetaGpuKmsFBArgs  *args,
-                     uint32_t                *fb_id_out,
-                     GError                 **error)
-{
-  MetaDrmFormatBuf tmp;
-  uint32_t fb_id;
-
-  if (use_modifiers && args->modifiers[0] != DRM_FORMAT_MOD_INVALID)
-    {
-      if (drmModeAddFB2WithModifiers (gpu_kms->fd,
-                                      args->width,
-                                      args->height,
-                                      args->format,
-                                      args->handles,
-                                      args->strides,
-                                      args->offsets,
-                                      args->modifiers,
-                                      &fb_id,
-                                      DRM_MODE_FB_MODIFIERS))
-        {
-          g_set_error (error,
-                       G_IO_ERROR,
-                       g_io_error_from_errno (errno),
-                       "drmModeAddFB2WithModifiers failed: %s",
-                       g_strerror (errno));
-          return FALSE;
-        }
-    }
-  else if (drmModeAddFB2 (gpu_kms->fd,
-                          args->width,
-                          args->height,
-                          args->format,
-                          args->handles,
-                          args->strides,
-                          args->offsets,
-                          &fb_id,
-                          0))
-    {
-      if (args->format != DRM_FORMAT_XRGB8888)
-        {
-          g_set_error (error,
-                       G_IO_ERROR,
-                       G_IO_ERROR_FAILED,
-                       "drmModeAddFB does not support format '%s' (0x%x)",
-                       meta_drm_format_to_string (&tmp, args->format),
-                       args->format);
-          return FALSE;
-        }
-
-      if (drmModeAddFB (gpu_kms->fd,
-                        args->width,
-                        args->height,
-                        24,
-                        32,
-                        args->strides[0],
-                        args->handles[0],
-                        &fb_id))
-        {
-          g_set_error (error,
-                       G_IO_ERROR,
-                       g_io_error_from_errno (errno),
-                       "drmModeAddFB failed: %s",
-                       g_strerror (errno));
-          return FALSE;
-        }
-    }
-
-    *fb_id_out = fb_id;
-    return TRUE;
-}
-
 gboolean
 meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms,
                              MetaCrtc   *crtc)
diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h
index 77aac47ec7..d75c8a40fd 100644
--- a/src/backends/native/meta-gpu-kms.h
+++ b/src/backends/native/meta-gpu-kms.h
@@ -75,21 +75,4 @@ MetaGpuKmsFlipClosureContainer * meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu
 
 void meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container);
 
-typedef struct _MetaGpuKmsFBArgs
-{
-  uint32_t width;
-  uint32_t height;
-  uint32_t format;
-  uint32_t handles[4];
-  uint32_t offsets[4];
-  uint32_t strides[4];
-  uint64_t modifiers[4];
-} MetaGpuKmsFBArgs;
-
-gboolean meta_gpu_kms_add_fb (MetaGpuKms              *gpu_kms,
-                              gboolean                 use_modifiers,
-                              const MetaGpuKmsFBArgs  *args,
-                              uint32_t                *fb_id_out,
-                              GError                 **error);
-
 #endif /* META_GPU_KMS_H */
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index 3cb68c8b07..6171c886e6 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -39,15 +39,12 @@
 
 #include <drm_fourcc.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <gbm.h>
 #include <gio/gio.h>
 #include <glib-object.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/mman.h>
 #include <unistd.h>
-#include <xf86drm.h>
 
 #include "backends/meta-backend-private.h"
 #include "backends/meta-crtc.h"
@@ -129,19 +126,6 @@ typedef struct _MetaRendererNativeGpuData
   } secondary;
 } MetaRendererNativeGpuData;
 
-typedef struct _MetaDumbBuffer
-{
-  uint32_t fb_id;
-  uint32_t handle;
-  void *map;
-  uint64_t map_size;
-  int width;
-  int height;
-  int stride_bytes;
-  uint32_t drm_format;
-  int dmabuf_fd;
-} MetaDumbBuffer;
-
 typedef enum _MetaSharedFramebufferImportStatus
 {
   /* Not tried importing yet. */
@@ -166,8 +150,8 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState
   } gbm;
 
   struct {
-    MetaDumbBuffer *dumb_fb;
-    MetaDumbBuffer dumb_fbs[2];
+    MetaDrmBufferDumb *current_dumb_fb;
+    MetaDrmBufferDumb *dumb_fbs[2];
   } cpu;
 
   gboolean noted_primary_gpu_copy_ok;
@@ -194,7 +178,7 @@ typedef struct _MetaOnscreenNative
   struct {
     EGLStreamKHR stream;
 
-    MetaDumbBuffer dumb_fb;
+    MetaDrmBufferDumb *dumb_fb;
   } egl;
 #endif
 
@@ -235,22 +219,6 @@ G_DEFINE_TYPE_WITH_CODE (MetaRendererNative,
 static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable;
 static const CoglWinsysVtable *parent_vtable;
 
-static void
-release_dumb_fb (MetaDumbBuffer *dumb_fb,
-                 MetaGpuKms     *gpu_kms);
-
-static gboolean
-init_dumb_fb (MetaDumbBuffer *dumb_fb,
-              MetaGpuKms     *gpu_kms,
-              int             width,
-              int             height,
-              uint32_t        format,
-              GError        **error);
-
-static int
-meta_dumb_buffer_ensure_dmabuf_fd (MetaDumbBuffer *dumb_fb,
-                                   MetaGpuKms     *gpu_kms);
-
 static MetaEgl *
 meta_renderer_native_get_egl (MetaRendererNative *renderer_native);
 
@@ -530,11 +498,10 @@ init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative         *renderer_nat
 static void
 secondary_gpu_release_dumb (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
 {
-  MetaGpuKms *gpu_kms = secondary_gpu_state->gpu_kms;
   unsigned i;
 
   for (i = 0; i < G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs); i++)
-    release_dumb_fb (&secondary_gpu_state->cpu.dumb_fbs[i], gpu_kms);
+    g_clear_object (&secondary_gpu_state->cpu.dumb_fbs[i]);
 }
 
 static void
@@ -635,6 +602,7 @@ init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative         *renderer_nat
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
   MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
   MetaGpuKms *gpu_kms;
+  MetaKmsDevice *kms_device;
   int width, height;
   unsigned int i;
   uint32_t drm_format;
@@ -652,6 +620,7 @@ init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative         *renderer_nat
   height = cogl_framebuffer_get_height (framebuffer);
 
   gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc));
+  kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
   g_debug ("Secondary GPU %s using DRM format '%s' (0x%x) for a %dx%d output.",
            meta_gpu_kms_get_file_path (gpu_kms),
            meta_drm_format_to_string (&tmp, drm_format),
@@ -665,13 +634,12 @@ init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative         *renderer_nat
 
   for (i = 0; i < G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs); i++)
     {
-      MetaDumbBuffer *dumb_fb = &secondary_gpu_state->cpu.dumb_fbs[i];
-
-      if (!init_dumb_fb (dumb_fb,
-                         gpu_kms,
-                         width, height,
-                         drm_format,
-                         error))
+      secondary_gpu_state->cpu.dumb_fbs[i] =
+        meta_drm_buffer_dumb_new (kms_device,
+                                  width, height,
+                                  drm_format,
+                                  error);
+      if (!secondary_gpu_state->cpu.dumb_fbs[i])
         {
           secondary_gpu_state_free (secondary_gpu_state);
           return FALSE;
@@ -1367,11 +1335,12 @@ meta_onscreen_native_set_crtc_mode (CoglOnscreen              *onscreen,
 #ifdef HAVE_EGL_DEVICE
     case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
       {
-        uint32_t fb_id;
+        MetaDrmBuffer *buffer;
 
-        fb_id = onscreen_native->egl.dumb_fb.fb_id;
+        buffer = META_DRM_BUFFER (onscreen_native->egl.dumb_fb);
         meta_crtc_kms_assign_primary_plane (crtc_kms,
-                                            fb_id, kms_update);
+                                            meta_drm_buffer_get_fb_id (buffer),
+                                            kms_update);
         break;
       }
 #endif
@@ -1403,13 +1372,20 @@ import_shared_framebuffer (CoglOnscreen                        *onscreen,
 {
   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
+  MetaGpuKms *gpu_kms;
+  MetaKmsDevice *kms_device;
+  struct gbm_device *gbm_device;
   MetaDrmBufferGbm *buffer_gbm;
   MetaDrmBufferImport *buffer_import;
   g_autoptr (GError) error = NULL;
 
   buffer_gbm = META_DRM_BUFFER_GBM (onscreen_native->gbm.next_fb);
 
-  buffer_import = meta_drm_buffer_import_new (secondary_gpu_state->gpu_kms,
+  gpu_kms = secondary_gpu_state->gpu_kms;
+  kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
+  gbm_device = meta_gbm_device_from_gpu (gpu_kms);
+  buffer_import = meta_drm_buffer_import_new (kms_device,
+                                              gbm_device,
                                               buffer_gbm,
                                               &error);
   if (!buffer_import)
@@ -1475,6 +1451,7 @@ copy_shared_framebuffer_gpu (CoglOnscreen                        *onscreen,
   MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
   MetaEgl *egl = meta_renderer_native_get_egl (renderer_native);
   GError *error = NULL;
+  MetaKmsDevice *kms_device;
   MetaDrmBufferGbm *buffer_gbm;
   struct gbm_bo *bo;
 
@@ -1523,8 +1500,9 @@ copy_shared_framebuffer_gpu (CoglOnscreen                        *onscreen,
       return;
     }
 
+  kms_device = meta_gpu_kms_get_kms_device (secondary_gpu_state->gpu_kms);
   buffer_gbm =
-    meta_drm_buffer_gbm_new_lock_front (secondary_gpu_state->gpu_kms,
+    meta_drm_buffer_gbm_new_lock_front (kms_device,
                                         secondary_gpu_state->gbm.surface,
                                         renderer_native->use_modifiers,
                                         &error);
@@ -1539,16 +1517,16 @@ copy_shared_framebuffer_gpu (CoglOnscreen                        *onscreen,
   secondary_gpu_state->gbm.next_fb = META_DRM_BUFFER (buffer_gbm);
 }
 
-static MetaDumbBuffer *
+static MetaDrmBufferDumb *
 secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
 {
-  MetaDumbBuffer *current_dumb_fb;
+  MetaDrmBufferDumb *current_dumb_fb;
 
-  current_dumb_fb = secondary_gpu_state->cpu.dumb_fb;
-  if (current_dumb_fb == &secondary_gpu_state->cpu.dumb_fbs[0])
-    return &secondary_gpu_state->cpu.dumb_fbs[1];
+  current_dumb_fb = secondary_gpu_state->cpu.current_dumb_fb;
+  if (current_dumb_fb == secondary_gpu_state->cpu.dumb_fbs[0])
+    return secondary_gpu_state->cpu.dumb_fbs[1];
   else
-    return &secondary_gpu_state->cpu.dumb_fbs[0];
+    return secondary_gpu_state->cpu.dumb_fbs[0];
 }
 
 static CoglContext *
@@ -1648,7 +1626,9 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen                        *onscre
   MetaRendererNative *renderer_native = onscreen_native->renderer_native;
   MetaRendererNativeGpuData *primary_gpu_data;
   MetaDrmBufferDumb *buffer_dumb;
-  MetaDumbBuffer *dumb_fb;
+  MetaDrmBuffer *buffer;
+  int width, height, stride;
+  uint32_t drm_format;
   CoglFramebuffer *dmabuf_fb;
   int dmabuf_fd;
   g_autoptr (GError) error = NULL;
@@ -1664,28 +1644,36 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen                        *onscre
   if (!primary_gpu_data->secondary.has_EGL_EXT_image_dma_buf_import_modifiers)
     return FALSE;
 
-  dumb_fb = secondary_gpu_get_next_dumb_buffer (secondary_gpu_state);
+  buffer_dumb = secondary_gpu_get_next_dumb_buffer (secondary_gpu_state);
+  buffer = META_DRM_BUFFER (buffer_dumb);
+
+  width = meta_drm_buffer_get_width (buffer);
+  height = meta_drm_buffer_get_height (buffer);
+  stride = meta_drm_buffer_get_stride (buffer);
+  drm_format = meta_drm_buffer_get_format (buffer);
 
-  g_assert (cogl_framebuffer_get_width (framebuffer) == dumb_fb->width);
-  g_assert (cogl_framebuffer_get_height (framebuffer) == dumb_fb->height);
+  g_assert (cogl_framebuffer_get_width (framebuffer) == width);
+  g_assert (cogl_framebuffer_get_height (framebuffer) == height);
 
-  ret = meta_cogl_pixel_format_from_drm_format (dumb_fb->drm_format,
+  ret = meta_cogl_pixel_format_from_drm_format (drm_format,
                                                 &cogl_format,
                                                 NULL);
   g_assert (ret);
 
-  dmabuf_fd = meta_dumb_buffer_ensure_dmabuf_fd (dumb_fb,
-                                                 secondary_gpu_state->gpu_kms);
-  if (dmabuf_fd == -1)
-    return FALSE;
+  dmabuf_fd = meta_drm_buffer_dumb_ensure_dmabuf_fd (buffer_dumb, &error);
+  if (!dmabuf_fd)
+    {
+      g_debug ("Failed to create DMA buffer: %s", error->message);
+      return FALSE;
+    }
 
   dmabuf_fb = create_dma_buf_framebuffer (renderer_native,
                                           dmabuf_fd,
-                                          dumb_fb->width,
-                                          dumb_fb->height,
-                                          dumb_fb->stride_bytes,
+                                          width,
+                                          height,
+                                          stride,
                                           0, DRM_FORMAT_MOD_LINEAR,
-                                          dumb_fb->drm_format,
+                                          drm_format,
                                           &error);
 
   if (error)
@@ -1697,8 +1685,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen                        *onscre
 
   if (!cogl_blit_framebuffer (framebuffer, COGL_FRAMEBUFFER (dmabuf_fb),
                               0, 0, 0, 0,
-                              dumb_fb->width,
-                              dumb_fb->height,
+                              width, height,
                               &error))
     {
       g_object_unref (dmabuf_fb);
@@ -1708,9 +1695,8 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen                        *onscre
   g_object_unref (dmabuf_fb);
 
   g_clear_object (&secondary_gpu_state->gbm.next_fb);
-  buffer_dumb = meta_drm_buffer_dumb_new (dumb_fb->fb_id);
-  secondary_gpu_state->gbm.next_fb = META_DRM_BUFFER (buffer_dumb);
-  secondary_gpu_state->cpu.dumb_fb = dumb_fb;
+  secondary_gpu_state->gbm.next_fb = buffer;
+  secondary_gpu_state->cpu.current_dumb_fb = buffer_dumb;
 
   return TRUE;
 }
@@ -1722,31 +1708,41 @@ copy_shared_framebuffer_cpu (CoglOnscreen                        *onscreen,
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer);
-  MetaDumbBuffer *dumb_fb;
+  MetaDrmBufferDumb *buffer_dumb;
+  MetaDrmBuffer *buffer;
+  int width, height, stride;
+  uint32_t drm_format;
+  void *buffer_data;
   CoglBitmap *dumb_bitmap;
   CoglPixelFormat cogl_format;
   gboolean ret;
-  MetaDrmBufferDumb *buffer_dumb;
 
   COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferCpu,
                            "FB Copy (CPU)");
 
-  dumb_fb = secondary_gpu_get_next_dumb_buffer (secondary_gpu_state);
+  buffer_dumb = secondary_gpu_get_next_dumb_buffer (secondary_gpu_state);
+  buffer = META_DRM_BUFFER (buffer_dumb);
 
-  g_assert (cogl_framebuffer_get_width (framebuffer) == dumb_fb->width);
-  g_assert (cogl_framebuffer_get_height (framebuffer) == dumb_fb->height);
+  width = meta_drm_buffer_get_width (buffer);
+  height = meta_drm_buffer_get_height (buffer);
+  stride = meta_drm_buffer_get_stride (buffer);
+  drm_format = meta_drm_buffer_get_format (buffer);
+  buffer_data = meta_drm_buffer_dumb_get_data (buffer_dumb);
 
-  ret = meta_cogl_pixel_format_from_drm_format (dumb_fb->drm_format,
+  g_assert (cogl_framebuffer_get_width (framebuffer) == width);
+  g_assert (cogl_framebuffer_get_height (framebuffer) == height);
+
+  ret = meta_cogl_pixel_format_from_drm_format (drm_format,
                                                 &cogl_format,
                                                 NULL);
   g_assert (ret);
 
   dumb_bitmap = cogl_bitmap_new_for_data (cogl_context,
-                                          dumb_fb->width,
-                                          dumb_fb->height,
+                                          width,
+                                          height,
                                           cogl_format,
-                                          dumb_fb->stride_bytes,
-                                          dumb_fb->map);
+                                          stride,
+                                          buffer_data);
 
   if (!cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
                                                  0 /* x */,
@@ -1758,9 +1754,8 @@ copy_shared_framebuffer_cpu (CoglOnscreen                        *onscreen,
   cogl_object_unref (dumb_bitmap);
 
   g_clear_object (&secondary_gpu_state->gbm.next_fb);
-  buffer_dumb = meta_drm_buffer_dumb_new (dumb_fb->fb_id);
-  secondary_gpu_state->gbm.next_fb = META_DRM_BUFFER (buffer_dumb);
-  secondary_gpu_state->cpu.dumb_fb = dumb_fb;
+  secondary_gpu_state->gbm.next_fb = buffer;
+  secondary_gpu_state->cpu.current_dumb_fb = buffer_dumb;
 }
 
 static void
@@ -1946,6 +1941,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen  *onscreen,
   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
   MetaGpuKms *render_gpu = onscreen_native->render_gpu;
+  MetaKmsDevice *render_kms_device = meta_gpu_kms_get_kms_device (render_gpu);
   gboolean egl_context_changed = FALSE;
   MetaPowerSave power_save_mode;
   g_autoptr (GError) error = NULL;
@@ -1971,7 +1967,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen  *onscreen,
       g_clear_object (&onscreen_native->gbm.next_fb);
 
       buffer_gbm =
-        meta_drm_buffer_gbm_new_lock_front (render_gpu,
+        meta_drm_buffer_gbm_new_lock_front (render_kms_device,
                                             onscreen_native->gbm.surface,
                                             renderer_native->use_modifiers,
                                             &error);
@@ -2427,154 +2423,6 @@ meta_renderer_native_create_surface_egl_device (CoglOnscreen  *onscreen,
 }
 #endif /* HAVE_EGL_DEVICE */
 
-static gboolean
-init_dumb_fb (MetaDumbBuffer  *dumb_fb,
-              MetaGpuKms      *gpu_kms,
-              int              width,
-              int              height,
-              uint32_t         format,
-              GError         **error)
-{
-  struct drm_mode_create_dumb create_arg;
-  struct drm_mode_destroy_dumb destroy_arg;
-  struct drm_mode_map_dumb map_arg;
-  uint32_t fb_id = 0;
-  void *map;
-  int kms_fd;
-  MetaGpuKmsFBArgs fb_args = {
-    .width = width,
-    .height = height,
-    .format = format,
-  };
-
-  kms_fd = meta_gpu_kms_get_fd (gpu_kms);
-
-  create_arg = (struct drm_mode_create_dumb) {
-    .bpp = 32, /* RGBX8888 */
-    .width = width,
-    .height = height
-  };
-  if (drmIoctl (kms_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg) != 0)
-    {
-      g_set_error (error, G_IO_ERROR,
-                   G_IO_ERROR_FAILED,
-                   "Failed to create dumb drm buffer: %s",
-                   g_strerror (errno));
-      goto err_ioctl;
-    }
-
-  fb_args.handles[0] = create_arg.handle;
-  fb_args.strides[0] = create_arg.pitch;
-
-  if (!meta_gpu_kms_add_fb (gpu_kms, FALSE, &fb_args, &fb_id, error))
-    goto err_add_fb;
-
-  map_arg = (struct drm_mode_map_dumb) {
-    .handle = create_arg.handle
-  };
-  if (drmIoctl (kms_fd, DRM_IOCTL_MODE_MAP_DUMB,
-                &map_arg) != 0)
-    {
-      g_set_error (error, G_IO_ERROR,
-                   G_IO_ERROR_FAILED,
-                   "Failed to map dumb drm buffer: %s",
-                   g_strerror (errno));
-      goto err_map_dumb;
-    }
-
-  map = mmap (NULL, create_arg.size, PROT_WRITE, MAP_SHARED,
-              kms_fd, map_arg.offset);
-  if (map == MAP_FAILED)
-    {
-      g_set_error (error, G_IO_ERROR,
-                   G_IO_ERROR_FAILED,
-                   "Failed to mmap dumb drm buffer memory: %s",
-                   g_strerror (errno));
-      goto err_mmap;
-    }
-
-  dumb_fb->fb_id = fb_id;
-  dumb_fb->handle = create_arg.handle;
-  dumb_fb->map = map;
-  dumb_fb->map_size = create_arg.size;
-  dumb_fb->width = width;
-  dumb_fb->height = height;
-  dumb_fb->stride_bytes = create_arg.pitch;
-  dumb_fb->drm_format = format;
-  dumb_fb->dmabuf_fd = -1;
-
-  return TRUE;
-
-err_mmap:
-err_map_dumb:
-  drmModeRmFB (kms_fd, fb_id);
-
-err_add_fb:
-  destroy_arg = (struct drm_mode_destroy_dumb) {
-    .handle = create_arg.handle
-  };
-  drmIoctl (kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
-
-err_ioctl:
-  return FALSE;
-}
-
-static int
-meta_dumb_buffer_ensure_dmabuf_fd (MetaDumbBuffer *dumb_fb,
-                                   MetaGpuKms     *gpu_kms)
-{
-  int ret;
-  int kms_fd;
-  int dmabuf_fd;
-
-  if (dumb_fb->dmabuf_fd != -1)
-    return dumb_fb->dmabuf_fd;
-
-  kms_fd = meta_gpu_kms_get_fd (gpu_kms);
-
-  ret = drmPrimeHandleToFD (kms_fd, dumb_fb->handle, DRM_CLOEXEC,
-                            &dmabuf_fd);
-  if (ret)
-    {
-      g_debug ("Failed to export dumb drm buffer: %s",
-               g_strerror (errno));
-      return -1;
-    }
-
-  dumb_fb->dmabuf_fd = dmabuf_fd;
-
-  return dumb_fb->dmabuf_fd;
-}
-
-static void
-release_dumb_fb (MetaDumbBuffer *dumb_fb,
-                 MetaGpuKms     *gpu_kms)
-{
-  struct drm_mode_destroy_dumb destroy_arg;
-  int kms_fd;
-
-  if (!dumb_fb->map)
-    return;
-
-  if (dumb_fb->dmabuf_fd != -1)
-    close (dumb_fb->dmabuf_fd);
-
-  munmap (dumb_fb->map, dumb_fb->map_size);
-
-  kms_fd = meta_gpu_kms_get_fd (gpu_kms);
-
-  drmModeRmFB (kms_fd, dumb_fb->fb_id);
-
-  destroy_arg = (struct drm_mode_destroy_dumb) {
-    .handle = dumb_fb->handle
-  };
-  drmIoctl (kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
-
-  *dumb_fb = (MetaDumbBuffer) {
-    .dmabuf_fd = -1,
-  };
-}
-
 static gboolean
 meta_renderer_native_init_onscreen (CoglOnscreen *onscreen,
                                     GError      **error)
@@ -2620,6 +2468,7 @@ meta_onscreen_native_allocate (CoglOnscreen *onscreen,
   int width;
   int height;
 #ifdef HAVE_EGL_DEVICE
+  MetaKmsDevice *render_kms_device;
   EGLStreamKHR egl_stream;
 #endif
 
@@ -2653,11 +2502,14 @@ meta_onscreen_native_allocate (CoglOnscreen *onscreen,
       break;
 #ifdef HAVE_EGL_DEVICE
     case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
-      if (!init_dumb_fb (&onscreen_native->egl.dumb_fb,
-                         onscreen_native->render_gpu,
-                         width, height,
-                         DRM_FORMAT_XRGB8888,
-                         error))
+      render_kms_device =
+        meta_gpu_kms_get_kms_device (onscreen_native->render_gpu);
+      onscreen_native->egl.dumb_fb =
+        meta_drm_buffer_dumb_new (render_kms_device,
+                                  width, height,
+                                  DRM_FORMAT_XRGB8888,
+                                  error);
+      if (!onscreen_native->egl.dumb_fb)
         return FALSE;
 
       if (!meta_renderer_native_create_surface_egl_device (onscreen,
@@ -2750,8 +2602,7 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
       break;
 #ifdef HAVE_EGL_DEVICE
     case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
-      release_dumb_fb (&onscreen_native->egl.dumb_fb,
-                       onscreen_native->render_gpu);
+      g_clear_object (&onscreen_native->egl.dumb_fb);
 
       destroy_egl_surface (onscreen);
 
diff --git a/src/meson.build b/src/meson.build
index 1dcddde3f0..fb1d2ab565 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -650,6 +650,7 @@ if have_native_backend
     'backends/native/meta-drm-buffer-gbm.h',
     'backends/native/meta-drm-buffer-import.c',
     'backends/native/meta-drm-buffer-import.h',
+    'backends/native/meta-drm-buffer-private.h',
     'backends/native/meta-drm-buffer.c',
     'backends/native/meta-drm-buffer.h',
     'backends/native/meta-gpu-kms.c',
diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c
index 211c85ff0e..5fd76cbfc4 100644
--- a/src/wayland/meta-wayland-buffer.c
+++ b/src/wayland/meta-wayland-buffer.c
@@ -687,6 +687,7 @@ try_acquire_egl_image_scanout (MetaWaylandBuffer *buffer,
   MetaRenderer *renderer = meta_backend_get_renderer (backend);
   MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
   MetaGpuKms *gpu_kms;
+  MetaKmsDevice *kms_device;
   struct gbm_device *gbm_device;
   struct gbm_bo *gbm_bo;
   uint32_t drm_format;
@@ -696,6 +697,7 @@ try_acquire_egl_image_scanout (MetaWaylandBuffer *buffer,
   g_autoptr (GError) error = NULL;
 
   gpu_kms = meta_renderer_native_get_primary_gpu (renderer_native);
+  kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
   gbm_device = meta_gbm_device_from_gpu (gpu_kms);
 
   gbm_bo = gbm_bo_import (gbm_device,
@@ -716,7 +718,7 @@ try_acquire_egl_image_scanout (MetaWaylandBuffer *buffer,
       return NULL;
     }
 
-  fb = meta_drm_buffer_gbm_new_take (gpu_kms, gbm_bo,
+  fb = meta_drm_buffer_gbm_new_take (kms_device, gbm_bo,
                                      drm_modifier != DRM_FORMAT_MOD_INVALID,
                                      &error);
   if (!fb)
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index e5a8f9a75b..7996958484 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -270,6 +270,7 @@ meta_wayland_dma_buf_try_acquire_scanout (MetaWaylandDmaBufBuffer *dma_buf,
   MetaRenderer *renderer = meta_backend_get_renderer (backend);
   MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
   MetaGpuKms *gpu_kms;
+  MetaKmsDevice *kms_device;
   int n_planes;
   uint32_t drm_format;
   uint64_t drm_modifier;
@@ -295,6 +296,7 @@ meta_wayland_dma_buf_try_acquire_scanout (MetaWaylandDmaBufBuffer *dma_buf,
     return NULL;
 
   gpu_kms = meta_renderer_native_get_primary_gpu (renderer_native);
+  kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
   gbm_bo = import_scanout_gbm_bo (dma_buf, gpu_kms, n_planes, &use_modifier);
   if (!gbm_bo)
     {
@@ -302,7 +304,7 @@ meta_wayland_dma_buf_try_acquire_scanout (MetaWaylandDmaBufBuffer *dma_buf,
       return NULL;
     }
 
-  fb = meta_drm_buffer_gbm_new_take (gpu_kms, gbm_bo,
+  fb = meta_drm_buffer_gbm_new_take (kms_device, gbm_bo,
                                      use_modifier,
                                      &error);
   if (!fb)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]