diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c index bbfbd50d..7406d5f5 100644 --- a/src/libply-splash-core/ply-device-manager.c +++ b/src/libply-splash-core/ply-device-manager.c @@ -345,35 +345,15 @@ syspath_is_simpledrm (const char *syspath) return ply_string_has_suffix (syspath, "simple-framebuffer.0/drm/card0"); } +/* Only use SimpleDRM devices if requested to do so */ static bool -verify_drm_device (struct udev_device *device) +verify_drm_device (ply_device_manager_t *manager, + struct udev_device *device) { - /* - * Simple-framebuffer devices driven by simpledrm lack information - * like panel-rotation info and physical size, causing the splash - * to briefly render on its side / without HiDPI scaling, switching - * to the correct rendering when the native driver loads. - * To avoid this treat simpledrm devices as fbdev devices and only - * use them after the timeout. - */ if (!syspath_is_simpledrm (udev_device_get_syspath (device))) return true; /* Not a SimpleDRM device */ - /* - * With nomodeset, no native drivers will load, so SimpleDRM devices - * should be used immediately. - */ - if (ply_kernel_command_line_has_argument ("nomodeset")) - return true; - - /* - * Some firmwares leave the panel black at boot. Allow enabling SimpleDRM - * use from the cmdline to show something to the user ASAP. - */ - if (ply_kernel_command_line_has_argument ("plymouth.use-simpledrm")) - return true; - - return false; + return manager->flags & PLY_DEVICE_MANAGER_FLAGS_USE_SIMPLEDRM; } static bool @@ -399,7 +379,8 @@ create_devices_for_udev_device (ply_device_manager_t *manager, ply_trace ("device subsystem is %s", subsystem); if (strcmp (subsystem, SUBSYSTEM_DRM) == 0) { - if (!manager->device_timeout_elapsed && !verify_drm_device (device)) { + if (!manager->device_timeout_elapsed && + !verify_drm_device (manager, device)) { ply_trace ("ignoring since we only handle SimpleDRM devices after timeout"); return false; } @@ -1132,9 +1113,12 @@ create_devices_for_terminal_and_renderer_type (ply_device_manager_t *manager, if (renderer_type != PLY_RENDERER_TYPE_NONE) { ply_renderer_t *old_renderer = NULL; + bool force = manager->device_timeout_elapsed || + (manager->flags & PLY_DEVICE_MANAGER_FLAGS_FORCE_OPEN); + renderer = ply_renderer_new (renderer_type, device_path, terminal); - if (renderer != NULL && !ply_renderer_open (renderer)) { + if (renderer != NULL && !ply_renderer_open (renderer, force)) { ply_trace ("could not open renderer for %s", device_path); ply_renderer_free (renderer); renderer = NULL; diff --git a/src/libply-splash-core/ply-device-manager.h b/src/libply-splash-core/ply-device-manager.h index 820ecc39..fb5e1cf7 100644 --- a/src/libply-splash-core/ply-device-manager.h +++ b/src/libply-splash-core/ply-device-manager.h @@ -33,7 +33,9 @@ typedef enum PLY_DEVICE_MANAGER_FLAGS_IGNORE_SERIAL_CONSOLES = 1 << 0, PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV = 1 << 1, PLY_DEVICE_MANAGER_FLAGS_SKIP_RENDERERS = 1 << 2, - PLY_DEVICE_MANAGER_FLAGS_FORCE_FRAME_BUFFER = 1 << 3 + PLY_DEVICE_MANAGER_FLAGS_FORCE_FRAME_BUFFER = 1 << 3, + PLY_DEVICE_MANAGER_FLAGS_USE_SIMPLEDRM = 1 << 4, + PLY_DEVICE_MANAGER_FLAGS_FORCE_OPEN = 1 << 5, } ply_device_manager_flags_t; typedef struct _ply_device_manager ply_device_manager_t; diff --git a/src/libply-splash-core/ply-renderer-plugin.h b/src/libply-splash-core/ply-renderer-plugin.h index 483ad27c..d9f31de9 100644 --- a/src/libply-splash-core/ply-renderer-plugin.h +++ b/src/libply-splash-core/ply-renderer-plugin.h @@ -43,7 +43,8 @@ typedef struct void (*destroy_backend)(ply_renderer_backend_t *backend); bool (*open_device)(ply_renderer_backend_t *backend); void (*close_device)(ply_renderer_backend_t *backend); - bool (*query_device)(ply_renderer_backend_t *backend); + bool (*query_device)(ply_renderer_backend_t *backend, + bool force); bool (*handle_change_event)(ply_renderer_backend_t *backend); bool (*map_to_device)(ply_renderer_backend_t *backend); void (*unmap_from_device)(ply_renderer_backend_t *backend); diff --git a/src/libply-splash-core/ply-renderer.c b/src/libply-splash-core/ply-renderer.c index 61c59ccc..2c555f46 100644 --- a/src/libply-splash-core/ply-renderer.c +++ b/src/libply-splash-core/ply-renderer.c @@ -199,12 +199,13 @@ ply_renderer_close_device (ply_renderer_t *renderer) } static bool -ply_renderer_query_device (ply_renderer_t *renderer) +ply_renderer_query_device (ply_renderer_t *renderer, + bool force) { assert (renderer != NULL); assert (renderer->plugin_interface != NULL); - return renderer->plugin_interface->query_device (renderer->backend); + return renderer->plugin_interface->query_device (renderer->backend, force); } static bool @@ -236,7 +237,8 @@ ply_renderer_unmap_from_device (ply_renderer_t *renderer) static bool ply_renderer_open_plugin (ply_renderer_t *renderer, - const char *plugin_path) + const char *plugin_path, + bool force) { ply_trace ("trying to open renderer plugin %s", plugin_path); @@ -250,7 +252,7 @@ ply_renderer_open_plugin (ply_renderer_t *renderer, return false; } - if (!ply_renderer_query_device (renderer)) { + if (!ply_renderer_query_device (renderer, force)) { ply_trace ("could not query rendering device for plugin %s", plugin_path); ply_renderer_close_device (renderer); @@ -263,7 +265,8 @@ ply_renderer_open_plugin (ply_renderer_t *renderer, } bool -ply_renderer_open (ply_renderer_t *renderer) +ply_renderer_open (ply_renderer_t *renderer, + bool force) { int i; @@ -284,7 +287,7 @@ ply_renderer_open (ply_renderer_t *renderer) for (i = 0; known_plugins[i].type != PLY_RENDERER_TYPE_NONE; i++) { if (renderer->type == known_plugins[i].type || renderer->type == PLY_RENDERER_TYPE_AUTO) { - if (ply_renderer_open_plugin (renderer, known_plugins[i].path)) { + if (ply_renderer_open_plugin (renderer, known_plugins[i].path, force)) { renderer->is_active = true; goto out; } diff --git a/src/libply-splash-core/ply-renderer.h b/src/libply-splash-core/ply-renderer.h index cfd4f2dd..5ba18118 100644 --- a/src/libply-splash-core/ply-renderer.h +++ b/src/libply-splash-core/ply-renderer.h @@ -55,7 +55,8 @@ ply_renderer_t *ply_renderer_new (ply_renderer_type_t renderer_type, const char *device_name, ply_terminal_t *terminal); void ply_renderer_free (ply_renderer_t *renderer); -bool ply_renderer_open (ply_renderer_t *renderer); +bool ply_renderer_open (ply_renderer_t *renderer, + bool force); void ply_renderer_close (ply_renderer_t *renderer); /* Returns true when the heads have changed as a result of the change event */ bool ply_renderer_handle_change_event (ply_renderer_t *renderer); diff --git a/src/libply/ply-key-file.c b/src/libply/ply-key-file.c index 28a4885c..c296865a 100644 --- a/src/libply/ply-key-file.c +++ b/src/libply/ply-key-file.c @@ -406,18 +406,27 @@ ply_key_file_get_double (ply_key_file_t *key_file, return ply_strtod (raw_value); } -double -ply_key_file_get_long (ply_key_file_t *key_file, - const char *group, - const char *key, - long default_value) +unsigned long +ply_key_file_get_ulong (ply_key_file_t *key_file, + const char *group, + const char *key, + unsigned long default_value) { char *raw_value = ply_key_file_get_raw_value (key_file, group, key); + char *endptr = NULL; + unsigned long u; if (!raw_value) return default_value; - return strtol (raw_value, NULL, 0); + u = strtoul (raw_value, &endptr, 0); + if (*endptr != '\0') { + ply_trace ("group '%s' key '%s' val '%s' is not a valid unsigned number", + group, key, raw_value); + return default_value; + } + + return u; } static void diff --git a/src/libply/ply-key-file.h b/src/libply/ply-key-file.h index e240363c..487fd137 100644 --- a/src/libply/ply-key-file.h +++ b/src/libply/ply-key-file.h @@ -55,10 +55,10 @@ double ply_key_file_get_double (ply_key_file_t *key_file, const char *group_name, const char *key, double default_value); -double ply_key_file_get_long (ply_key_file_t *key_file, - const char *group, - const char *key, - long default_value); +unsigned long ply_key_file_get_ulong (ply_key_file_t *key_file, + const char *group, + const char *key, + unsigned long default_value); void ply_key_file_foreach_entry (ply_key_file_t *key_file, ply_key_file_foreach_func_t func, void *user_data); diff --git a/src/libply/ply-utils.c b/src/libply/ply-utils.c index 155459dc..dee79869 100644 --- a/src/libply/ply-utils.c +++ b/src/libply/ply-utils.c @@ -1251,6 +1251,28 @@ ply_kernel_command_line_get_key_value (const char *key) return strndup (value, strcspn (value, " \n")); } +unsigned long +ply_kernel_command_line_get_ulong (const char *key, + unsigned long default_value) +{ + const char *raw_value; + char *endptr = NULL; + unsigned long u; + + raw_value = ply_kernel_command_line_get_string_after_prefix (key); + if (raw_value == NULL || raw_value[0] == '\0') + return default_value; + + u = strtoul (raw_value, &endptr, 0); + if (!isspace ((int) *endptr) && *endptr != '\0') { + ply_trace ("'%s' argument '%s' is not a valid unsigned number", + key, raw_value); + return default_value; + } + + return u; +} + void ply_kernel_command_line_override (const char *command_line) { diff --git a/src/libply/ply-utils.h b/src/libply/ply-utils.h index 1ee31960..058c7bff 100644 --- a/src/libply/ply-utils.h +++ b/src/libply/ply-utils.h @@ -175,6 +175,8 @@ const char *ply_kernel_command_line_get_string_after_prefix (const char *prefix) bool ply_kernel_command_line_has_argument (const char *argument); void ply_kernel_command_line_override (const char *command_line); char *ply_kernel_command_line_get_key_value (const char *key); +unsigned long ply_kernel_command_line_get_ulong (const char *key, + unsigned long default_value); char *ply_get_primary_kernel_console_type (void); diff --git a/src/main.c b/src/main.c index e200c262..d9ba7340 100644 --- a/src/main.c +++ b/src/main.c @@ -101,6 +101,8 @@ typedef struct double start_time; double splash_delay; double device_timeout; + int device_scale; + int use_simpledrm; uint32_t no_boot_log : 1; uint32_t showing_details : 1; @@ -307,7 +309,6 @@ load_settings (state_t *state, { ply_key_file_t *key_file = NULL; bool settings_loaded = false; - char *scale_string = NULL; char *splash_string = NULL; ply_trace ("Trying to load %s", path); @@ -336,12 +337,11 @@ load_settings (state_t *state, ply_trace ("Device timeout is set to %lf", state->device_timeout); } - scale_string = ply_key_file_get_value (key_file, "Daemon", "DeviceScale"); + if (state->device_scale == -1) + state->device_scale = ply_key_file_get_ulong (key_file, "Daemon", "DeviceScale", -1); - if (scale_string != NULL) { - ply_set_device_scale (strtoul (scale_string, NULL, 0)); - free (scale_string); - } + if (state->use_simpledrm == -1) + state->use_simpledrm = ply_key_file_get_ulong (key_file, "Daemon", "UseSimpledrm", -1); settings_loaded = true; out: @@ -401,17 +401,19 @@ find_override_splash (state_t *state) if (delay_string != NULL) state->splash_delay = ply_strtod (delay_string); } -} -static void -find_force_scale (state_t *state) -{ - const char *scale_string; + if (state->device_scale == -1) + state->device_scale = ply_kernel_command_line_get_ulong ("plymouth.force-scale=", -1); - scale_string = ply_kernel_command_line_get_string_after_prefix ("plymouth.force-scale="); + if (state->use_simpledrm == -1) + state->use_simpledrm = ply_kernel_command_line_get_ulong ("plymouth.use-simpledrm=", -1); - if (scale_string != NULL) - ply_set_device_scale (strtoul (scale_string, NULL, 0)); + if (state->use_simpledrm == -1) { + if (ply_kernel_command_line_has_argument ("plymouth.use-simpledrm")) + state->use_simpledrm = 1; + else if (ply_kernel_command_line_has_argument ("nomodeset")) + state->use_simpledrm = 2; + } } static void @@ -2532,6 +2534,8 @@ main (int argc, state.progress = ply_progress_new (); state.splash_delay = NAN; state.device_timeout = NAN; + state.device_scale = -1; + state.use_simpledrm = -1; ply_progress_load_cache (state.progress, get_cache_file_for_mode (state.mode)); @@ -2572,7 +2576,14 @@ main (int argc, state.splash_delay = NAN; } - find_force_scale (&state); + if (state.device_scale != -1) + ply_set_device_scale (state.device_scale); + + if (state.use_simpledrm >= 1) + device_manager_flags |= PLY_DEVICE_MANAGER_FLAGS_USE_SIMPLEDRM; + + if (state.use_simpledrm >= 2) + device_manager_flags |= PLY_DEVICE_MANAGER_FLAGS_FORCE_OPEN; load_devices (&state, device_manager_flags); diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c index e09c7b3e..0249dbfa 100644 --- a/src/plugins/renderers/drm/plugin.c +++ b/src/plugins/renderers/drm/plugin.c @@ -1391,12 +1391,37 @@ check_if_output_has_changed (ply_renderer_backend_t *backend, return true; } +/* Sometimes the EFI firmware sets up the framebuffer at 800x600 or 1024x768 + * instead of the native panel resolution. In this case it is better to wait + * for the native driver to load, so we return false from query_device (). + */ +static bool +check_simpledrm_resolution (ply_renderer_backend_t *backend, + ply_output_t *output) +{ + if (!backend->simpledrm) + return true; + + if (!output->connected) + return true; + + if ((output->mode.hdisplay == 800 && output->mode.vdisplay == 600) || + (output->mode.hdisplay == 1024 && output->mode.vdisplay == 768)) { + ply_trace ("Skipping simpledrm device with mode %dx%d", + output->mode.hdisplay, output->mode.vdisplay); + return false; + } + + return true; +} + /* Update our outputs array to match the hardware state and * create and/or remove heads as necessary. * Returns true if any heads were modified. */ static bool create_heads_for_active_connectors (ply_renderer_backend_t *backend, + bool force, bool change) { int i, j, number_of_setup_outputs, outputs_len; @@ -1420,6 +1445,11 @@ create_heads_for_active_connectors (ply_renderer_backend_t *backend, for (i = 0; i < outputs_len; i++) { get_output_info (backend, backend->resources->connectors[i], &outputs[i]); + if (!force && !check_simpledrm_resolution (backend, &outputs[i])) { + free (outputs); + return false; + } + if (check_if_output_has_changed (backend, &outputs[i])) changed = true; @@ -1563,7 +1593,8 @@ has_32bpp_support (ply_renderer_backend_t *backend) } static bool -query_device (ply_renderer_backend_t *backend) +query_device (ply_renderer_backend_t *backend, + bool force) { bool ret = true; @@ -1577,7 +1608,7 @@ query_device (ply_renderer_backend_t *backend) return false; } - if (!create_heads_for_active_connectors (backend, false)) { + if (!create_heads_for_active_connectors (backend, force, false)) { ply_trace ("Could not initialize heads"); ret = false; } else if (!has_32bpp_support (backend)) { @@ -1602,7 +1633,7 @@ handle_change_event (ply_renderer_backend_t *backend) return false; } - ret = create_heads_for_active_connectors (backend, true); + ret = create_heads_for_active_connectors (backend, true, true); drmModeFreeResources (backend->resources); backend->resources = NULL; diff --git a/src/plugins/renderers/frame-buffer/plugin.c b/src/plugins/renderers/frame-buffer/plugin.c index 8f341d07..7d74bdc2 100644 --- a/src/plugins/renderers/frame-buffer/plugin.c +++ b/src/plugins/renderers/frame-buffer/plugin.c @@ -420,7 +420,8 @@ static const char *get_visual_name (int visual) } static bool -query_device (ply_renderer_backend_t *backend) +query_device (ply_renderer_backend_t *backend, + bool force) { struct fb_var_screeninfo variable_screen_info; struct fb_fix_screeninfo fixed_screen_info; diff --git a/src/plugins/renderers/x11/plugin.c b/src/plugins/renderers/x11/plugin.c index a673a40d..87aa7a93 100644 --- a/src/plugins/renderers/x11/plugin.c +++ b/src/plugins/renderers/x11/plugin.c @@ -284,7 +284,8 @@ create_fullscreen_single_head_setup (ply_renderer_backend_t *backend) } static bool -query_device (ply_renderer_backend_t *backend) +query_device (ply_renderer_backend_t *backend, + bool force) { assert (backend != NULL); diff --git a/src/plugins/splash/fade-throbber/plugin.c b/src/plugins/splash/fade-throbber/plugin.c index 17c4e25a..d9e018f5 100644 --- a/src/plugins/splash/fade-throbber/plugin.c +++ b/src/plugins/splash/fade-throbber/plugin.c @@ -255,14 +255,14 @@ create_plugin (ply_key_file_t *key_file) plugin->monospace_font = strdup ("monospace 10"); plugin->console_text_color = - ply_key_file_get_long (key_file, "fade-throbber", - "ConsoleLogTextColor", - PLY_CONSOLE_VIEWER_LOG_TEXT_COLOR); + ply_key_file_get_ulong (key_file, "fade-throbber", + "ConsoleLogTextColor", + PLY_CONSOLE_VIEWER_LOG_TEXT_COLOR); plugin->console_background_color = - ply_key_file_get_long (key_file, "fade-throbber", - "ConsoleLogBackgroundColor", - 0x00000000); + ply_key_file_get_ulong (key_file, "fade-throbber", + "ConsoleLogBackgroundColor", + 0x00000000); plugin->image_dir = image_dir; diff --git a/src/plugins/splash/script/plugin.c b/src/plugins/splash/script/plugin.c index 0bdd0258..a2e7443a 100644 --- a/src/plugins/splash/script/plugin.c +++ b/src/plugins/splash/script/plugin.c @@ -233,14 +233,14 @@ create_plugin (ply_key_file_t *key_file) plugin->monospace_font = strdup ("monospace 10"); plugin->console_text_color = - ply_key_file_get_long (key_file, "script", - "ConsoleLogTextColor", - PLY_CONSOLE_VIEWER_LOG_TEXT_COLOR); + ply_key_file_get_ulong (key_file, "script", + "ConsoleLogTextColor", + PLY_CONSOLE_VIEWER_LOG_TEXT_COLOR); plugin->console_background_color = - ply_key_file_get_long (key_file, "script", - "ConsoleLogBackgroundColor", - 0x00000000); + ply_key_file_get_ulong (key_file, "script", + "ConsoleLogBackgroundColor", + 0x00000000); plugin->displays = ply_list_new (); diff --git a/src/plugins/splash/space-flares/plugin.c b/src/plugins/splash/space-flares/plugin.c index e7ab76d5..8161dfa7 100644 --- a/src/plugins/splash/space-flares/plugin.c +++ b/src/plugins/splash/space-flares/plugin.c @@ -634,14 +634,14 @@ create_plugin (ply_key_file_t *key_file) plugin->monospace_font = strdup ("monospace 10"); plugin->console_text_color = - ply_key_file_get_long (key_file, "space-flares", - "ConsoleLogTextColor", - PLY_CONSOLE_VIEWER_LOG_TEXT_COLOR); + ply_key_file_get_ulong (key_file, "space-flares", + "ConsoleLogTextColor", + PLY_CONSOLE_VIEWER_LOG_TEXT_COLOR); plugin->console_background_color = - ply_key_file_get_long (key_file, "space-flares", - "ConsoleLogBackgroundColor", - 0x00000000); + ply_key_file_get_ulong (key_file, "space-flares", + "ConsoleLogBackgroundColor", + 0x00000000); plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL; plugin->progress = 0; diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c index 8fa0d621..65789bed 100644 --- a/src/plugins/splash/two-step/plugin.c +++ b/src/plugins/splash/two-step/plugin.c @@ -1286,44 +1286,44 @@ create_plugin (ply_key_file_t *key_file) plugin->console_text_color = - ply_key_file_get_long (key_file, "two-step", - "ConsoleLogTextColor", - PLY_CONSOLE_VIEWER_LOG_TEXT_COLOR); + ply_key_file_get_ulong (key_file, "two-step", + "ConsoleLogTextColor", + PLY_CONSOLE_VIEWER_LOG_TEXT_COLOR); plugin->console_background_color = - ply_key_file_get_long (key_file, "two-step", - "ConsoleLogBackgroundColor", - 0x00000000); + ply_key_file_get_ulong (key_file, "two-step", + "ConsoleLogBackgroundColor", + 0x00000000); plugin->transition_duration = ply_key_file_get_double (key_file, "two-step", "TransitionDuration", 0.0); plugin->background_start_color = - ply_key_file_get_long (key_file, "two-step", - "BackgroundStartColor", - PLYMOUTH_BACKGROUND_START_COLOR); + ply_key_file_get_ulong (key_file, "two-step", + "BackgroundStartColor", + PLYMOUTH_BACKGROUND_START_COLOR); plugin->background_end_color = - ply_key_file_get_long (key_file, "two-step", - "BackgroundEndColor", - PLYMOUTH_BACKGROUND_END_COLOR); + ply_key_file_get_ulong (key_file, "two-step", + "BackgroundEndColor", + PLYMOUTH_BACKGROUND_END_COLOR); plugin->progress_bar_bg_color = - ply_key_file_get_long (key_file, "two-step", - "ProgressBarBackgroundColor", - 0xffffff /* white */); + ply_key_file_get_ulong (key_file, "two-step", + "ProgressBarBackgroundColor", + 0xffffff /* white */); plugin->progress_bar_fg_color = - ply_key_file_get_long (key_file, "two-step", - "ProgressBarForegroundColor", - 0x000000 /* black */); + ply_key_file_get_ulong (key_file, "two-step", + "ProgressBarForegroundColor", + 0x000000 /* black */); plugin->progress_bar_width = - ply_key_file_get_long (key_file, "two-step", - "ProgressBarWidth", - PROGRESS_BAR_WIDTH); + ply_key_file_get_ulong (key_file, "two-step", + "ProgressBarWidth", + PROGRESS_BAR_WIDTH); plugin->progress_bar_height = - ply_key_file_get_long (key_file, "two-step", - "ProgressBarHeight", - PROGRESS_BAR_HEIGHT); + ply_key_file_get_ulong (key_file, "two-step", + "ProgressBarHeight", + PROGRESS_BAR_HEIGHT); load_mode_settings (plugin, key_file, "boot-up", PLY_BOOT_SPLASH_MODE_BOOT_UP); load_mode_settings (plugin, key_file, "shutdown", PLY_BOOT_SPLASH_MODE_SHUTDOWN);