diff --git a/src/backends/native/meta-egl-gbm.c b/src/backends/native/meta-egl-gbm.c
new file mode 100644
index 000000000..c50d9556a
--- /dev/null
+++ b/src/backends/native/meta-egl-gbm.c
@@ -0,0 +1,150 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2016, 2017 Red Hat Inc.
+ * Copyright (C) 2018, 2019 DisplayLink (UK) 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, see .
+ *
+ * Written by:
+ * Jonas Ådahl
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#include "backends/native/meta-egl-gbm.h"
+
+typedef struct _GbmBoUserData
+{
+ EGLImageKHR egl_image;
+
+ MetaEgl *egl;
+ EGLDisplay egl_display;
+} GbmBoUserData;
+
+static EGLImageKHR
+create_gbm_bo_egl_image (MetaEgl *egl,
+ EGLDisplay egl_display,
+ struct gbm_bo *shared_bo,
+ GError **error)
+{
+ int shared_bo_fd;
+ unsigned int width;
+ unsigned int height;
+ uint32_t i, n_planes;
+ uint32_t strides[4] = { 0 };
+ uint32_t offsets[4] = { 0 };
+ uint64_t modifiers[4] = { 0 };
+ int fds[4] = { -1, -1, -1, -1 };
+ uint32_t format;
+ EGLImageKHR egl_image;
+ gboolean use_modifiers;
+
+ shared_bo_fd = gbm_bo_get_fd (shared_bo);
+ if (shared_bo_fd < 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Failed to export gbm_bo: %s", strerror (errno));
+ return FALSE;
+ }
+
+ width = gbm_bo_get_width (shared_bo);
+ height = gbm_bo_get_height (shared_bo);
+ format = gbm_bo_get_format (shared_bo);
+
+ n_planes = gbm_bo_get_plane_count (shared_bo);
+ for (i = 0; i < n_planes; i++)
+ {
+ strides[i] = gbm_bo_get_stride_for_plane (shared_bo, i);
+ offsets[i] = gbm_bo_get_offset (shared_bo, i);
+ modifiers[i] = gbm_bo_get_modifier (shared_bo);
+ fds[i] = shared_bo_fd;
+ }
+
+ /* Workaround for https://gitlab.gnome.org/GNOME/mutter/issues/18 */
+ if (modifiers[0] == DRM_FORMAT_MOD_LINEAR ||
+ modifiers[0] == DRM_FORMAT_MOD_INVALID)
+ use_modifiers = FALSE;
+ else
+ use_modifiers = TRUE;
+
+ egl_image = meta_egl_create_dmabuf_image (egl,
+ egl_display,
+ width,
+ height,
+ format,
+ n_planes,
+ fds,
+ strides,
+ offsets,
+ use_modifiers ? modifiers : NULL,
+ error);
+ close (shared_bo_fd);
+
+ return egl_image;
+}
+
+static void
+free_gbm_bo_egl_image (struct gbm_bo *bo,
+ void *data)
+{
+ GbmBoUserData *user_data = data;
+ g_autoptr (GError) error = NULL;
+
+ if (!meta_egl_destroy_image (user_data->egl,
+ user_data->egl_display,
+ user_data->egl_image,
+ &error))
+ {
+ g_warning ("Could not destroy EGLImage attached to GBM BO: %s", error->message);
+ }
+
+ g_free (data);
+}
+
+EGLImageKHR
+meta_egl_ensure_gbm_bo_egl_image (MetaEgl *egl,
+ EGLDisplay egl_display,
+ struct gbm_bo *bo,
+ GError **error)
+{
+ GbmBoUserData *bo_user_data = NULL;
+
+ bo_user_data = gbm_bo_get_user_data (bo);
+
+ if (!bo_user_data)
+ {
+ EGLImageKHR egl_image = EGL_NO_IMAGE;
+
+ egl_image = create_gbm_bo_egl_image (egl,
+ egl_display,
+ bo,
+ error);
+
+ if (!egl_image)
+ return EGL_NO_IMAGE;
+
+ bo_user_data = g_new0 (GbmBoUserData, 1);
+ bo_user_data->egl = egl;
+ bo_user_data->egl_display = egl_display;
+ bo_user_data->egl_image = egl_image;
+
+ gbm_bo_set_user_data (bo, bo_user_data, free_gbm_bo_egl_image);
+ }
+
+ return bo_user_data->egl_image;
+}
diff --git a/src/backends/native/meta-egl-gbm.h b/src/backends/native/meta-egl-gbm.h
new file mode 100644
index 000000000..6685db7f9
--- /dev/null
+++ b/src/backends/native/meta-egl-gbm.h
@@ -0,0 +1,34 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2016 Red Hat Inc.
+ * Copyright (C) 2019 DisplayLink (UK) 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, see .
+ *
+ * Written by:
+ * Jonas Ådahl
+ */
+
+#pragma once
+
+#include
+#include
+
+#include "backends/meta-egl.h"
+
+EGLImageKHR meta_egl_ensure_gbm_bo_egl_image (MetaEgl *egl,
+ EGLDisplay egl_display,
+ struct gbm_bo *shared_bo,
+ GError **error);
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
index a7a632abc..8006b9f52 100644
--- a/src/backends/native/meta-onscreen-native.c
+++ b/src/backends/native/meta-onscreen-native.c
@@ -50,6 +50,7 @@
#include "backends/native/meta-render-device.h"
#include "backends/native/meta-renderer-native-gles3.h"
#include "backends/native/meta-renderer-native-private.h"
+#include "backends/native/meta-egl-gbm.h"
#include "cogl/cogl.h"
#include "common/meta-cogl-drm-formats.h"
#include "common/meta-drm-format-helpers.h"
@@ -847,6 +848,7 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
struct gbm_bo *bo;
EGLSync egl_sync = EGL_NO_SYNC;
g_autofd int sync_fd = -1;
+ EGLImageKHR egl_image;
COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferSecondaryGpu,
"copy_shared_framebuffer_gpu()");
@@ -900,11 +902,19 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
buffer_gbm = META_DRM_BUFFER_GBM (primary_gpu_fb);
bo = meta_drm_buffer_gbm_get_bo (buffer_gbm);
+ egl_image = meta_egl_ensure_gbm_bo_egl_image (egl, egl_display, bo, error);
+
+ if (!egl_image)
+ {
+ g_prefix_error (error, "Failed to create EGL image from buffer object for secondary GPU: ");
+ goto done;
+ }
+
if (!meta_renderer_native_gles3_blit_shared_bo (egl,
gles3,
egl_display,
renderer_gpu_data->secondary.egl_context,
- secondary_gpu_state->egl_surface,
+ egl_image,
bo,
error))
{
diff --git a/src/backends/native/meta-renderer-native-gles3.c b/src/backends/native/meta-renderer-native-gles3.c
index b23e04f47..51a449a96 100644
--- a/src/backends/native/meta-renderer-native-gles3.c
+++ b/src/backends/native/meta-renderer-native-gles3.c
@@ -347,74 +347,12 @@ paint_egl_image (ContextData *context_data,
GLBAS (gles3, glDeleteTextures, (1, &texture));
}
-static EGLImageKHR
-meta_create_gbm_bo_egl_image (MetaEgl *egl,
- EGLDisplay egl_display,
- struct gbm_bo *shared_bo,
- GError **error)
-{
- int shared_bo_fd;
- unsigned int width;
- unsigned int height;
- uint32_t i, n_planes;
- uint32_t strides[4] = { 0 };
- uint32_t offsets[4] = { 0 };
- uint64_t modifiers[4] = { 0 };
- int fds[4] = { -1, -1, -1, -1 };
- uint32_t format;
- EGLImageKHR egl_image;
- gboolean use_modifiers;
-
- shared_bo_fd = gbm_bo_get_fd (shared_bo);
- if (shared_bo_fd < 0)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Failed to export gbm_bo: %s", strerror (errno));
- return FALSE;
- }
-
- width = gbm_bo_get_width (shared_bo);
- height = gbm_bo_get_height (shared_bo);
- format = gbm_bo_get_format (shared_bo);
-
- n_planes = gbm_bo_get_plane_count (shared_bo);
- for (i = 0; i < n_planes; i++)
- {
- strides[i] = gbm_bo_get_stride_for_plane (shared_bo, i);
- offsets[i] = gbm_bo_get_offset (shared_bo, i);
- modifiers[i] = gbm_bo_get_modifier (shared_bo);
- fds[i] = shared_bo_fd;
- }
-
- /* Workaround for https://gitlab.gnome.org/GNOME/mutter/issues/18 */
- if (modifiers[0] == DRM_FORMAT_MOD_LINEAR ||
- modifiers[0] == DRM_FORMAT_MOD_INVALID)
- use_modifiers = FALSE;
- else
- use_modifiers = TRUE;
-
- egl_image = meta_egl_create_dmabuf_image (egl,
- egl_display,
- width,
- height,
- format,
- n_planes,
- fds,
- strides,
- offsets,
- use_modifiers ? modifiers : NULL,
- error);
- close (shared_bo_fd);
-
- return egl_image;
-}
-
gboolean
meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl,
MetaGles3 *gles3,
EGLDisplay egl_display,
EGLContext egl_context,
- EGLSurface egl_surface,
+ EGLImageKHR egl_image,
struct gbm_bo *shared_bo,
GError **error)
{
@@ -423,7 +361,6 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl,
GQuark context_data_quark;
ContextData *context_data;
gboolean can_blit;
- EGLImageKHR egl_image = EGL_NO_IMAGE;
context_data_quark = get_quark_for_egl_context (egl_context);
context_data = g_object_get_qdata (G_OBJECT (gles3), context_data_quark);
@@ -447,18 +384,11 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl,
width = gbm_bo_get_width (shared_bo);
height = gbm_bo_get_height (shared_bo);
- egl_image = meta_create_gbm_bo_egl_image (egl,
- egl_display,
- shared_bo,
- error);
-
if (can_blit)
blit_egl_image (gles3, egl_image, width, height);
else
paint_egl_image (context_data, gles3, egl_image, width, height);
- meta_egl_destroy_image (egl, egl_display, egl_image, NULL);
-
return TRUE;
}
diff --git a/src/backends/native/meta-renderer-native-gles3.h b/src/backends/native/meta-renderer-native-gles3.h
index f5791a171..6a935c7e6 100644
--- a/src/backends/native/meta-renderer-native-gles3.h
+++ b/src/backends/native/meta-renderer-native-gles3.h
@@ -30,7 +30,7 @@ gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl,
MetaGles3 *gles3,
EGLDisplay egl_display,
EGLContext egl_context,
- EGLSurface egl_surface,
+ EGLImageKHR egl_image,
struct gbm_bo *shared_bo,
GError **error);
diff --git a/src/meson.build b/src/meson.build
index 12362093c..84640debe 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -791,6 +791,8 @@ if have_native_backend
'backends/native/meta-drm-buffer-private.h',
'backends/native/meta-drm-buffer.c',
'backends/native/meta-drm-buffer.h',
+ 'backends/native/meta-egl-gbm.c',
+ 'backends/native/meta-egl-gbm.h',
'backends/native/meta-gpu-kms.c',
'backends/native/meta-gpu-kms.h',
'backends/native/meta-frame-native.c',