# Calculate format=diff merge(sys-boot/plymouth)<0.9.5
commit 4ec46d8b9a1fdd4eb791013bae98e4ca34b412de
Author: Mir Calculate <support@calculate.ru>
Date:   Wed Feb 13 15:35:50 2019 +0300

    Изменён порядок инициализации framebuffer для plymouth
    
    Добавлена переменная конфигурационного файла
    FBDeviceTimeout, по истечении которого plymouth будет ожидать не только DRM
    устройства, но и framebuffer. По истечении DeviceTimeout plymouth будет
    запущен для text mode.

diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c
index 55248ac..4350324 100644
--- a/src/libply-splash-core/ply-device-manager.c
+++ b/src/libply-splash-core/ply-device-manager.c
@@ -39,12 +39,14 @@
 #include "ply-hashtable.h"
 #include "ply-list.h"
 #include "ply-utils.h"
+#include <math.h>
 
 #define SUBSYSTEM_DRM "drm"
 #define SUBSYSTEM_FRAME_BUFFER "graphics"
 
 #ifdef HAVE_UDEV
 static void create_devices_from_udev (ply_device_manager_t *manager);
+static void create_fb_devices_from_udev (ply_device_manager_t *manager);
 #endif
 
 static bool create_devices_for_terminal_and_renderer_type (ply_device_manager_t *manager,
@@ -81,6 +83,7 @@ struct _ply_device_manager
 
         uint32_t                    paused : 1;
         uint32_t                    device_timeout_elapsed : 1;
+        uint32_t                    fb_device_timeout_elapsed : 1;
 };
 
 static void
@@ -361,7 +364,12 @@ on_udev_event (ply_device_manager_t *manager)
                                 ply_trace ("ignoring since we're already using text splash for local console");
                         else
                                 create_devices_for_udev_device (manager, device);
-                } else {
+                } else if (manager->fb_device_timeout_elapsed && strcmp (subsystem, SUBSYSTEM_FRAME_BUFFER) == 0){
+                        if (manager->local_console_managed && manager->local_console_is_text)
+                                ply_trace ("ignoring since we're already using text splash for local console");
+                        else
+                                create_devices_for_udev_device (manager, device);
+		} else {
                         ply_trace ("ignoring since we only handle subsystem %s devices after timeout", subsystem);
                 }
         } else if (strcmp (action, "remove") == 0) {
@@ -539,6 +547,9 @@ ply_device_manager_free (ply_device_manager_t *manager)
         ply_event_loop_stop_watching_for_timeout (manager->loop,
                                          (ply_event_loop_timeout_handler_t)
                                          create_devices_from_udev, manager);
+        ply_event_loop_stop_watching_for_timeout (manager->loop,
+                                         (ply_event_loop_timeout_handler_t)
+                                         create_fb_devices_from_udev, manager);
 
         if (manager->udev_monitor != NULL)
                 udev_monitor_unref (manager->udev_monitor);
@@ -838,6 +849,24 @@ create_devices_from_udev (ply_device_manager_t *manager)
         ply_trace ("Creating non-graphical devices, since there's no suitable graphics hardware");
         create_non_graphical_devices (manager);
 }
+
+static void
+create_fb_devices_from_udev (ply_device_manager_t *manager)
+{
+        bool found_drm_device, found_fb_device;
+
+        manager->fb_device_timeout_elapsed = true;
+
+        if (manager->paused) {
+                ply_trace ("create_fb_devices_from_udev timeout elapsed while paused, deferring execution");
+                return;
+        }
+
+        ply_trace ("Timeout elapsed, looking for framebuffer devices from udev");
+
+        found_drm_device = create_devices_for_subsystem (manager, SUBSYSTEM_DRM);
+        found_fb_device = create_devices_for_subsystem (manager, SUBSYSTEM_FRAME_BUFFER);
+}
 #endif
 
 static void
