[mutter] Introduce MetaRenderDevice{Gbm,EglStream,Surfaceless}
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] Introduce MetaRenderDevice{Gbm,EglStream,Surfaceless}
- Date: Mon, 18 Oct 2021 16:45:45 +0000 (UTC)
commit 2047d2d4e9ab38586f6c3cbb7508b4837941bd0e
Author: Jonas Ã…dahl <jadahl gmail com>
Date: Mon May 3 19:23:52 2021 +0200
Introduce MetaRenderDevice{Gbm,EglStream,Surfaceless}
The purpose of MetaRenderDevice is to contain the logics related to a
render device; i.e. e.g. a gbm_device, or an EGLDevice. It's meant to
help abstract away unrelated details from where it's eventually used,
which will be by MetaRendererNative and the MetaOnscreenNative
instances.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1854>
.../native/meta-render-device-egl-stream.c | 286 +++++++++++++++++
.../native/meta-render-device-egl-stream.h | 35 +++
src/backends/native/meta-render-device-gbm.c | 155 ++++++++++
src/backends/native/meta-render-device-gbm.h | 35 +++
src/backends/native/meta-render-device-private.h | 39 +++
.../native/meta-render-device-surfaceless.c | 92 ++++++
.../native/meta-render-device-surfaceless.h | 34 +++
src/backends/native/meta-render-device.c | 340 +++++++++++++++++++++
src/backends/native/meta-render-device.h | 43 +++
src/meson.build | 14 +
10 files changed, 1073 insertions(+)
---
diff --git a/src/backends/native/meta-render-device-egl-stream.c
b/src/backends/native/meta-render-device-egl-stream.c
new file mode 100644
index 0000000000..fa287a66d5
--- /dev/null
+++ b/src/backends/native/meta-render-device-egl-stream.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2016-2021 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.
+ *
+ */
+
+#include "config.h"
+
+#include "backends/native/meta-render-device-egl-stream.h"
+
+#include "backends/meta-backend-private.h"
+
+struct _MetaRenderDeviceEglStream
+{
+ MetaRenderDevice parent;
+
+ EGLDeviceEXT egl_device;
+};
+
+static GInitableIface *initable_parent_iface;
+
+static void
+initable_iface_init (GInitableIface *initable_iface);
+
+G_DEFINE_TYPE_WITH_CODE (MetaRenderDeviceEglStream, meta_render_device_egl_stream,
+ META_TYPE_RENDER_DEVICE,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ initable_iface_init))
+
+static EGLDisplay
+get_egl_device_display (MetaRenderDevice *render_device,
+ EGLDeviceEXT egl_device,
+ GError **error)
+{
+ MetaBackend *backend = meta_render_device_get_backend (render_device);
+ MetaEgl *egl = meta_backend_get_egl (backend);
+ MetaDeviceFile *device_file =
+ meta_render_device_get_device_file (render_device);
+ int kms_fd = meta_device_file_get_fd (device_file);
+ EGLint platform_attribs[] = {
+ EGL_DRM_MASTER_FD_EXT, kms_fd,
+ EGL_NONE
+ };
+
+ return meta_egl_get_platform_display (egl, EGL_PLATFORM_DEVICE_EXT,
+ (void *) egl_device,
+ platform_attribs,
+ error);
+}
+
+static int
+count_mode_setting_devices (MetaBackend *backend)
+{
+ return g_list_length (meta_backend_get_gpus (backend));
+}
+
+static const char *
+get_drm_device_file (MetaEgl *egl,
+ EGLDeviceEXT device,
+ GError **error)
+{
+ if (!meta_egl_egl_device_has_extensions (egl, device,
+ NULL,
+ "EGL_EXT_device_drm",
+ NULL))
+ {
+ g_set_error (error, G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Missing required EGLDevice extension EGL_EXT_device_drm");
+ return NULL;
+ }
+
+ return meta_egl_query_device_string (egl, device,
+ EGL_DRM_DEVICE_FILE_EXT,
+ error);
+}
+
+static EGLDeviceEXT
+find_egl_device (MetaRenderDevice *render_device,
+ GError **error)
+{
+ MetaBackend *backend = meta_render_device_get_backend (render_device);
+ MetaEgl *egl = meta_backend_get_egl (backend);
+ g_autofree const char **missing_extensions = NULL;
+ MetaDeviceFile *device_file =
+ meta_render_device_get_device_file (render_device);
+ EGLint num_devices;
+ g_autofree EGLDeviceEXT *devices = NULL;
+ const char *device_file_path;
+ EGLDeviceEXT device;
+ EGLint i;
+
+ if (!meta_egl_has_extensions (egl,
+ EGL_NO_DISPLAY,
+ &missing_extensions,
+ "EGL_EXT_device_base",
+ NULL))
+ {
+ g_autofree char *missing_extensions_str = NULL;
+
+ missing_extensions_str = g_strjoinv (", ", (char **) missing_extensions);
+ g_set_error (error, G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Missing EGL extensions required for EGLDevice renderer: %s",
+ missing_extensions_str);
+ return EGL_NO_DEVICE_EXT;
+ }
+
+ if (!meta_egl_query_devices (egl, 0, NULL, &num_devices, error))
+ return EGL_NO_DEVICE_EXT;
+
+ devices = g_new0 (EGLDeviceEXT, num_devices);
+ if (!meta_egl_query_devices (egl, num_devices, devices, &num_devices,
+ error))
+ return EGL_NO_DEVICE_EXT;
+
+ device_file_path = meta_device_file_get_path (device_file);
+
+ device = EGL_NO_DEVICE_EXT;
+ for (i = 0; i < num_devices; i++)
+ {
+ const char *egl_device_drm_path;
+
+ g_clear_error (error);
+
+ egl_device_drm_path = get_drm_device_file (egl, devices[i], error);
+ if (!egl_device_drm_path)
+ continue;
+
+ if (g_str_equal (egl_device_drm_path, device_file_path))
+ {
+ device = devices[i];
+ break;
+ }
+ }
+
+ if (device == EGL_NO_DEVICE_EXT)
+ {
+ if (!*error)
+ g_set_error (error, G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Failed to find matching EGLDeviceEXT");
+ return EGL_NO_DEVICE_EXT;
+ }
+
+ return device;
+}
+
+static gboolean
+meta_render_device_egl_stream_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ MetaRenderDevice *render_device = META_RENDER_DEVICE (initable);
+ MetaRenderDeviceEglStream *render_device_egl_stream =
+ META_RENDER_DEVICE_EGL_STREAM (initable);
+ MetaBackend *backend = meta_render_device_get_backend (render_device);
+ EGLDeviceEXT egl_device;
+ EGLDisplay egl_display;
+ g_autofree const char **missing_extensions = NULL;
+
+ if (count_mode_setting_devices (backend) != 1)
+ {
+ g_set_error (error, G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "EGLDevice currently only works with single GPU systems");
+ return FALSE;
+ }
+
+ egl_device = find_egl_device (render_device, error);
+ if (egl_device == EGL_NO_DEVICE_EXT)
+ return FALSE;
+
+ render_device_egl_stream->egl_device = egl_device;
+
+ if (!initable_parent_iface->init (initable, cancellable, error))
+ return FALSE;
+
+ egl_display = meta_render_device_get_egl_display (render_device);
+ if (egl_display == EGL_NO_DISPLAY)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "EGLStream render device requires an EGL display");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+initable_iface_init (GInitableIface *initable_iface)
+{
+ initable_parent_iface = g_type_interface_peek_parent (initable_iface);
+
+ initable_iface->init = meta_render_device_egl_stream_initable_init;
+}
+
+static EGLDisplay
+meta_render_device_egl_stream_create_egl_display (MetaRenderDevice *render_device,
+ GError **error)
+{
+ MetaRenderDeviceEglStream *render_device_egl_stream =
+ META_RENDER_DEVICE_EGL_STREAM (render_device);
+ EGLDeviceEXT egl_device = render_device_egl_stream->egl_device;
+ MetaBackend *backend = meta_render_device_get_backend (render_device);
+ MetaEgl *egl = meta_backend_get_egl (backend);
+ EGLDisplay egl_display;
+ g_autofree const char **missing_extensions = NULL;
+
+ egl_display = get_egl_device_display (render_device, egl_device, error);
+ if (egl_display == EGL_NO_DISPLAY)
+ return EGL_NO_DISPLAY;
+
+ if (!meta_egl_initialize (egl, egl_display, error))
+ {
+ meta_egl_terminate (egl, egl_display, NULL);
+ return EGL_NO_DISPLAY;
+ }
+
+ if (!meta_egl_has_extensions (egl,
+ egl_display,
+ &missing_extensions,
+ "EGL_NV_output_drm_flip_event",
+ "EGL_EXT_output_base",
+ "EGL_EXT_output_drm",
+ "EGL_KHR_stream",
+ "EGL_KHR_stream_producer_eglsurface",
+ "EGL_EXT_stream_consumer_egloutput",
+ "EGL_EXT_stream_acquire_mode",
+ NULL))
+ {
+ g_autofree char *missing_extensions_str = NULL;
+
+ meta_egl_terminate (egl, egl_display, NULL);
+
+ missing_extensions_str = g_strjoinv (", ", (char **) missing_extensions);
+ g_set_error (error, G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Missing EGL extensions required for EGLDevice renderer: %s",
+ missing_extensions_str);
+ meta_egl_terminate (egl, egl_display, NULL);
+ return EGL_NO_DISPLAY;
+ }
+
+ return egl_display;
+}
+
+static void
+meta_render_device_egl_stream_class_init (MetaRenderDeviceEglStreamClass *klass)
+{
+ MetaRenderDeviceClass *render_device_class = META_RENDER_DEVICE_CLASS (klass);
+
+ render_device_class->create_egl_display =
+ meta_render_device_egl_stream_create_egl_display;
+}
+
+static void
+meta_render_device_egl_stream_init (MetaRenderDeviceEglStream *render_device_egl_stream)
+{
+}
+
+MetaRenderDeviceEglStream *
+meta_render_device_egl_stream_new (MetaBackend *backend,
+ MetaDeviceFile *device_file,
+ GError **error)
+{
+ return g_initable_new (META_TYPE_RENDER_DEVICE_EGL_STREAM,
+ NULL, error,
+ "backend", backend,
+ "device-file", device_file,
+ NULL);
+}
diff --git a/src/backends/native/meta-render-device-egl-stream.h
b/src/backends/native/meta-render-device-egl-stream.h
new file mode 100644
index 0000000000..b4b66b8b17
--- /dev/null
+++ b/src/backends/native/meta-render-device-egl-stream.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 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_RENDER_DEVICE_EGL_STREAM_H
+#define META_RENDER_DEVICE_EGL_STREAM_H
+
+#include "backends/native/meta-render-device-private.h"
+
+#define META_TYPE_RENDER_DEVICE_EGL_STREAM (meta_render_device_egl_stream_get_type ())
+G_DECLARE_FINAL_TYPE (MetaRenderDeviceEglStream, meta_render_device_egl_stream,
+ META, RENDER_DEVICE_EGL_STREAM,
+ MetaRenderDevice)
+
+MetaRenderDeviceEglStream * meta_render_device_egl_stream_new (MetaBackend *backend,
+ MetaDeviceFile *device_file,
+ GError **error);
+
+#endif /* META_RENDER_DEVICE_EGL_STREAM_H */
diff --git a/src/backends/native/meta-render-device-gbm.c b/src/backends/native/meta-render-device-gbm.c
new file mode 100644
index 0000000000..5dc99d379e
--- /dev/null
+++ b/src/backends/native/meta-render-device-gbm.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2016-2021 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include "backends/native/meta-render-device-gbm.h"
+
+#include <gbm.h>
+
+#include "backends/meta-backend-private.h"
+
+struct _MetaRenderDeviceGbm
+{
+ MetaRenderDevice parent;
+
+ struct gbm_device *gbm_device;
+};
+
+static GInitableIface *initable_parent_iface;
+
+static void
+initable_iface_init (GInitableIface *initable_iface);
+
+G_DEFINE_TYPE_WITH_CODE (MetaRenderDeviceGbm, meta_render_device_gbm,
+ META_TYPE_RENDER_DEVICE,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ initable_iface_init))
+
+static gboolean
+meta_render_device_gbm_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ MetaRenderDevice *render_device = META_RENDER_DEVICE (initable);
+ MetaRenderDeviceGbm *render_device_gbm = META_RENDER_DEVICE_GBM (initable);
+ MetaDeviceFile *device_file =
+ meta_render_device_get_device_file (render_device);
+ struct gbm_device *gbm_device;
+
+ gbm_device = gbm_create_device (meta_device_file_get_fd (device_file));
+ if (!gbm_device)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Failed to create gbm device: %s", g_strerror (errno));
+ return FALSE;
+ }
+
+ render_device_gbm->gbm_device = gbm_device;
+
+ return initable_parent_iface->init (initable, cancellable, error);
+}
+
+static void
+initable_iface_init (GInitableIface *initable_iface)
+{
+ initable_parent_iface = g_type_interface_peek_parent (initable_iface);
+
+ initable_iface->init = meta_render_device_gbm_initable_init;
+}
+
+static EGLDisplay
+meta_render_device_gbm_create_egl_display (MetaRenderDevice *render_device,
+ GError **error)
+{
+ MetaRenderDeviceGbm *render_device_gbm =
+ META_RENDER_DEVICE_GBM (render_device);
+ MetaBackend *backend = meta_render_device_get_backend (render_device);
+ MetaEgl *egl = meta_backend_get_egl (backend);
+ EGLDisplay egl_display;
+
+ if (!meta_egl_has_extensions (egl, EGL_NO_DISPLAY, NULL,
+ "EGL_MESA_platform_gbm",
+ NULL) &&
+ !meta_egl_has_extensions (egl, EGL_NO_DISPLAY, NULL,
+ "EGL_KHR_platform_gbm",
+ NULL))
+ {
+ g_set_error (error, G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Missing extension for GBM renderer: EGL_KHR_platform_gbm");
+ return EGL_NO_DISPLAY;
+ }
+
+ egl_display = meta_egl_get_platform_display (egl,
+ EGL_PLATFORM_GBM_KHR,
+ render_device_gbm->gbm_device,
+ NULL, error);
+ if (egl_display == EGL_NO_DISPLAY)
+ return EGL_NO_DISPLAY;
+
+ if (!meta_egl_initialize (egl, egl_display, error))
+ {
+ meta_egl_terminate (egl, egl_display, NULL);
+ return EGL_NO_DISPLAY;
+ }
+
+ return egl_display;
+}
+
+static void
+meta_render_device_gbm_finalize (GObject *object)
+{
+ MetaRenderDeviceGbm *render_device_gbm = META_RENDER_DEVICE_GBM (object);
+
+ g_clear_pointer (&render_device_gbm->gbm_device, gbm_device_destroy);
+
+ G_OBJECT_CLASS (meta_render_device_gbm_parent_class)->finalize (object);
+}
+
+static void
+meta_render_device_gbm_class_init (MetaRenderDeviceGbmClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MetaRenderDeviceClass *render_device_class = META_RENDER_DEVICE_CLASS (klass);
+
+ object_class->finalize = meta_render_device_gbm_finalize;
+
+ render_device_class->create_egl_display =
+ meta_render_device_gbm_create_egl_display;
+}
+
+static void
+meta_render_device_gbm_init (MetaRenderDeviceGbm *render_device_gbm)
+{
+}
+
+MetaRenderDeviceGbm *
+meta_render_device_gbm_new (MetaBackend *backend,
+ MetaDeviceFile *device_file,
+ GError **error)
+{
+ return g_initable_new (META_TYPE_RENDER_DEVICE_GBM,
+ NULL, error,
+ "backend", backend,
+ "device-file", device_file,
+ NULL);
+}
diff --git a/src/backends/native/meta-render-device-gbm.h b/src/backends/native/meta-render-device-gbm.h
new file mode 100644
index 0000000000..c831b0d407
--- /dev/null
+++ b/src/backends/native/meta-render-device-gbm.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 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_RENDER_DEVICE_GBM_H
+#define META_RENDER_DEVICE_GBM_H
+
+#include "backends/native/meta-render-device-private.h"
+
+#define META_TYPE_RENDER_DEVICE_GBM (meta_render_device_gbm_get_type ())
+G_DECLARE_FINAL_TYPE (MetaRenderDeviceGbm, meta_render_device_gbm,
+ META, RENDER_DEVICE_GBM,
+ MetaRenderDevice)
+
+MetaRenderDeviceGbm * meta_render_device_gbm_new (MetaBackend *backend,
+ MetaDeviceFile *device_file,
+ GError **error);
+
+#endif /* META_RENDER_DEVICE_GBM_H */
diff --git a/src/backends/native/meta-render-device-private.h
b/src/backends/native/meta-render-device-private.h
new file mode 100644
index 0000000000..f064160bc7
--- /dev/null
+++ b/src/backends/native/meta-render-device-private.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 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_RENDER_DEVICE_PRIVATE_H
+#define META_RENDER_DEVICE_PRIVATE_H
+
+#include <gio/gio.h>
+#include <glib-object.h>
+
+#include "backends/meta-egl.h"
+#include "backends/native/meta-device-pool.h"
+#include "backends/native/meta-render-device.h"
+
+struct _MetaRenderDeviceClass
+{
+ GObjectClass parent_class;
+
+ EGLDisplay (* create_egl_display) (MetaRenderDevice *render_device,
+ GError **error);
+};
+
+#endif /* META_RENDER_DEVICE_PRIVATE_H */
diff --git a/src/backends/native/meta-render-device-surfaceless.c
b/src/backends/native/meta-render-device-surfaceless.c
new file mode 100644
index 0000000000..fbeea3a7c9
--- /dev/null
+++ b/src/backends/native/meta-render-device-surfaceless.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2020-2021 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.
+ *
+ */
+
+#include "config.h"
+
+#include "backends/native/meta-render-device-surfaceless.h"
+
+#include "backends/meta-backend-private.h"
+#include "backends/meta-egl.h"
+
+struct _MetaRenderDeviceSurfaceless
+{
+ MetaRenderDevice parent;
+};
+
+G_DEFINE_TYPE (MetaRenderDeviceSurfaceless, meta_render_device_surfaceless,
+ META_TYPE_RENDER_DEVICE)
+
+static EGLDisplay
+meta_render_device_surfaceless_create_egl_display (MetaRenderDevice *render_device,
+ GError **error)
+{
+ MetaBackend *backend = meta_render_device_get_backend (render_device);
+ MetaEgl *egl = meta_backend_get_egl (backend);
+ EGLDisplay egl_display;
+
+ if (!meta_egl_has_extensions (egl, EGL_NO_DISPLAY, NULL,
+ "EGL_MESA_platform_surfaceless",
+ NULL))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Missing EGL platform required for surfaceless context: "
+ "EGL_MESA_platform_surfaceless");
+ return EGL_NO_DISPLAY;
+ }
+
+ egl_display = meta_egl_get_platform_display (egl,
+ EGL_PLATFORM_SURFACELESS_MESA,
+ EGL_DEFAULT_DISPLAY,
+ NULL, error);
+ if (egl_display == EGL_NO_DISPLAY)
+ return EGL_NO_DISPLAY;
+
+ if (!meta_egl_initialize (egl, egl_display, error))
+ {
+ meta_egl_terminate (egl, egl_display, NULL);
+ return EGL_NO_DISPLAY;
+ }
+
+ return egl_display;
+}
+
+static void
+meta_render_device_surfaceless_class_init (MetaRenderDeviceSurfacelessClass *klass)
+{
+ MetaRenderDeviceClass *render_device_class = META_RENDER_DEVICE_CLASS (klass);
+
+ render_device_class->create_egl_display =
+ meta_render_device_surfaceless_create_egl_display;
+}
+
+static void
+meta_render_device_surfaceless_init (MetaRenderDeviceSurfaceless *render_device_surfaceless)
+{
+}
+
+MetaRenderDeviceSurfaceless *
+meta_render_device_surfaceless_new (MetaBackend *backend,
+ GError **error)
+{
+ return g_initable_new (META_TYPE_RENDER_DEVICE_SURFACELESS,
+ NULL, error,
+ "backend", backend,
+ NULL);
+}
diff --git a/src/backends/native/meta-render-device-surfaceless.h
b/src/backends/native/meta-render-device-surfaceless.h
new file mode 100644
index 0000000000..b85fc6eeba
--- /dev/null
+++ b/src/backends/native/meta-render-device-surfaceless.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 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_RENDER_DEVICE_SURFACELESS_H
+#define META_RENDER_DEVICE_SURFACELESS_H
+
+#include "backends/native/meta-render-device-private.h"
+
+#define META_TYPE_RENDER_DEVICE_SURFACELESS (meta_render_device_surfaceless_get_type ())
+G_DECLARE_FINAL_TYPE (MetaRenderDeviceSurfaceless, meta_render_device_surfaceless,
+ META, RENDER_DEVICE_SURFACELESS,
+ MetaRenderDevice)
+
+MetaRenderDeviceSurfaceless * meta_render_device_surfaceless_new (MetaBackend *backend,
+ GError **error);
+
+#endif /* META_RENDER_DEVICE_SURFACELESS_H */
diff --git a/src/backends/native/meta-render-device.c b/src/backends/native/meta-render-device.c
new file mode 100644
index 0000000000..d696f7fe03
--- /dev/null
+++ b/src/backends/native/meta-render-device.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2021 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.
+ *
+ */
+
+#include "config.h"
+
+#include "backends/native/meta-render-device-private.h"
+
+#include "backends/meta-backend-private.h"
+#include "backends/meta-egl.h"
+
+enum
+{
+ PROP_0,
+
+ PROP_BACKEND,
+ PROP_DEVICE_FILE,
+
+ N_PROPS
+};
+
+static GParamSpec *obj_props[N_PROPS];
+
+typedef struct _MetaRenderDevicePrivate
+{
+ MetaBackend *backend;
+
+ MetaDeviceFile *device_file;
+
+ EGLDisplay egl_display;
+ EGLConfig egl_config;
+
+ gboolean is_hardware_rendering;
+} MetaRenderDevicePrivate;
+
+static void
+initable_iface_init (GInitableIface *initable_iface);
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaRenderDevice, meta_render_device,
+ G_TYPE_OBJECT,
+ G_ADD_PRIVATE (MetaRenderDevice)
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ initable_iface_init))
+
+static EGLDisplay
+meta_render_device_create_egl_display (MetaRenderDevice *render_device,
+ GError **error)
+{
+ MetaRenderDeviceClass *klass = META_RENDER_DEVICE_GET_CLASS (render_device);
+
+ return klass->create_egl_display (render_device, error);
+}
+
+static void
+detect_hardware_rendering (MetaRenderDevice *render_device)
+{
+ MetaRenderDevicePrivate *priv =
+ meta_render_device_get_instance_private (render_device);
+ MetaEgl *egl = meta_backend_get_egl (priv->backend);
+ g_autoptr (GError) error = NULL;
+ EGLint *attributes;
+ EGLContext egl_context;
+ const char *renderer_str;
+
+ attributes = (EGLint[]) {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+ egl_context = meta_egl_create_context (egl,
+ priv->egl_display,
+ EGL_NO_CONFIG_KHR,
+ EGL_NO_CONTEXT,
+ attributes,
+ &error);
+ if (egl_context == EGL_NO_CONTEXT)
+ {
+ meta_topic (META_DEBUG_RENDER, "Failed to create EGLContext for %s: %s",
+ meta_device_file_get_path (priv->device_file),
+ error->message);
+ return;
+ }
+
+ if (!meta_egl_make_current (egl,
+ priv->egl_display,
+ EGL_NO_SURFACE,
+ EGL_NO_SURFACE,
+ egl_context,
+ &error))
+ {
+ g_warning ("Failed to detect hardware rendering: eglMakeCurrent(): %s",
+ error->message);
+ goto out_has_context;
+ }
+
+ renderer_str = (const char *) glGetString (GL_RENDERER);
+ if (g_str_has_prefix (renderer_str, "llvmpipe") ||
+ g_str_has_prefix (renderer_str, "softpipe") ||
+ g_str_has_prefix (renderer_str, "swrast"))
+ goto out_has_context;
+
+ priv->is_hardware_rendering = TRUE;
+
+out_has_context:
+ meta_egl_destroy_context (egl, priv->egl_display, egl_context, NULL);
+}
+
+static void
+init_egl (MetaRenderDevice *render_device)
+{
+ MetaRenderDevicePrivate *priv =
+ meta_render_device_get_instance_private (render_device);
+ MetaEgl *egl = meta_backend_get_egl (priv->backend);
+ g_autoptr (GError) error = NULL;
+ EGLDisplay egl_display;
+
+ meta_egl_bind_api (egl, EGL_OPENGL_ES_API, NULL);
+
+ egl_display = meta_render_device_create_egl_display (render_device, &error);
+ if (egl_display == EGL_NO_DISPLAY)
+ {
+ meta_topic (META_DEBUG_RENDER, "Failed to create EGLDisplay for %s: %s",
+ meta_device_file_get_path (priv->device_file),
+ error->message);
+ return;
+ }
+
+ priv->egl_display = egl_display;
+ detect_hardware_rendering (render_device);
+}
+
+static gboolean
+meta_render_device_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ MetaRenderDevice *render_device = META_RENDER_DEVICE (initable);
+
+ init_egl (render_device);
+
+ return TRUE;
+}
+
+static void
+initable_iface_init (GInitableIface *initable_iface)
+{
+ initable_iface->init = meta_render_device_initable_init;
+}
+
+static void
+meta_render_device_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MetaRenderDevice *render_device = META_RENDER_DEVICE (object);
+ MetaRenderDevicePrivate *priv =
+ meta_render_device_get_instance_private (render_device);
+
+ switch (prop_id)
+ {
+ case PROP_BACKEND:
+ g_value_set_object (value, priv->backend);
+ break;
+ case PROP_DEVICE_FILE:
+ g_value_set_pointer (value, priv->device_file);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+meta_render_device_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MetaRenderDevice *render_device = META_RENDER_DEVICE (object);
+ MetaRenderDevicePrivate *priv =
+ meta_render_device_get_instance_private (render_device);
+
+ switch (prop_id)
+ {
+ case PROP_BACKEND:
+ priv->backend = g_value_get_object (value);
+ break;
+ case PROP_DEVICE_FILE:
+ priv->device_file = g_value_get_pointer (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+meta_render_device_dispose (GObject *object)
+{
+ MetaRenderDevice *render_device = META_RENDER_DEVICE (object);
+ MetaRenderDevicePrivate *priv =
+ meta_render_device_get_instance_private (render_device);
+ MetaEgl *egl = meta_backend_get_egl (priv->backend);
+
+ if (priv->egl_display != EGL_NO_DISPLAY)
+ {
+ meta_egl_terminate (egl, priv->egl_display, NULL);
+ priv->egl_display = EGL_NO_DISPLAY;
+ }
+
+ G_OBJECT_CLASS (meta_render_device_parent_class)->dispose (object);
+}
+
+static void
+meta_render_device_finalize (GObject *object)
+{
+ MetaRenderDevice *render_device = META_RENDER_DEVICE (object);
+ MetaRenderDevicePrivate *priv =
+ meta_render_device_get_instance_private (render_device);
+
+ g_clear_pointer (&priv->device_file, meta_device_file_release);
+
+ G_OBJECT_CLASS (meta_render_device_parent_class)->finalize (object);
+}
+
+static void
+meta_render_device_constructed (GObject *object)
+{
+ MetaRenderDevice *render_device = META_RENDER_DEVICE (object);
+ MetaRenderDevicePrivate *priv =
+ meta_render_device_get_instance_private (render_device);
+
+ if (priv->device_file)
+ meta_device_file_acquire (priv->device_file);
+
+ G_OBJECT_CLASS (meta_render_device_parent_class)->constructed (object);
+}
+
+static void
+meta_render_device_class_init (MetaRenderDeviceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = meta_render_device_get_property;
+ object_class->set_property = meta_render_device_set_property;
+ object_class->constructed = meta_render_device_constructed;
+ object_class->dispose = meta_render_device_dispose;
+ object_class->finalize = meta_render_device_finalize;
+
+ obj_props[PROP_BACKEND] =
+ g_param_spec_object ("backend",
+ "backend",
+ "MetaBackend",
+ META_TYPE_BACKEND,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+ obj_props[PROP_DEVICE_FILE] =
+ g_param_spec_pointer ("device-file",
+ "device file",
+ "MetaDeviceFile",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+ g_object_class_install_properties (object_class, N_PROPS, obj_props);
+}
+
+static void
+meta_render_device_init (MetaRenderDevice *render_device)
+{
+ MetaRenderDevicePrivate *priv =
+ meta_render_device_get_instance_private (render_device);
+
+ priv->egl_display = EGL_NO_DISPLAY;
+ priv->egl_config = EGL_NO_CONFIG_KHR;
+}
+
+MetaBackend *
+meta_render_device_get_backend (MetaRenderDevice *render_device)
+{
+ MetaRenderDevicePrivate *priv =
+ meta_render_device_get_instance_private (render_device);
+
+ return priv->backend;
+}
+
+MetaDeviceFile *
+meta_render_device_get_device_file (MetaRenderDevice *render_device)
+{
+ MetaRenderDevicePrivate *priv =
+ meta_render_device_get_instance_private (render_device);
+
+ return priv->device_file;
+}
+
+EGLDisplay
+meta_render_device_get_egl_display (MetaRenderDevice *render_device)
+{
+ MetaRenderDevicePrivate *priv =
+ meta_render_device_get_instance_private (render_device);
+
+ return priv->egl_display;
+}
+
+gboolean
+meta_render_device_is_hardware_accelerated (MetaRenderDevice *render_device)
+{
+ MetaRenderDevicePrivate *priv =
+ meta_render_device_get_instance_private (render_device);
+
+ return priv->is_hardware_rendering;
+}
+
+const char *
+meta_render_device_get_name (MetaRenderDevice *render_device)
+{
+ MetaRenderDevicePrivate *priv =
+ meta_render_device_get_instance_private (render_device);
+
+ if (priv->device_file)
+ return meta_device_file_get_path (priv->device_file);
+ else
+ return "(device-less)";
+}
diff --git a/src/backends/native/meta-render-device.h b/src/backends/native/meta-render-device.h
new file mode 100644
index 0000000000..b1b71028e9
--- /dev/null
+++ b/src/backends/native/meta-render-device.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 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_RENDER_DEVICE_H
+#define META_RENDER_DEVICE_H
+
+#include <glib-object.h>
+
+#include "backends/meta-backend-types.h"
+
+#define META_TYPE_RENDER_DEVICE (meta_render_device_get_type ())
+G_DECLARE_DERIVABLE_TYPE (MetaRenderDevice, meta_render_device,
+ META, RENDER_DEVICE,
+ GObject)
+
+MetaBackend * meta_render_device_get_backend (MetaRenderDevice *render_device);
+
+EGLDisplay meta_render_device_get_egl_display (MetaRenderDevice *render_device);
+
+const char * meta_render_device_get_name (MetaRenderDevice *render_device);
+
+gboolean meta_render_device_is_hardware_accelerated (MetaRenderDevice *render_device);
+
+MetaDeviceFile * meta_render_device_get_device_file (MetaRenderDevice *render_device);
+
+#endif /* META_RENDER_DEVICE_H */
diff --git a/src/meson.build b/src/meson.build
index f3aebfb285..f4ecba3b31 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -460,6 +460,13 @@ mutter_sources = [
'x11/xprops.h',
]
+if have_egl_device
+ mutter_sources += [
+ 'backends/native/meta-render-device-egl-stream.c',
+ 'backends/native/meta-render-device-egl-stream.h',
+ ]
+endif
+
if have_egl
mutter_sources += [
'backends/meta-egl.c',
@@ -748,6 +755,13 @@ if have_native_backend
'backends/native/meta-onscreen-native.h',
'backends/native/meta-pointer-constraint-native.c',
'backends/native/meta-pointer-constraint-native.h',
+ 'backends/native/meta-render-device-gbm.c',
+ 'backends/native/meta-render-device-gbm.h',
+ 'backends/native/meta-render-device-private.h',
+ 'backends/native/meta-render-device-surfaceless.c',
+ 'backends/native/meta-render-device-surfaceless.h',
+ 'backends/native/meta-render-device.c',
+ 'backends/native/meta-render-device.h',
'backends/native/meta-renderer-native-gles3.c',
'backends/native/meta-renderer-native-gles3.h',
'backends/native/meta-renderer-native-private.h',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]