diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c index d75ac6c5..1f41e1b2 100644 --- a/src/libply-splash-core/ply-device-manager.c +++ b/src/libply-splash-core/ply-device-manager.c @@ -339,11 +339,15 @@ remove_input_device_from_renderers (ply_device_manager_t *manager, ply_hashtable_foreach (manager->renderers, (ply_hashtable_foreach_func_t *) on_each_input_device_remove_from_renderer, input_device); } +static bool +syspath_is_simpledrm (const char *syspath) +{ + return ply_string_has_suffix (syspath, "simple-framebuffer.0/drm/card0"); +} + static bool verify_drm_device (struct udev_device *device) { - const char *id_path; - /* * Simple-framebuffer devices driven by simpledrm lack information * like panel-rotation info and physical size, causing the splash @@ -352,8 +356,7 @@ verify_drm_device (struct udev_device *device) * To avoid this treat simpledrm devices as fbdev devices and only * use them after the timeout. */ - id_path = udev_device_get_property_value (device, "ID_PATH"); - if (!ply_string_has_prefix (id_path, "platform-simple-framebuffer")) + if (!syspath_is_simpledrm (udev_device_get_syspath (device))) return true; /* Not a SimpleDRM device */ /* @@ -377,7 +380,7 @@ static bool create_devices_for_udev_device (ply_device_manager_t *manager, struct udev_device *device) { - const char *device_path, *device_sysname; + const char *device_path, *device_sysname, *device_syspath; bool created = false; bool force_fb = false; @@ -386,6 +389,7 @@ create_devices_for_udev_device (ply_device_manager_t *manager, device_path = udev_device_get_devnode (device); device_sysname = udev_device_get_sysname (device); + device_syspath = udev_device_get_syspath (device); if (device_path != NULL) { const char *subsystem; @@ -399,8 +403,15 @@ create_devices_for_udev_device (ply_device_manager_t *manager, ply_trace ("ignoring since we only handle SimpleDRM devices after timeout"); return false; } + if (ply_string_has_prefix (device_path, "/dev/dri/render")) { + ply_trace ("ignoring since it is a render node"); + return false; + } ply_trace ("found DRM device %s", device_path); - renderer_type = PLY_RENDERER_TYPE_DRM; + if (syspath_is_simpledrm (device_syspath)) + renderer_type = PLY_RENDERER_TYPE_SIMPLEDRM; + else + renderer_type = PLY_RENDERER_TYPE_DRM; } else if (strcmp (subsystem, SUBSYSTEM_FRAME_BUFFER) == 0) { ply_trace ("found frame buffer device %s", device_path); if (!fb_device_has_drm_device (manager, device)) @@ -430,20 +441,13 @@ create_devices_for_udev_device (ply_device_manager_t *manager, } if (renderer_type != PLY_RENDERER_TYPE_NONE) { - ply_terminal_t *terminal = NULL; - - if (!manager->local_console_managed && - manager->local_console_terminal != NULL && - ply_terminal_is_vt (manager->local_console_terminal)) { - terminal = manager->local_console_terminal; - } - created = create_devices_for_terminal_and_renderer_type (manager, device_path, - terminal, + NULL, renderer_type); if (created) { - if (renderer_type == PLY_RENDERER_TYPE_DRM) + if (renderer_type == PLY_RENDERER_TYPE_DRM || + renderer_type == PLY_RENDERER_TYPE_SIMPLEDRM) manager->found_drm_device = 1; if (renderer_type == PLY_RENDERER_TYPE_FRAME_BUFFER) manager->found_fb_device = 1; @@ -454,23 +458,22 @@ create_devices_for_udev_device (ply_device_manager_t *manager, return created; } -static bool +static void create_devices_for_subsystem (ply_device_manager_t *manager, const char *subsystem) { struct udev_enumerate *matches; struct udev_list_entry *entry; - bool found_device = false; if (strcmp (subsystem, SUBSYSTEM_INPUT) == 0) { if (ply_kernel_command_line_has_argument ("plymouth.use-legacy-input")) { ply_trace ("Not creating devices for subsystem " SUBSYSTEM_INPUT " because plymouth.use-legacy-input on command line"); - return false; + return; } if (manager->xkb_keymap == NULL) { ply_trace ("Not creating devices for subsystem " SUBSYSTEM_INPUT " because there is no configure XKB layout"); - return false; + return; } } @@ -486,6 +489,7 @@ create_devices_for_subsystem (ply_device_manager_t *manager, udev_list_entry_foreach (entry, udev_enumerate_get_list_entry (matches)){ struct udev_device *device = NULL; const char *path, *node; + int initialized; path = udev_list_entry_get_name (entry); @@ -498,15 +502,16 @@ create_devices_for_subsystem (ply_device_manager_t *manager, device = udev_device_new_from_syspath (manager->udev_context, path); - /* if device isn't fully initialized, we'll get an add event later - */ - if (udev_device_get_is_initialized (device)) { - ply_trace ("device is initialized"); + /* If device isn't fully initialized, we'll get an add event later */ + initialized = udev_device_get_is_initialized (device); + /* Simpledrm can be handled uninitialized and this shows the splash sooner */ + if (initialized || syspath_is_simpledrm (path)) { + ply_trace ("device is initialized %d", initialized); node = udev_device_get_devnode (device); if (node != NULL) { ply_trace ("found node %s", node); - found_device = create_devices_for_udev_device (manager, device); + create_devices_for_udev_device (manager, device); } } else { ply_trace ("it's not initialized"); @@ -516,8 +521,6 @@ create_devices_for_subsystem (ply_device_manager_t *manager, } udev_enumerate_unref (matches); - - return found_device; } static void @@ -1076,6 +1079,18 @@ create_text_displays_for_terminal (ply_device_manager_t *manager, manager->text_display_added_handler (manager->event_handler_data, display); } +static void +free_simpledrm_renderer (char *device_path, + ply_renderer_t *renderer, + ply_device_manager_t *manager) +{ + if (ply_renderer_get_type (renderer) != PLY_RENDERER_TYPE_SIMPLEDRM) + return; + + ply_trace ("removing simpledrm renderer %s", device_path); + free_devices_from_device_path (manager, device_path, true); +} + static bool create_devices_for_terminal_and_renderer_type (ply_device_manager_t *manager, const char *device_path, @@ -1093,6 +1108,23 @@ create_devices_for_terminal_and_renderer_type (ply_device_manager_t *manager, return true; } + /* + * simpledrm udev remove events may arrive after normal drm device add + * events, leaving the local_console unmanaged breaking legacy input. + * Remove simpledrm renderers before adding drm renderers to avoid this. + */ + if (renderer_type == PLY_RENDERER_TYPE_DRM) { + ply_hashtable_foreach (manager->renderers, + (ply_hashtable_foreach_func_t *) + free_simpledrm_renderer, + manager); + } + + if (!terminal && !manager->local_console_managed && + manager->local_console_terminal != NULL && + ply_terminal_is_vt (manager->local_console_terminal)) + terminal = manager->local_console_terminal; + ply_trace ("creating devices for %s (renderer type: %u) (terminal: %s)", device_path ? : "", renderer_type, terminal ? ply_terminal_get_name (terminal) : "none"); diff --git a/src/libply-splash-core/ply-renderer.c b/src/libply-splash-core/ply-renderer.c index 40a2c813..61c59ccc 100644 --- a/src/libply-splash-core/ply-renderer.c +++ b/src/libply-splash-core/ply-renderer.c @@ -102,6 +102,12 @@ ply_renderer_get_device_name (ply_renderer_t *renderer) return renderer->device_name; } +ply_renderer_type_t +ply_renderer_get_type (ply_renderer_t *renderer) +{ + return renderer->type; +} + static bool ply_renderer_load_plugin (ply_renderer_t *renderer, const char *module_path) @@ -269,6 +275,7 @@ ply_renderer_open (ply_renderer_t *renderer) { { PLY_RENDERER_TYPE_X11, PLYMOUTH_PLUGIN_PATH "renderers/x11.so" }, { PLY_RENDERER_TYPE_DRM, PLYMOUTH_PLUGIN_PATH "renderers/drm.so" }, + { PLY_RENDERER_TYPE_SIMPLEDRM, PLYMOUTH_PLUGIN_PATH "renderers/drm.so" }, { PLY_RENDERER_TYPE_FRAME_BUFFER, PLYMOUTH_PLUGIN_PATH "renderers/frame-buffer.so" }, { PLY_RENDERER_TYPE_NONE, NULL } }; diff --git a/src/libply-splash-core/ply-renderer.h b/src/libply-splash-core/ply-renderer.h index 5fbf819d..cfd4f2dd 100644 --- a/src/libply-splash-core/ply-renderer.h +++ b/src/libply-splash-core/ply-renderer.h @@ -41,6 +41,7 @@ typedef enum PLY_RENDERER_TYPE_NONE = -1, PLY_RENDERER_TYPE_AUTO, PLY_RENDERER_TYPE_DRM, + PLY_RENDERER_TYPE_SIMPLEDRM, PLY_RENDERER_TYPE_FRAME_BUFFER, PLY_RENDERER_TYPE_X11 } ply_renderer_type_t; @@ -62,6 +63,7 @@ void ply_renderer_activate (ply_renderer_t *renderer); void ply_renderer_deactivate (ply_renderer_t *renderer); bool ply_renderer_is_active (ply_renderer_t *renderer); const char *ply_renderer_get_device_name (ply_renderer_t *renderer); +ply_renderer_type_t ply_renderer_get_type (ply_renderer_t *renderer); ply_list_t *ply_renderer_get_heads (ply_renderer_t *renderer); ply_pixel_buffer_t *ply_renderer_get_buffer_for_head (ply_renderer_t *renderer, ply_renderer_head_t *head); diff --git a/src/libply/ply-utils.c b/src/libply/ply-utils.c index 0e317b67..d6d127f1 100644 --- a/src/libply/ply-utils.c +++ b/src/libply/ply-utils.c @@ -473,6 +473,24 @@ ply_string_has_prefix (const char *str, return strncmp (str, prefix, strlen (prefix)) == 0; } +bool +ply_string_has_suffix (const char *str, + const char *suffix) +{ + size_t str_len, suffix_len; + + if (str == NULL || suffix == NULL) + return false; + + str_len = strlen (str); + suffix_len = strlen (suffix); + + if (suffix_len > str_len) + return false; + + return strcmp (str + (str_len - suffix_len), suffix) == 0; +} + double ply_get_timestamp (void) { diff --git a/src/libply/ply-utils.h b/src/libply/ply-utils.h index 7cbbb2f4..86d66384 100644 --- a/src/libply/ply-utils.h +++ b/src/libply/ply-utils.h @@ -109,6 +109,8 @@ char **ply_copy_string_array (const char *const *array); void ply_free_string_array (char **array); bool ply_string_has_prefix (const char *str, const char *prefix); +bool ply_string_has_suffix (const char *str, + const char *suffix); double ply_get_timestamp (void); void ply_save_errno (void);