From 58c3734d78e95e58c43216d9a3668ebcb0238139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 17 Aug 2022 12:11:29 +0200 Subject: [PATCH] backend/native: Prepare render devices earlier than KMS The type of render device used for a specific GPU affects the mode setting backend that can be used, more specifically, when the render device is an EGLStream based one, atomic mode setting isn't possible, as page flipping is done via EGL, not via atomic mode setting commits. Preparing the render devices before KMS devices means can make a more informed decision whether to deny-list atomic mode setting for when a certain GPU uses a EGLStream based render device instance. This also means we need to translate mode setting devices to render node devices when creating the render device itself, as doing it later when creating the mode setting device is already too late. Part-of: --- src/backends/meta-backend.c | 9 +- .../native/meta-backend-native-private.h | 3 + .../native/meta-backend-native-types.h | 1 + src/backends/native/meta-backend-native.c | 188 ++++++++++++++++-- .../native/meta-kms-impl-device-dummy.c | 25 +-- src/backends/native/meta-renderer-native.c | 132 +++--------- 6 files changed, 207 insertions(+), 151 deletions(-) diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c index 509dd2aad..5cf09c61d 100644 --- a/src/backends/meta-backend.c +++ b/src/backends/meta-backend.c @@ -821,6 +821,10 @@ meta_backend_constructed (GObject *object) NULL); } +#ifdef HAVE_EGL + priv->egl = g_object_new (META_TYPE_EGL, NULL); +#endif + G_OBJECT_CLASS (meta_backend_parent_class)->constructed (object); } @@ -1199,11 +1203,6 @@ meta_backend_initable_init (GInitable *initable, MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); priv->settings = meta_settings_new (backend); - -#ifdef HAVE_EGL - priv->egl = g_object_new (META_TYPE_EGL, NULL); -#endif - priv->orientation_manager = g_object_new (META_TYPE_ORIENTATION_MANAGER, NULL); priv->monitor_manager = meta_backend_create_monitor_manager (backend, error); diff --git a/src/backends/native/meta-backend-native-private.h b/src/backends/native/meta-backend-native-private.h index 904b052da..2a945f4b8 100644 --- a/src/backends/native/meta-backend-native-private.h +++ b/src/backends/native/meta-backend-native-private.h @@ -33,4 +33,7 @@ MetaBarrierManagerNative *meta_backend_native_get_barrier_manager (MetaBackendNa META_EXPORT_TEST MetaDevicePool * meta_backend_native_get_device_pool (MetaBackendNative *native); +MetaRenderDevice * meta_backend_native_take_render_device (MetaBackendNative *backend_native, + const char *device_path); + #endif /* META_BACKEND_NATIVE_PRIVATE_H */ diff --git a/src/backends/native/meta-backend-native-types.h b/src/backends/native/meta-backend-native-types.h index c78d44ff8..3d98b3207 100644 --- a/src/backends/native/meta-backend-native-types.h +++ b/src/backends/native/meta-backend-native-types.h @@ -32,6 +32,7 @@ typedef struct _MetaCrtcModeVirtual MetaCrtcModeVirtual; typedef struct _MetaDevicePool MetaDevicePool; typedef struct _MetaDeviceFile MetaDeviceFile; typedef struct _MetaDrmBuffer MetaDrmBuffer; +typedef struct _MetaRenderDevice MetaRenderDevice; typedef enum _MetaSeatNativeFlag { diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c index 86eccec2b..9b0220cbd 100644 --- a/src/backends/native/meta-backend-native.c +++ b/src/backends/native/meta-backend-native.c @@ -55,6 +55,7 @@ #include "backends/native/meta-kms-device.h" #include "backends/native/meta-launcher.h" #include "backends/native/meta-monitor-manager-native.h" +#include "backends/native/meta-render-device-gbm.h" #include "backends/native/meta-renderer-native.h" #include "backends/native/meta-seat-native.h" #include "backends/native/meta-stage-native.h" @@ -67,6 +68,10 @@ #include "backends/meta-screen-cast.h" #endif +#ifdef HAVE_EGL_DEVICE +#include "backends/native/meta-render-device-egl-stream.h" +#endif + #include "meta-private-enum-types.h" enum @@ -89,6 +94,8 @@ struct _MetaBackendNative MetaUdev *udev; MetaKms *kms; + GHashTable *startup_render_devices; + MetaBackendNativeMode mode; }; @@ -111,6 +118,7 @@ meta_backend_native_dispose (GObject *object) G_OBJECT_CLASS (meta_backend_native_parent_class)->dispose (object); + g_clear_pointer (&native->startup_render_devices, g_hash_table_unref); g_clear_object (&native->kms); g_clear_object (&native->udev); g_clear_object (&native->device_pool); @@ -206,6 +214,7 @@ update_viewports (MetaBackend *backend) static void meta_backend_native_post_init (MetaBackend *backend) { + MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); MetaSettings *settings = meta_backend_get_settings (backend); META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend); @@ -246,9 +255,12 @@ meta_backend_native_post_init (MetaBackend *backend) } #ifdef HAVE_REMOTE_DESKTOP - maybe_disable_screen_cast_dma_bufs (META_BACKEND_NATIVE (backend)); + maybe_disable_screen_cast_dma_bufs (backend_native); #endif + g_clear_pointer (&backend_native->startup_render_devices, + g_hash_table_unref); + update_viewports (backend); } @@ -450,14 +462,129 @@ meta_backend_native_update_screen_size (MetaBackend *backend, clutter_actor_set_size (stage, width, height); } -static MetaGpuKms * -create_gpu_from_udev_device (MetaBackendNative *native, - GUdevDevice *device, - GError **error) +static MetaRenderDevice * +create_render_device (MetaBackendNative *backend_native, + const char *device_path, + GError **error) +{ + MetaBackend *backend = META_BACKEND (backend_native); + MetaDevicePool *device_pool = + meta_backend_native_get_device_pool (backend_native); + g_autoptr (MetaDeviceFile) device_file = NULL; + MetaDeviceFileFlags device_file_flags; + g_autoptr (MetaRenderDeviceGbm) render_device_gbm = NULL; + g_autoptr (GError) gbm_error = NULL; +#ifdef HAVE_EGL_DEVICE + g_autoptr (MetaRenderDeviceEglStream) render_device_egl_stream = NULL; + g_autoptr (GError) egl_stream_error = NULL; +#endif + + if (meta_backend_is_headless (backend)) + device_file_flags = META_DEVICE_FILE_FLAG_NONE; + else + device_file_flags = META_DEVICE_FILE_FLAG_TAKE_CONTROL; + + device_file = meta_device_pool_open (device_pool, + device_path, + device_file_flags, + error); + if (!device_file) + return NULL; + + if (meta_backend_is_headless (backend)) + { + int fd; + g_autofree char *render_node_path = NULL; + g_autoptr (MetaDeviceFile) render_node_device_file = NULL; + + fd = meta_device_file_get_fd (device_file); + render_node_path = drmGetRenderDeviceNameFromFd (fd); + + if (!render_node_path) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Couldn't find render node device for '%s'", + meta_device_file_get_path (device_file)); + return NULL; + } + + meta_topic (META_DEBUG_KMS, "Found render node '%s' from '%s'", + render_node_path, + meta_device_file_get_path (device_file)); + + render_node_device_file = + meta_device_pool_open (device_pool, render_node_path, + META_DEVICE_FILE_FLAG_NONE, + error); + if (!render_node_device_file) + return NULL; + + g_clear_pointer (&device_file, meta_device_file_release); + device_file = g_steal_pointer (&render_node_device_file); + } + +#ifdef HAVE_EGL_DEVICE + if (g_strcmp0 (getenv ("MUTTER_DEBUG_FORCE_EGL_STREAM"), "1") != 0) +#endif + { + render_device_gbm = meta_render_device_gbm_new (backend, device_file, + &gbm_error); + if (render_device_gbm) + { + MetaRenderDevice *render_device = + META_RENDER_DEVICE (render_device_gbm); + + if (meta_render_device_is_hardware_accelerated (render_device)) + return META_RENDER_DEVICE (g_steal_pointer (&render_device_gbm)); + } + } +#ifdef HAVE_EGL_DEVICE + else + { + g_set_error (&gbm_error, G_IO_ERROR, G_IO_ERROR_FAILED, + "GBM backend was disabled using env var"); + } +#endif + +#ifdef HAVE_EGL_DEVICE + render_device_egl_stream = + meta_render_device_egl_stream_new (backend, + device_file, + &egl_stream_error); + if (render_device_egl_stream) + return META_RENDER_DEVICE (g_steal_pointer (&render_device_egl_stream)); +#endif + + if (render_device_gbm) + return META_RENDER_DEVICE (g_steal_pointer (&render_device_gbm)); + + g_set_error (error, G_IO_ERROR, + G_IO_ERROR_FAILED, + "Failed to initialize render device for %s: " + "%s" +#ifdef HAVE_EGL_DEVICE + ", %s" +#endif + , device_path + , gbm_error->message +#ifdef HAVE_EGL_DEVICE + , egl_stream_error->message +#endif + ); + + return NULL; +} + +static gboolean +add_drm_device (MetaBackendNative *backend_native, + GUdevDevice *device, + GError **error) { MetaKmsDeviceFlag flags = META_KMS_DEVICE_FLAG_NONE; const char *device_path; + g_autoptr (MetaRenderDevice) render_device = NULL; MetaKmsDevice *kms_device; + MetaGpuKms *gpu_kms; if (meta_is_udev_device_platform_device (device)) flags |= META_KMS_DEVICE_FLAG_PLATFORM_DEVICE; @@ -473,12 +600,22 @@ create_gpu_from_udev_device (MetaBackendNative *native, device_path = g_udev_device_get_device_file (device); - kms_device = meta_kms_create_device (native->kms, device_path, flags, + render_device = create_render_device (backend_native, device_path, error); + if (!render_device) + return FALSE; + + kms_device = meta_kms_create_device (backend_native->kms, device_path, flags, error); if (!kms_device) - return NULL; + return FALSE; - return meta_gpu_kms_new (native, kms_device, error); + g_hash_table_insert (backend_native->startup_render_devices, + g_strdup (device_path), + g_steal_pointer (&render_device)); + + gpu_kms = meta_gpu_kms_new (backend_native, kms_device, error); + meta_backend_add_gpu (META_BACKEND (backend_native), META_GPU (gpu_kms)); + return TRUE; } static gboolean @@ -504,7 +641,6 @@ on_udev_device_added (MetaUdev *udev, MetaBackend *backend = META_BACKEND (native); g_autoptr (GError) error = NULL; const char *device_path; - MetaGpuKms *new_gpu_kms; GList *gpus, *l; if (!meta_udev_is_drm_device (udev, device)) @@ -531,8 +667,7 @@ on_udev_device_added (MetaUdev *udev, return; } - new_gpu_kms = create_gpu_from_udev_device (native, device, &error); - if (!new_gpu_kms) + if (!add_drm_device (native, device, &error)) { if (meta_backend_is_headless (backend) && g_error_matches (error, G_IO_ERROR, @@ -547,11 +682,7 @@ on_udev_device_added (MetaUdev *udev, g_warning ("Failed to hotplug secondary gpu '%s': %s", device_path, error->message); } - - return; } - - meta_backend_add_gpu (backend, META_GPU (new_gpu_kms)); } static gboolean @@ -570,7 +701,6 @@ init_gpus (MetaBackendNative *native, for (l = devices; l; l = l->next) { GUdevDevice *device = l->data; - MetaGpuKms *gpu_kms; GError *local_error = NULL; if (should_ignore_device (native, device)) @@ -580,9 +710,7 @@ init_gpus (MetaBackendNative *native, continue; } - gpu_kms = create_gpu_from_udev_device (native, device, &local_error); - - if (!gpu_kms) + if (!add_drm_device (native, device, &local_error)) { if (meta_backend_is_headless (backend) && g_error_matches (local_error, G_IO_ERROR, @@ -603,8 +731,6 @@ init_gpus (MetaBackendNative *native, g_clear_error (&local_error); continue; } - - meta_backend_add_gpu (backend, META_GPU (gpu_kms)); } g_list_free_full (devices, g_object_unref); @@ -753,8 +879,11 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass) } static void -meta_backend_native_init (MetaBackendNative *native) +meta_backend_native_init (MetaBackendNative *backend_native) { + backend_native->startup_render_devices = + g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_object_unref); } MetaLauncher * @@ -860,3 +989,18 @@ void meta_backend_native_resume (MetaBackendNative *native) clutter_seat_ensure_a11y_state (CLUTTER_SEAT (seat)); } + +MetaRenderDevice * +meta_backend_native_take_render_device (MetaBackendNative *backend_native, + const char *device_path) +{ + MetaRenderDevice *render_device; + + if (g_hash_table_steal_extended (backend_native->startup_render_devices, + device_path, + NULL, + (gpointer *) &render_device)) + return render_device; + else + return NULL; +} diff --git a/src/backends/native/meta-kms-impl-device-dummy.c b/src/backends/native/meta-kms-impl-device-dummy.c index 02583bbeb..57fd6de25 100644 --- a/src/backends/native/meta-kms-impl-device-dummy.c +++ b/src/backends/native/meta-kms-impl-device-dummy.c @@ -55,31 +55,8 @@ meta_kms_impl_device_dummy_open_device_file (MetaKmsImplDevice *impl_device, MetaBackend *backend = meta_kms_get_backend (kms); MetaDevicePool *device_pool = meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend)); - g_autoptr (MetaDeviceFile) device_file = NULL; - int fd; - g_autofree char *render_node_path = NULL; - device_file = meta_device_pool_open (device_pool, path, - META_DEVICE_FILE_FLAG_NONE, - error); - if (!device_file) - return NULL; - - fd = meta_device_file_get_fd (device_file); - render_node_path = drmGetRenderDeviceNameFromFd (fd); - if (!render_node_path) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Couldn't find render node device for '%s' (%s)", - meta_kms_impl_device_get_path (impl_device), - meta_kms_impl_device_get_driver_name (impl_device)); - return NULL; - } - - meta_topic (META_DEBUG_KMS, "Found render node '%s' from '%s'", - render_node_path, path); - - return meta_device_pool_open (device_pool, render_node_path, + return meta_device_pool_open (device_pool, path, META_DEVICE_FILE_FLAG_NONE, error); } diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 76169d510..99fbb2bb6 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -1701,24 +1701,16 @@ gpu_kms_is_hardware_rendering (MetaRendererNative *renderer_native, } static MetaRendererNativeGpuData * -create_renderer_gpu_data_gbm (MetaRendererNative *renderer_native, - MetaDeviceFile *device_file, - MetaGpuKms *gpu_kms, - GError **error) +create_renderer_gpu_data_gbm (MetaRendererNative *renderer_native, + MetaRenderDevice *render_device, + MetaGpuKms *gpu_kms) { - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaRenderDeviceGbm *render_device_gbm; MetaRendererNativeGpuData *renderer_gpu_data; - render_device_gbm = meta_render_device_gbm_new (backend, device_file, error); - if (!render_device_gbm) - return NULL; - renderer_gpu_data = meta_create_renderer_native_gpu_data (); renderer_gpu_data->renderer_native = renderer_native; renderer_gpu_data->mode = META_RENDERER_NATIVE_MODE_GBM; - renderer_gpu_data->render_device = META_RENDER_DEVICE (render_device_gbm); + renderer_gpu_data->render_device = render_device; renderer_gpu_data->gpu_kms = gpu_kms; init_secondary_gpu_data (renderer_gpu_data); @@ -1751,26 +1743,15 @@ create_renderer_gpu_data_surfaceless (MetaRendererNative *renderer_native, #ifdef HAVE_EGL_DEVICE static MetaRendererNativeGpuData * create_renderer_gpu_data_egl_device (MetaRendererNative *renderer_native, - MetaDeviceFile *device_file, - MetaGpuKms *gpu_kms, - GError **error) + MetaRenderDevice *render_device, + MetaGpuKms *gpu_kms) { - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaRenderDeviceEglStream *render_device_egl_stream; MetaRendererNativeGpuData *renderer_gpu_data; - render_device_egl_stream = meta_render_device_egl_stream_new (backend, - device_file, - error); - if (!render_device_egl_stream) - return NULL; - renderer_gpu_data = meta_create_renderer_native_gpu_data (); renderer_gpu_data->renderer_native = renderer_native; renderer_gpu_data->mode = META_RENDERER_NATIVE_MODE_EGL_DEVICE; - renderer_gpu_data->render_device = - META_RENDER_DEVICE (render_device_egl_stream); + renderer_gpu_data->render_device = render_device; renderer_gpu_data->gpu_kms = gpu_kms; return renderer_gpu_data; @@ -1784,91 +1765,42 @@ meta_renderer_native_create_renderer_gpu_data (MetaRendererNative *renderer_nat { MetaRenderer *renderer = META_RENDERER (renderer_native); MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaDevicePool *device_pool = - meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend)); - MetaRendererNativeGpuData *gbm_renderer_gpu_data = NULL; - MetaDeviceFileFlags device_file_flags = META_DEVICE_FILE_FLAG_NONE; - g_autoptr (MetaDeviceFile) device_file = NULL; - GError *gbm_error = NULL; -#ifdef HAVE_EGL_DEVICE - MetaRendererNativeGpuData *egl_stream_renderer_gpu_data; - GError *egl_device_error = NULL; -#endif + MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); + const char *device_path; + MetaRenderDevice *render_device; if (!gpu_kms) return create_renderer_gpu_data_surfaceless (renderer_native, error); - if (!(meta_kms_device_get_flags (meta_gpu_kms_get_kms_device (gpu_kms)) & - META_KMS_DEVICE_FLAG_NO_MODE_SETTING)) - device_file_flags = META_DEVICE_FILE_FLAG_TAKE_CONTROL; - - device_file = meta_device_pool_open (device_pool, - meta_gpu_kms_get_file_path (gpu_kms), - device_file_flags, - error); - if (!device_file) - return NULL; - -#ifdef HAVE_EGL_DEVICE - if (g_strcmp0 (getenv ("MUTTER_DEBUG_FORCE_EGL_STREAM"), "1") != 0) -#endif + device_path = meta_gpu_kms_get_file_path (gpu_kms); + render_device = meta_backend_native_take_render_device (backend_native, + device_path); + if (!render_device) { - gbm_renderer_gpu_data = create_renderer_gpu_data_gbm (renderer_native, - device_file, - gpu_kms, - &gbm_error); - if (gbm_renderer_gpu_data) - { - MetaRenderDevice *render_device = gbm_renderer_gpu_data->render_device; + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "No render device found for %s", device_path); + return NULL; + } - if (meta_render_device_is_hardware_accelerated (render_device)) - return gbm_renderer_gpu_data; - } + if (META_IS_RENDER_DEVICE_GBM (render_device)) + { + return create_renderer_gpu_data_gbm (renderer_native, + render_device, + gpu_kms); } #ifdef HAVE_EGL_DEVICE + else if (META_IS_RENDER_DEVICE_EGL_STREAM (render_device)) + { + return create_renderer_gpu_data_egl_device (renderer_native, + render_device, + gpu_kms); + } +#endif else { - g_set_error (&gbm_error, G_IO_ERROR, G_IO_ERROR_FAILED, - "GBM backend was disabled using env var"); + g_assert_not_reached (); + return NULL; } -#endif - -#ifdef HAVE_EGL_DEVICE - egl_stream_renderer_gpu_data = - create_renderer_gpu_data_egl_device (renderer_native, - device_file, - gpu_kms, - &egl_device_error); - if (egl_stream_renderer_gpu_data) - { - g_clear_pointer (&gbm_renderer_gpu_data, - meta_renderer_native_gpu_data_free); - return egl_stream_renderer_gpu_data; - } -#endif - - if (gbm_renderer_gpu_data) - return gbm_renderer_gpu_data; - - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to initialize renderer: " - "%s" -#ifdef HAVE_EGL_DEVICE - ", %s" -#endif - , gbm_error->message -#ifdef HAVE_EGL_DEVICE - , egl_device_error->message -#endif - ); - - g_error_free (gbm_error); -#ifdef HAVE_EGL_DEVICE - g_error_free (egl_device_error); -#endif - - return NULL; } static const char *