@@ -851,6 +880,7 @@ create_fallback_devices (ply_device_manager_t *manager)
 
 void
 ply_device_manager_watch_devices (ply_device_manager_t                *manager,
+                                  double                               fb_device_timeout,
                                   double                               device_timeout,
                                   ply_keyboard_added_handler_t         keyboard_added_handler,
                                   ply_keyboard_removed_handler_t       keyboard_removed_handler,
@@ -870,6 +900,9 @@ ply_device_manager_watch_devices (ply_device_manager_t                *manager,
         manager->text_display_removed_handler = text_display_removed_handler;
         manager->event_handler_data = data;
 
+        if (isnan (fb_device_timeout))
+                fb_device_timeout = 5;
+
         /* Try to create devices for each serial device right away, if possible
          */
         done_with_initial_devices_setup = create_devices_from_terminals (manager);
@@ -892,6 +925,10 @@ ply_device_manager_watch_devices (ply_device_manager_t                *manager,
 #ifdef HAVE_UDEV
         watch_for_udev_events (manager);
         create_devices_for_subsystem (manager, SUBSYSTEM_DRM);
+        ply_event_loop_watch_for_timeout (manager->loop,
+                                         fb_device_timeout,
+                                         (ply_event_loop_timeout_handler_t)
+                                         create_fb_devices_from_udev, manager);
         ply_event_loop_watch_for_timeout (manager->loop,
                                          device_timeout,
                                          (ply_event_loop_timeout_handler_t)
@@ -1035,6 +1072,10 @@ ply_device_manager_unpause (ply_device_manager_t *manager)
         ply_trace ("ply_device_manager_unpause() called, resuming watching for udev events");
         manager->paused = false;
 #ifdef HAVE_UDEV
+        if (manager->fb_device_timeout_elapsed) {
+                ply_trace ("ply_device_manager_unpause(): timeout elapsed while paused, looking for framebuffer udev devices");
+                create_fb_devices_from_udev (manager);
+        }
         if (manager->device_timeout_elapsed) {
                 ply_trace ("ply_device_manager_unpause(): timeout elapsed while paused, looking for udev devices");
                 create_devices_from_udev (manager);
diff --git a/src/libply-splash-core/ply-device-manager.h b/src/libply-splash-core/ply-device-manager.h
index 389b636..37198a2 100644
--- a/src/libply-splash-core/ply-device-manager.h
+++ b/src/libply-splash-core/ply-device-manager.h
@@ -47,6 +47,7 @@ typedef void (* ply_text_display_removed_handler_t) (void *, ply_text_display_t
 ply_device_manager_t *ply_device_manager_new (const char                *default_tty,
                                               ply_device_manager_flags_t flags);
 void ply_device_manager_watch_devices (ply_device_manager_t                *manager,
+                                       double                               fb_device_timeout,
                                        double                               device_timeout,
                                        ply_keyboard_added_handler_t         keyboard_added_handler,
                                        ply_keyboard_removed_handler_t       keyboard_removed_handler,
diff --git a/src/main.c b/src/main.c
index ddc1883..f8f980c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -103,6 +103,7 @@ typedef struct
         double                  start_time;
         double                  splash_delay;
         double                  device_timeout;
+        double                  fb_device_timeout;
 
         uint32_t                no_boot_log : 1;
         uint32_t                showing_details : 1;
@@ -340,6 +341,19 @@ load_settings (state_t    *state,
                 }
         }
 
+        if (isnan (state->fb_device_timeout)) {
+                char *timeout_string;
+
+                timeout_string = ply_key_file_get_value (key_file, "Daemon", "FBDeviceTimeout");
+
+                if (timeout_string != NULL) {
+                        state->fb_device_timeout = atof (timeout_string);
+                        ply_trace ("Framebuffer device timeout is set to %lf", state->fb_device_timeout);
+
+                        free (timeout_string);
+                }
+        }
+
         scale_string = ply_key_file_get_value (key_file, "Daemon", "DeviceScale");
 
         if (scale_string != NULL) {
@@ -1100,6 +1114,7 @@ load_devices (state_t                   *state,
         state->local_console_terminal = ply_device_manager_get_default_terminal (state->device_manager);
 
         ply_device_manager_watch_devices (state->device_manager,
+                                          state->fb_device_timeout,
                                           state->device_timeout,
                                           (ply_keyboard_added_handler_t)
                                           on_keyboard_added,
@@ -2269,6 +2284,7 @@ main (int    argc,
         state.progress = ply_progress_new ();
         state.splash_delay = NAN;
         state.device_timeout = NAN;
+        state.fb_device_timeout = NAN;
 
         ply_progress_load_cache (state.progress,
                                  get_cache_file_for_mode (state.mode));
