[mutter] renderer-native: Reference count front buffers



commit fecc57ddf0d56e8893c0f44ea0b8af9dc76576cd
Author: Daniel van Vugt <daniel van vugt canonical com>
Date:   Tue Jan 30 17:47:17 2018 +0800

    renderer-native: Reference count front buffers
    
    Start reference counting front buffers instead of assuming we know
    their (scanout) lifetimes.
    
    Functionally, this should not change anything.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/119

 src/backends/native/meta-kms-buffer.c      | 287 +++++++++++++++++++++++++++++
 src/backends/native/meta-kms-buffer.h      |  50 +++++
 src/backends/native/meta-renderer-native.c | 235 +++++------------------
 src/meson.build                            |   2 +
 4 files changed, 390 insertions(+), 184 deletions(-)
---
diff --git a/src/backends/native/meta-kms-buffer.c b/src/backends/native/meta-kms-buffer.c
new file mode 100644
index 000000000..3527735f6
--- /dev/null
+++ b/src/backends/native/meta-kms-buffer.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2011 Intel Corporation.
+ * Copyright (C) 2016 Red Hat
+ * Copyright (C) 2018 DisplayLink (UK) Ltd.
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * 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.
+ *
+ * Author: Daniel van Vugt <daniel van vugt canonical com>
+ */
+
+#include "backends/native/meta-kms-buffer.h"
+
+#include "config.h"
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <drm_fourcc.h>
+#include <errno.h>
+
+#define INVALID_FB_ID 0U
+
+typedef enum _MetaKmsBufferType
+{
+  META_KMS_BUFFER_TYPE_GBM,
+  META_KMS_BUFFER_TYPE_WRAPPED_DUMB
+} MetaKmsBufferType;
+
+struct _MetaKmsBuffer
+{
+  GObject parent;
+
+  MetaKmsBufferType type;
+
+  union
+  {
+    uint32_t fb_id;
+
+    struct
+    {
+      uint32_t fb_id;
+      struct gbm_surface *surface;
+      struct gbm_bo *bo;
+      MetaGpuKms *gpu_kms;
+    } gbm;
+
+    struct
+    {
+      uint32_t fb_id;
+    } wrapped_dumb;
+  };
+};
+
+G_DEFINE_TYPE (MetaKmsBuffer, meta_kms_buffer, G_TYPE_OBJECT)
+
+static gboolean
+meta_kms_buffer_acquire_swapped_buffer (MetaKmsBuffer  *kms_buffer,
+                                        gboolean        use_modifiers,
+                                        GError        **error)
+{
+  uint32_t handles[4] = {0, 0, 0, 0};
+  uint32_t strides[4] = {0, 0, 0, 0};
+  uint32_t offsets[4] = {0, 0, 0, 0};
+  uint64_t modifiers[4] = {0, 0, 0, 0};
+  uint32_t width, height, format;
+  struct gbm_bo *bo;
+  int i;
+  int drm_fd;
+
+  g_return_val_if_fail (META_IS_KMS_BUFFER (kms_buffer), FALSE);
+  g_return_val_if_fail (kms_buffer->type == META_KMS_BUFFER_TYPE_GBM, FALSE);
+  g_return_val_if_fail (kms_buffer->gbm.bo == NULL, FALSE);
+  g_return_val_if_fail (kms_buffer->gbm.surface != NULL, FALSE);
+  g_return_val_if_fail (kms_buffer->gbm.gpu_kms != NULL, FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  drm_fd = meta_gpu_kms_get_fd (kms_buffer->gbm.gpu_kms);
+  g_return_val_if_fail (drm_fd >= 0, FALSE);
+
+  bo = gbm_surface_lock_front_buffer (kms_buffer->gbm.surface);
+  if (!bo)
+    {
+      g_set_error (error,
+                   G_IO_ERROR,
+                   G_IO_ERROR_FAILED,
+                   "gbm_surface_lock_front_buffer failed");
+      return FALSE;
+    }
+
+  if (gbm_bo_get_handle_for_plane (bo, 0).s32 == -1)
+    {
+      /* Failed to fetch handle to plane, falling back to old method */
+      strides[0] = gbm_bo_get_stride (bo);
+      handles[0] = gbm_bo_get_handle (bo).u32;
+      offsets[0] = 0;
+      modifiers[0] = DRM_FORMAT_MOD_INVALID;
+    }
+  else
+    {
+      for (i = 0; i < gbm_bo_get_plane_count (bo); i++)
+        {
+          strides[i] = gbm_bo_get_stride_for_plane (bo, i);
+          handles[i] = gbm_bo_get_handle_for_plane (bo, i).u32;
+          offsets[i] = gbm_bo_get_offset (bo, i);
+          modifiers[i] = gbm_bo_get_modifier (bo);
+        }
+     }
+
+  width = gbm_bo_get_width (bo);
+  height = gbm_bo_get_height (bo);
+  format = gbm_bo_get_format (bo);
+
+  if (use_modifiers && modifiers[0] != DRM_FORMAT_MOD_INVALID)
+    {
+      if (drmModeAddFB2WithModifiers (drm_fd,
+                                      width,
+                                      height,
+                                      format,
+                                      handles,
+                                      strides,
+                                      offsets,
+                                      modifiers,
+                                      &kms_buffer->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));
+          gbm_surface_release_buffer (kms_buffer->gbm.surface, bo);
+          return FALSE;
+        }
+    }
+  else if (drmModeAddFB2 (drm_fd,
+                          width,
+                          height,
+                          format,
+                          handles,
+                          strides,
+                          offsets,
+                          &kms_buffer->fb_id,
+                          0))
+    {
+      if (format != DRM_FORMAT_XRGB8888)
+        {
+          g_set_error (error,
+                       G_IO_ERROR,
+                       G_IO_ERROR_FAILED,
+                       "drmModeAddFB does not support format 0x%x",
+                       format);
+          gbm_surface_release_buffer (kms_buffer->gbm.surface, bo);
+          return FALSE;
+        }
+
+      if (drmModeAddFB (drm_fd,
+                        width,
+                        height,
+                        24,
+                        32,
+                        strides[0],
+                        handles[0],
+                        &kms_buffer->fb_id))
+        {
+          g_set_error (error,
+                       G_IO_ERROR,
+                       g_io_error_from_errno (errno),
+                       "drmModeAddFB failed: %s",
+                       g_strerror (errno));
+          gbm_surface_release_buffer (kms_buffer->gbm.surface, bo);
+          return FALSE;
+        }
+    }
+
+  kms_buffer->gbm.bo = bo;
+
+  return TRUE;
+}
+
+static void
+meta_kms_buffer_init (MetaKmsBuffer *kms_buffer)
+{
+}
+
+static void
+meta_kms_buffer_finalize (GObject *object)
+{
+  MetaKmsBuffer *kms_buffer = META_KMS_BUFFER (object);
+
+  if (kms_buffer->type == META_KMS_BUFFER_TYPE_GBM)
+    {
+      if (kms_buffer->gbm.gpu_kms != NULL &&
+          kms_buffer->gbm.fb_id != INVALID_FB_ID)
+        {
+          int drm_fd = meta_gpu_kms_get_fd (kms_buffer->gbm.gpu_kms);
+
+          drmModeRmFB (drm_fd, kms_buffer->fb_id);
+          kms_buffer->fb_id = INVALID_FB_ID;
+        }
+
+      if (kms_buffer->gbm.surface &&
+          kms_buffer->gbm.bo)
+        {
+          gbm_surface_release_buffer (kms_buffer->gbm.surface,
+                                      kms_buffer->gbm.bo);
+        }
+    }
+
+  G_OBJECT_CLASS (meta_kms_buffer_parent_class)->finalize (object);
+}
+
+static void
+meta_kms_buffer_class_init (MetaKmsBufferClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = meta_kms_buffer_finalize;
+}
+
+MetaKmsBuffer *
+meta_kms_buffer_new_from_gbm (MetaGpuKms          *gpu_kms,
+                              struct gbm_surface  *gbm_surface,
+                              gboolean             use_modifiers,
+                              GError             **error)
+{
+  MetaKmsBuffer *kms_buffer;
+
+  g_return_val_if_fail (META_IS_GPU_KMS (gpu_kms), NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  kms_buffer = g_object_new (META_TYPE_KMS_BUFFER, NULL);
+  kms_buffer->type = META_KMS_BUFFER_TYPE_GBM;
+  kms_buffer->gbm.gpu_kms = gpu_kms;
+  kms_buffer->gbm.surface = gbm_surface;
+
+  if (!meta_kms_buffer_acquire_swapped_buffer (kms_buffer,
+                                               use_modifiers,
+                                               error))
+    {
+      g_object_unref (kms_buffer);
+      return NULL;
+    }
+
+  return kms_buffer;
+}
+
+MetaKmsBuffer *
+meta_kms_buffer_new_from_dumb (uint32_t dumb_fb_id)
+{
+  MetaKmsBuffer *kms_buffer;
+
+  kms_buffer = g_object_new (META_TYPE_KMS_BUFFER, NULL);
+  kms_buffer->type = META_KMS_BUFFER_TYPE_WRAPPED_DUMB;
+  kms_buffer->wrapped_dumb.fb_id = dumb_fb_id;
+
+  return kms_buffer;
+}
+
+uint32_t
+meta_kms_buffer_get_fb_id (const MetaKmsBuffer *kms_buffer)
+{
+  g_return_val_if_fail (kms_buffer != NULL, INVALID_FB_ID);
+
+  return kms_buffer->fb_id;
+}
+
+struct gbm_bo *
+meta_kms_buffer_get_bo (const MetaKmsBuffer *kms_buffer)
+{
+  g_return_val_if_fail (kms_buffer != NULL, NULL);
+  g_return_val_if_fail (kms_buffer->type == META_KMS_BUFFER_TYPE_GBM, NULL);
+
+  return kms_buffer->gbm.bo;
+}
diff --git a/src/backends/native/meta-kms-buffer.h b/src/backends/native/meta-kms-buffer.h
new file mode 100644
index 000000000..74d02d543
--- /dev/null
+++ b/src/backends/native/meta-kms-buffer.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * 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.
+ *
+ * Author: Daniel van Vugt <daniel van vugt canonical com>
+ */
+
+#ifndef META_KMS_BUFFER_H
+#define META_KMS_BUFFER_H
+
+#include <gbm.h>
+#include <glib-object.h>
+
+#include "backends/native/meta-gpu-kms.h"
+
+#define META_TYPE_KMS_BUFFER (meta_kms_buffer_get_type ())
+G_DECLARE_FINAL_TYPE (MetaKmsBuffer,
+                      meta_kms_buffer,
+                      META,
+                      KMS_BUFFER,
+                      GObject)
+
+MetaKmsBuffer *
+meta_kms_buffer_new_from_gbm (MetaGpuKms          *gpu_kms,
+                              struct gbm_surface  *gbm_surface,
+                              gboolean             use_modifiers,
+                              GError             **error);
+
+MetaKmsBuffer *
+meta_kms_buffer_new_from_dumb (uint32_t dumb_fb_id);
+
+uint32_t meta_kms_buffer_get_fb_id (const MetaKmsBuffer *kms_buffer);
+
+struct gbm_bo *meta_kms_buffer_get_bo (const MetaKmsBuffer *kms_buffer);
+
+#endif /* META_KMS_BUFFER_H */
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index dbfc97aae..94b7f290b 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -59,6 +59,7 @@
 #include "backends/meta-renderer-view.h"
 #include "backends/native/meta-crtc-kms.h"
 #include "backends/native/meta-gpu-kms.h"
+#include "backends/native/meta-kms-buffer.h"
 #include "backends/native/meta-monitor-manager-kms.h"
 #include "backends/native/meta-renderer-native-gles3.h"
 #include "backends/native/meta-renderer-native.h"
@@ -144,10 +145,8 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState
 
   struct {
     struct gbm_surface *surface;
-    uint32_t current_fb_id;
-    uint32_t next_fb_id;
-    struct gbm_bo *current_bo;
-    struct gbm_bo *next_bo;
+    MetaKmsBuffer *current_fb;
+    MetaKmsBuffer *next_fb;
   } gbm;
 
   struct {
@@ -168,10 +167,8 @@ typedef struct _MetaOnscreenNative
 
   struct {
     struct gbm_surface *surface;
-    uint32_t current_fb_id;
-    uint32_t next_fb_id;
-    struct gbm_bo *current_bo;
-    struct gbm_bo *next_bo;
+    MetaKmsBuffer *current_fb;
+    MetaKmsBuffer *next_fb;
   } gbm;
 
 #ifdef HAVE_EGL_DEVICE
@@ -971,25 +968,12 @@ free_current_secondary_bo (MetaGpuKms                          *gpu_kms,
                            MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
 {
   MetaRendererNativeGpuData *renderer_gpu_data;
-  int kms_fd;
-
-  kms_fd = meta_gpu_kms_get_fd (gpu_kms);
 
   renderer_gpu_data = secondary_gpu_state->renderer_gpu_data;
   switch (renderer_gpu_data->secondary.copy_mode)
     {
     case META_SHARED_FRAMEBUFFER_COPY_MODE_GPU:
-      if (secondary_gpu_state->gbm.current_fb_id)
-        {
-          drmModeRmFB (kms_fd, secondary_gpu_state->gbm.current_fb_id);
-          secondary_gpu_state->gbm.current_fb_id = 0;
-        }
-      if (secondary_gpu_state->gbm.current_bo)
-        {
-          gbm_surface_release_buffer (secondary_gpu_state->gbm.surface,
-                                      secondary_gpu_state->gbm.current_bo);
-          secondary_gpu_state->gbm.current_bo = NULL;
-        }
+      g_clear_object (&secondary_gpu_state->gbm.current_fb);
       break;
     case META_SHARED_FRAMEBUFFER_COPY_MODE_CPU:
       break;
@@ -1001,22 +985,8 @@ free_current_bo (CoglOnscreen *onscreen)
 {
   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
-  MetaGpuKms *render_gpu = onscreen_native->render_gpu;
-  int kms_fd;
-
-  kms_fd = meta_gpu_kms_get_fd (render_gpu);
 
-  if (onscreen_native->gbm.current_fb_id)
-    {
-      drmModeRmFB (kms_fd, onscreen_native->gbm.current_fb_id);
-      onscreen_native->gbm.current_fb_id = 0;
-    }
-  if (onscreen_native->gbm.current_bo)
-    {
-      gbm_surface_release_buffer (onscreen_native->gbm.surface,
-                                  onscreen_native->gbm.current_bo);
-      onscreen_native->gbm.current_bo = NULL;
-    }
+  g_clear_object (&onscreen_native->gbm.current_fb);
 
   g_hash_table_foreach (onscreen_native->secondary_gpu_states,
                         (GHFunc) free_current_secondary_bo,
@@ -1310,11 +1280,9 @@ static void
 swap_secondary_drm_fb (MetaGpuKms                          *gpu_kms,
                        MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
 {
-  secondary_gpu_state->gbm.current_fb_id = secondary_gpu_state->gbm.next_fb_id;
-  secondary_gpu_state->gbm.next_fb_id = 0;
-
-  secondary_gpu_state->gbm.current_bo = secondary_gpu_state->gbm.next_bo;
-  secondary_gpu_state->gbm.next_bo = NULL;
+  g_set_object (&secondary_gpu_state->gbm.current_fb,
+                secondary_gpu_state->gbm.next_fb);
+  g_clear_object (&secondary_gpu_state->gbm.next_fb);
 }
 
 static void
@@ -1325,11 +1293,8 @@ meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen)
 
   free_current_bo (onscreen);
 
-  onscreen_native->gbm.current_fb_id = onscreen_native->gbm.next_fb_id;
-  onscreen_native->gbm.next_fb_id = 0;
-
-  onscreen_native->gbm.current_bo = onscreen_native->gbm.next_bo;
-  onscreen_native->gbm.next_bo = NULL;
+  g_set_object (&onscreen_native->gbm.current_fb, onscreen_native->gbm.next_fb);
+  g_clear_object (&onscreen_native->gbm.next_fb);
 
   g_hash_table_foreach (onscreen_native->secondary_gpu_states,
                         (GHFunc) swap_secondary_drm_fb,
@@ -1413,17 +1378,7 @@ free_next_secondary_bo (MetaGpuKms                          *gpu_kms,
   switch (renderer_gpu_data->secondary.copy_mode)
     {
     case META_SHARED_FRAMEBUFFER_COPY_MODE_GPU:
-      if (secondary_gpu_state->gbm.next_fb_id)
-        {
-          int kms_fd;
-
-          kms_fd = meta_gpu_kms_get_fd (gpu_kms);
-          drmModeRmFB (kms_fd, secondary_gpu_state->gbm.next_fb_id);
-          gbm_surface_release_buffer (secondary_gpu_state->gbm.surface,
-                                      secondary_gpu_state->gbm.next_bo);
-          secondary_gpu_state->gbm.next_fb_id = 0;
-          secondary_gpu_state->gbm.next_bo = NULL;
-        }
+      g_clear_object (&secondary_gpu_state->gbm.next_fb);
       break;
     case META_SHARED_FRAMEBUFFER_COPY_MODE_CPU:
       break;
@@ -1448,17 +1403,7 @@ flip_closure_destroyed (MetaRendererView *view)
   switch (renderer_gpu_data->mode)
     {
     case META_RENDERER_NATIVE_MODE_GBM:
-      if (onscreen_native->gbm.next_fb_id)
-        {
-          int kms_fd;
-
-          kms_fd = meta_gpu_kms_get_fd (render_gpu);
-          drmModeRmFB (kms_fd, onscreen_native->gbm.next_fb_id);
-          gbm_surface_release_buffer (onscreen_native->gbm.surface,
-                                      onscreen_native->gbm.next_bo);
-          onscreen_native->gbm.next_bo = NULL;
-          onscreen_native->gbm.next_fb_id = 0;
-        }
+      g_clear_object (&onscreen_native->gbm.next_fb);
 
       g_hash_table_foreach (onscreen_native->secondary_gpu_states,
                             (GHFunc) free_next_secondary_bo,
@@ -1808,12 +1753,12 @@ meta_onscreen_native_flip_crtc (CoglOnscreen  *onscreen,
     case META_RENDERER_NATIVE_MODE_GBM:
       if (gpu_kms == render_gpu)
         {
-          fb_id = onscreen_native->gbm.next_fb_id;
+          fb_id = meta_kms_buffer_get_fb_id (onscreen_native->gbm.next_fb);
         }
       else
         {
           secondary_gpu_state = get_secondary_gpu_state (onscreen, gpu_kms);
-          fb_id = secondary_gpu_state->gbm.next_fb_id;
+          fb_id = meta_kms_buffer_get_fb_id (secondary_gpu_state->gbm.next_fb);
         }
 
       if (!meta_gpu_kms_flip_crtc (gpu_kms,
@@ -1879,7 +1824,7 @@ set_crtc_fb (CoglOnscreen       *onscreen,
       if (!secondary_gpu_state)
         return;
 
-      fb_id = secondary_gpu_state->gbm.next_fb_id;
+      fb_id = meta_kms_buffer_get_fb_id (secondary_gpu_state->gbm.next_fb);
     }
 
   x = crtc->rect.x - logical_monitor->rect.x;
@@ -1922,7 +1867,7 @@ meta_onscreen_native_set_crtc_modes (CoglOnscreen *onscreen)
   switch (renderer_gpu_data->mode)
     {
     case META_RENDERER_NATIVE_MODE_GBM:
-      fb_id = onscreen_native->gbm.next_fb_id;
+      fb_id = meta_kms_buffer_get_fb_id (onscreen_native->gbm.next_fb);
       break;
 #ifdef HAVE_EGL_DEVICE
     case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
@@ -1990,7 +1935,7 @@ crtc_mode_set_fallback (CoglOnscreen       *onscreen,
       return FALSE;
     }
 
-  fb_id = onscreen_native->gbm.next_fb_id;
+  fb_id = meta_kms_buffer_get_fb_id (onscreen_native->gbm.next_fb);
   set_crtc_fb (onscreen, logical_monitor, crtc, fb_id);
   return TRUE;
 }
@@ -2090,101 +2035,6 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen)
   g_closure_unref (flip_closure);
 }
 
-static gboolean
-gbm_get_next_fb_id (MetaGpuKms         *gpu_kms,
-                    struct gbm_surface *gbm_surface,
-                    struct gbm_bo     **out_next_bo,
-                    uint32_t           *out_next_fb_id)
-{
-  MetaRendererNative *renderer_native = meta_renderer_native_from_gpu (gpu_kms);
-  struct gbm_bo *next_bo;
-  uint32_t next_fb_id;
-  int kms_fd;
-  uint32_t handles[4] = { 0, };
-  uint32_t strides[4] = { 0, };
-  uint32_t offsets[4] = { 0, };
-  uint64_t modifiers[4] = { 0, };
-  int i;
-
-  /* Now we need to set the CRTC to whatever is the front buffer */
-  next_bo = gbm_surface_lock_front_buffer (gbm_surface);
-
-  if (!next_bo)
-    {
-      g_error ("Impossible to lock surface front buffer: %m");
-      return FALSE;
-    }
-
-  if (gbm_bo_get_handle_for_plane (next_bo, 0).s32 == -1)
-    {
-      /* Failed to fetch handle to plane, falling back to old method */
-      strides[0] = gbm_bo_get_stride (next_bo);
-      handles[0] = gbm_bo_get_handle (next_bo).u32;
-      offsets[0] = 0;
-      modifiers[0] = DRM_FORMAT_MOD_INVALID;
-    }
-  else
-    {
-      for (i = 0; i < gbm_bo_get_plane_count (next_bo); i++)
-        {
-          strides[i] = gbm_bo_get_stride_for_plane (next_bo, i);
-          handles[i] = gbm_bo_get_handle_for_plane (next_bo, i).u32;
-          offsets[i] = gbm_bo_get_offset (next_bo, i);
-          modifiers[i] = gbm_bo_get_modifier (next_bo);
-        }
-    }
-
-  kms_fd = meta_gpu_kms_get_fd (gpu_kms);
-
-  if (renderer_native->use_modifiers &&
-      modifiers[0] != DRM_FORMAT_MOD_INVALID)
-    {
-      if (drmModeAddFB2WithModifiers (kms_fd,
-                                      gbm_bo_get_width (next_bo),
-                                      gbm_bo_get_height (next_bo),
-                                      gbm_bo_get_format (next_bo),
-                                      handles,
-                                      strides,
-                                      offsets,
-                                      modifiers,
-                                      &next_fb_id,
-                                      DRM_MODE_FB_MODIFIERS))
-        {
-          g_warning ("Failed to create new back buffer handle: %m");
-          gbm_surface_release_buffer (gbm_surface, next_bo);
-          return FALSE;
-        }
-    }
-  else if (drmModeAddFB2 (kms_fd,
-                          gbm_bo_get_width (next_bo),
-                          gbm_bo_get_height (next_bo),
-                          gbm_bo_get_format (next_bo),
-                          handles,
-                          strides,
-                          offsets,
-                          &next_fb_id,
-                          0))
-    {
-      if (drmModeAddFB (kms_fd,
-                        gbm_bo_get_width (next_bo),
-                        gbm_bo_get_height (next_bo),
-                        24, /* depth */
-                        32, /* bpp */
-                        strides[0],
-                        handles[0],
-                        &next_fb_id))
-        {
-          g_warning ("Failed to create new back buffer handle: %m");
-          gbm_surface_release_buffer (gbm_surface, next_bo);
-          return FALSE;
-        }
-    }
-
-  *out_next_bo = next_bo;
-  *out_next_fb_id = next_fb_id;
-  return TRUE;
-}
-
 static void
 wait_for_pending_flips (CoglOnscreen *onscreen)
 {
@@ -2237,7 +2087,7 @@ copy_shared_framebuffer_gpu (CoglOnscreen                        *onscreen,
                                                   renderer_gpu_data->egl_display,
                                                   renderer_gpu_data->secondary.egl_context,
                                                   secondary_gpu_state->egl_surface,
-                                                  onscreen_native->gbm.next_bo,
+                                                  meta_kms_buffer_get_bo (onscreen_native->gbm.next_fb),
                                                   &error))
     {
       g_warning ("Failed to blit shared framebuffer: %s", error->message);
@@ -2255,10 +2105,19 @@ copy_shared_framebuffer_gpu (CoglOnscreen                        *onscreen,
       return;
     }
 
-  gbm_get_next_fb_id (secondary_gpu_state->gpu_kms,
-                      secondary_gpu_state->gbm.surface,
-                      &secondary_gpu_state->gbm.next_bo,
-                      &secondary_gpu_state->gbm.next_fb_id);
+  g_clear_object (&secondary_gpu_state->gbm.next_fb);
+  secondary_gpu_state->gbm.next_fb =
+    meta_kms_buffer_new_from_gbm (secondary_gpu_state->gpu_kms,
+                                  secondary_gpu_state->gbm.surface,
+                                  renderer_native->use_modifiers,
+                                  &error);
+  if (!secondary_gpu_state->gbm.next_fb)
+    {
+      g_warning ("meta_kms_buffer_new_from_gbm failed: %s",
+                 error->message);
+      g_error_free (error);
+      return;
+    }
 }
 
 typedef struct _PixelFormatMap {
@@ -2377,7 +2236,9 @@ copy_shared_framebuffer_cpu (CoglOnscreen                        *onscreen,
 
   cogl_object_unref (dumb_bitmap);
 
-  secondary_gpu_state->gbm.next_fb_id = target_fb_id;
+  g_clear_object (&secondary_gpu_state->gbm.next_fb);
+  secondary_gpu_state->gbm.next_fb =
+    meta_kms_buffer_new_from_dumb (target_fb_id);
 }
 
 static void
@@ -2464,6 +2325,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
   CoglFrameInfo *frame_info;
   gboolean egl_context_changed = FALSE;
   MetaPowerSave power_save_mode;
+  g_autoptr (GError) error = NULL;
 
   /*
    * Wait for the flip callback before continuing, as we might have started the
@@ -2485,14 +2347,19 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
   switch (renderer_gpu_data->mode)
     {
     case META_RENDERER_NATIVE_MODE_GBM:
-      g_warn_if_fail (onscreen_native->gbm.next_bo == NULL &&
-                      onscreen_native->gbm.next_fb_id == 0);
-
-      if (!gbm_get_next_fb_id (render_gpu,
-                               onscreen_native->gbm.surface,
-                               &onscreen_native->gbm.next_bo,
-                               &onscreen_native->gbm.next_fb_id))
-        return;
+      g_warn_if_fail (onscreen_native->gbm.next_fb == NULL);
+      g_clear_object (&onscreen_native->gbm.next_fb);
+      onscreen_native->gbm.next_fb =
+        meta_kms_buffer_new_from_gbm (render_gpu,
+                                      onscreen_native->gbm.surface,
+                                      renderer_native->use_modifiers,
+                                      &error);
+      if (!onscreen_native->gbm.next_fb)
+        {
+          g_warning ("meta_kms_buffer_new_from_gbm failed: %s",
+                     error->message);
+          return;
+        }
 
       break;
 #ifdef HAVE_EGL_DEVICE
@@ -3083,7 +2950,7 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
     case META_RENDERER_NATIVE_MODE_GBM:
       /* flip state takes a reference on the onscreen so there should
        * never be outstanding flips when we reach here. */
-      g_return_if_fail (onscreen_native->gbm.next_fb_id == 0);
+      g_return_if_fail (onscreen_native->gbm.next_fb == NULL);
 
       free_current_bo (onscreen);
 
diff --git a/src/meson.build b/src/meson.build
index cc0fa25ce..74fe879d8 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -578,6 +578,8 @@ if have_native_backend
     'backends/native/meta-gpu-kms.h',
     'backends/native/meta-input-settings-native.c',
     'backends/native/meta-input-settings-native.h',
+    'backends/native/meta-kms-buffer.c',
+    'backends/native/meta-kms-buffer.h',
     'backends/native/meta-launcher.c',
     'backends/native/meta-launcher.h',
     'backends/native/meta-monitor-manager-kms.c',


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