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 *