diff --git a/Makefile.am b/Makefile.am index 395c91b..cb6eedb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,7 +4,7 @@ if BUILD_DOCUMENTATION SUBDIRS += docs endif -DISTCHECK_CONFIGURE_FLAGS = --disable-tests --without-system-root-install +DISTCHECK_CONFIGURE_FLAGS = --disable-tests --disable-systemd-integration EXTRA_DIST = ChangeLog \ README diff --git a/configure.ac b/configure.ac index aad673e..d145c69 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([plymouth],[0.9.2],[https://bugs.freedesktop.org/enter_bug.cgi?product=plymouth]) +AC_INIT([plymouth],[0.9.3],[https://bugs.freedesktop.org/enter_bug.cgi?product=plymouth]) AC_CONFIG_SRCDIR(src/main.c) AC_CONFIG_HEADER(config.h) AC_CONFIG_AUX_DIR(build-tools) @@ -11,7 +11,7 @@ AM_PROG_CC_C_O AC_HEADER_STDC AC_C_CONST -AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip]) +AM_INIT_AUTOMAKE([dist-xz no-dist-gzip]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) AM_MAINTAINER_MODE([enable]) @@ -38,9 +38,18 @@ PKG_CHECK_MODULES(IMAGE, [libpng >= 1.2.16 ]) AC_SUBST(IMAGE_CFLAGS) AC_SUBST(IMAGE_LIBS) -PKG_CHECK_MODULES(UDEV, [libudev]); -AC_SUBST(UDEV_CFLAGS) -AC_SUBST(UDEV_LIBS) +AC_ARG_WITH(udev, AS_HELP_STRING([--with-udev], [Add udev support]),, with_udev=yes) + +if test "x$with_udev" != "xno" ; then + PKG_CHECK_MODULES(UDEV, [libudev], have_udev=yes, have_udev=no) + AC_SUBST(UDEV_CFLAGS) + AC_SUBST(UDEV_LIBS) + if test "x$have_udev" = "xyes"; then + AC_DEFINE(HAVE_UDEV, 1, [Define if have udev support]) + else + AC_MSG_ERROR([libudev is required unless --without-udev is passed]) + fi +fi PLYMOUTH_CFLAGS="" PLYMOUTH_LIBS="-lm -lrt -ldl" @@ -117,16 +126,21 @@ if test x$enable_upstart_monitoring = xyes; then fi AM_CONDITIONAL(ENABLE_UPSTART_MONITORING, [test "$enable_upstart_monitoring" = yes]) -AC_ARG_ENABLE(systemd-integration, AS_HELP_STRING([--enable-systemd-integration],[coordinate boot up with systemd]),enable_systemd_integration=$enableval,enable_systemd_integration=no) +AC_ARG_ENABLE(systemd-integration, AS_HELP_STRING([--enable-systemd-integration],[coordinate boot up with systemd]),enable_systemd_integration=$enableval,enable_systemd_integration=yes) AM_CONDITIONAL(ENABLE_SYSTEMD_INTEGRATION, [test "$enable_systemd_integration" = yes]) if test x$enable_systemd_integration = xyes; then AC_DEFINE(PLY_ENABLE_SYSTEMD_INTEGRATION, 1, [Coordinate boot up with systemd]) - SYSTEMD_UNIT_DIR=$($PKG_CONFIG --variable=systemdsystemunitdir systemd) + AC_ARG_WITH([systemdunitdir], AC_HELP_STRING([--with-systemdunitdir=DIR], + [path to systemd service directory]), [path_systemdunit=${withval}], + [path_systemdunit="`$PKG_CONFIG --variable=systemdsystemunitdir systemd`"]) + if (test -n "${path_systemdunit}"); then + SYSTEMD_UNIT_DIR="${path_systemdunit}" + fi AC_SUBST(SYSTEMD_UNIT_DIR) fi -AC_ARG_WITH(system-root-install, AS_HELP_STRING([--with-system-root-install],[Install client in /bin and daemon in /sbin]),with_system_root_install=${withval},with_system_root_install=yes) +AC_ARG_WITH(system-root-install, AS_HELP_STRING([--with-system-root-install],[Install client in /bin and daemon in /sbin]),with_system_root_install=${withval},with_system_root_install=no) AM_CONDITIONAL(WITH_SYSTEM_ROOT_INSTALL, [test "$with_system_root_install" = yes]) if test x$with_system_root_install = xyes; then diff --git a/scripts/plymouth-populate-initrd.in b/scripts/plymouth-populate-initrd.in index 43c7f22..e3326e9 100755 --- a/scripts/plymouth-populate-initrd.in +++ b/scripts/plymouth-populate-initrd.in @@ -392,6 +392,9 @@ fi if [ $THEME_OVERRIDE ]; then conf=$INITRDDIR/${PLYMOUTH_CONFDIR}/plymouthd.conf echo "modifying plymouthd.conf: Theme=$PLYMOUTH_THEME_NAME" > /dev/stderr + # make sure the section and key exist so we can modify them + grep -q "^ *\[Daemon\]" $conf || echo "[Daemon]" >> $conf + grep -q "^ *Theme *=" $conf || echo "Theme=fade-in" >> $conf sed -i "s/^ *Theme *=.*/# theme modified by plymouth-populate-initrd\nTheme=$PLYMOUTH_THEME_NAME/" $conf fi diff --git a/src/libply-splash-core/Makefile.am b/src/libply-splash-core/Makefile.am index d07d7f1..7036569 100644 --- a/src/libply-splash-core/Makefile.am +++ b/src/libply-splash-core/Makefile.am @@ -21,7 +21,6 @@ libply_splash_core_HEADERS = \ ply-pixel-display.h \ ply-renderer.h \ ply-renderer-plugin.h \ - ply-seat.h \ ply-terminal.h \ ply-text-display.h \ ply-text-progress-bar.h \ @@ -47,7 +46,6 @@ libply_splash_core_la_SOURCES = \ ply-terminal.c \ ply-pixel-buffer.c \ ply-renderer.c \ - ply-seat.c \ ply-boot-splash.c MAINTAINERCLEANFILES = Makefile.in diff --git a/src/libply-splash-core/ply-boot-splash.c b/src/libply-splash-core/ply-boot-splash.c index 310d4d5..87a7a0c 100644 --- a/src/libply-splash-core/ply-boot-splash.c +++ b/src/libply-splash-core/ply-boot-splash.c @@ -57,7 +57,10 @@ struct _ply_boot_splash ply_boot_splash_mode_t mode; ply_buffer_t *boot_buffer; ply_trigger_t *idle_trigger; - ply_list_t *seats; + + ply_keyboard_t *keyboard; + ply_list_t *pixel_displays; + ply_list_t *text_displays; char *theme_path; char *plugin_dir; @@ -94,160 +97,102 @@ ply_boot_splash_new (const char *theme_path, splash->mode = PLY_BOOT_SPLASH_MODE_INVALID; splash->boot_buffer = boot_buffer; - splash->seats = ply_list_new (); + splash->pixel_displays = ply_list_new (); + splash->text_displays = ply_list_new (); return splash; } -static void -detach_from_seat (ply_boot_splash_t *splash, - ply_seat_t *seat) +void +ply_boot_splash_set_keyboard (ply_boot_splash_t *splash, + ply_keyboard_t *keyboard) { - ply_keyboard_t *keyboard; - ply_list_t *displays; - ply_list_node_t *node, *next_node; - - ply_trace ("removing keyboard"); - if (splash->plugin_interface->unset_keyboard != NULL) { - keyboard = ply_seat_get_keyboard (seat); - splash->plugin_interface->unset_keyboard (splash->plugin, keyboard); - } - - ply_trace ("removing pixel displays"); - displays = ply_seat_get_pixel_displays (seat); - - node = ply_list_get_first_node (displays); - while (node != NULL) { - ply_pixel_display_t *display; - ply_list_node_t *next_node; - unsigned long width, height; - - display = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (displays, node); - - width = ply_pixel_display_get_width (display); - height = ply_pixel_display_get_height (display); - - ply_trace ("Removing %lux%lu pixel display", width, height); - - if (splash->plugin_interface->remove_pixel_display != NULL) - splash->plugin_interface->remove_pixel_display (splash->plugin, display); - - node = next_node; - } - - ply_trace ("removing text displays"); - displays = ply_seat_get_text_displays (seat); - - node = ply_list_get_first_node (displays); - while (node != NULL) { - ply_text_display_t *display; - int number_of_columns, number_of_rows; - - display = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (displays, node); - - number_of_columns = ply_text_display_get_number_of_columns (display); - number_of_rows = ply_text_display_get_number_of_rows (display); - - ply_trace ("Removing %dx%d text display", number_of_columns, number_of_rows); - - if (splash->plugin_interface->remove_text_display != NULL) - splash->plugin_interface->remove_text_display (splash->plugin, display); + if (splash->plugin_interface->set_keyboard == NULL) + return; - node = next_node; - } + splash->plugin_interface->set_keyboard (splash->plugin, keyboard); + splash->keyboard = keyboard; } -static void -attach_to_seat (ply_boot_splash_t *splash, - ply_seat_t *seat) +void +ply_boot_splash_unset_keyboard (ply_boot_splash_t *splash) { - ply_keyboard_t *keyboard; - ply_list_t *displays; - ply_list_node_t *node, *next_node; - - if (splash->plugin_interface->set_keyboard != NULL) { - keyboard = ply_seat_get_keyboard (seat); - splash->plugin_interface->set_keyboard (splash->plugin, keyboard); - } - - if (splash->plugin_interface->add_pixel_display != NULL) { - displays = ply_seat_get_pixel_displays (seat); - - ply_trace ("adding pixel displays"); - node = ply_list_get_first_node (displays); - while (node != NULL) { - ply_pixel_display_t *display; - ply_list_node_t *next_node; - unsigned long width, height; - - display = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (displays, node); + if (splash->plugin_interface->unset_keyboard == NULL) + return; - width = ply_pixel_display_get_width (display); - height = ply_pixel_display_get_height (display); + splash->plugin_interface->unset_keyboard (splash->plugin, splash->keyboard); +} - ply_trace ("Adding %lux%lu pixel display", width, height); +void +ply_boot_splash_add_pixel_display (ply_boot_splash_t *splash, + ply_pixel_display_t *display) +{ + unsigned long width, height; - splash->plugin_interface->add_pixel_display (splash->plugin, display); + if (splash->plugin_interface->add_pixel_display == NULL) + return; - node = next_node; - } - } + width = ply_pixel_display_get_width (display); + height = ply_pixel_display_get_height (display); - if (splash->plugin_interface->add_text_display != NULL) { - displays = ply_seat_get_text_displays (seat); + ply_trace ("adding %lux%lu pixel display", width, height); - ply_trace ("adding text displays"); - node = ply_list_get_first_node (displays); - while (node != NULL) { - ply_text_display_t *display; - int number_of_columns, number_of_rows; + splash->plugin_interface->add_pixel_display (splash->plugin, display); + ply_list_append_data (splash->pixel_displays, display); +} - display = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (displays, node); +void +ply_boot_splash_remove_pixel_display (ply_boot_splash_t *splash, + ply_pixel_display_t *display) +{ + unsigned long width, height; - number_of_columns = ply_text_display_get_number_of_columns (display); - number_of_rows = ply_text_display_get_number_of_rows (display); + if (splash->plugin_interface->remove_pixel_display == NULL) + return; - ply_trace ("Adding %dx%d text display", number_of_columns, number_of_rows); + width = ply_pixel_display_get_width (display); + height = ply_pixel_display_get_height (display); - splash->plugin_interface->add_text_display (splash->plugin, display); + ply_trace ("removing %lux%lu pixel display", width, height); - node = next_node; - } - } + splash->plugin_interface->remove_pixel_display (splash->plugin, display); + ply_list_remove_data (splash->pixel_displays, display); } void -ply_boot_splash_attach_to_seat (ply_boot_splash_t *splash, - ply_seat_t *seat) +ply_boot_splash_add_text_display (ply_boot_splash_t *splash, + ply_text_display_t *display) { - ply_list_node_t *node; + int number_of_columns, number_of_rows; - node = ply_list_find_node (splash->seats, seat); - - if (node != NULL) + if (splash->plugin_interface->add_text_display == NULL) return; - ply_list_append_data (splash->seats, seat); - attach_to_seat (splash, seat); + number_of_columns = ply_text_display_get_number_of_columns (display); + number_of_rows = ply_text_display_get_number_of_rows (display); + + ply_trace ("adding %dx%d text display", number_of_columns, number_of_rows); + + splash->plugin_interface->add_text_display (splash->plugin, display); + ply_list_append_data (splash->text_displays, display); } void -ply_boot_splash_detach_from_seat (ply_boot_splash_t *splash, - ply_seat_t *seat) +ply_boot_splash_remove_text_display (ply_boot_splash_t *splash, + ply_text_display_t *display) { - ply_list_node_t *node; - - node = ply_list_find_node (splash->seats, seat); + int number_of_columns, number_of_rows; - if (node == NULL) + if (splash->plugin_interface->remove_text_display == NULL) return; - ply_list_remove_data (splash->seats, seat); - detach_from_seat (splash, seat); + number_of_columns = ply_text_display_get_number_of_columns (display); + number_of_rows = ply_text_display_get_number_of_rows (display); + + ply_trace ("removing %dx%d text display", number_of_columns, number_of_rows); + + splash->plugin_interface->remove_text_display (splash->plugin, display); + ply_list_remove_data (splash->text_displays, display); } bool @@ -378,23 +323,60 @@ ply_boot_splash_unload (ply_boot_splash_t *splash) } static void -detach_from_seats (ply_boot_splash_t *splash) +remove_pixel_displays (ply_boot_splash_t *splash) +{ + ply_list_node_t *node; + + if (splash->plugin_interface->remove_pixel_display == NULL) + return; + + ply_trace ("removing pixel displays"); + + node = ply_list_get_first_node (splash->pixel_displays); + while (node != NULL) { + ply_pixel_display_t *display; + ply_list_node_t *next_node; + unsigned long width, height; + + display = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (splash->pixel_displays, node); + + width = ply_pixel_display_get_width (display); + height = ply_pixel_display_get_height (display); + + ply_trace ("Removing %lux%lu pixel display", width, height); + + splash->plugin_interface->remove_pixel_display (splash->plugin, display); + + node = next_node; + } +} + +static void +remove_text_displays (ply_boot_splash_t *splash) { ply_list_node_t *node; - ply_trace ("detaching from seats"); + if (splash->plugin_interface->remove_text_display == NULL) + return; + + ply_trace ("removing text displays"); - node = ply_list_get_first_node (splash->seats); + node = ply_list_get_first_node (splash->text_displays); while (node != NULL) { - ply_seat_t *seat; + ply_text_display_t *display; ply_list_node_t *next_node; + int number_of_columns, number_of_rows; - seat = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (splash->seats, node); + display = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (splash->text_displays, node); - detach_from_seat (splash, seat); + number_of_columns = ply_text_display_get_number_of_columns (display); + number_of_rows = ply_text_display_get_number_of_rows (display); + + ply_trace ("Removing %dx%d text display", number_of_columns, number_of_rows); - ply_list_remove_node (splash->seats, node); + splash->plugin_interface->remove_text_display (splash->plugin, display); node = next_node; } @@ -419,11 +401,17 @@ ply_boot_splash_free (ply_boot_splash_t *splash) splash); } - detach_from_seats (splash); - ply_list_free (splash->seats); + if (splash->module_handle != NULL) { + ply_boot_splash_unset_keyboard (splash); + + remove_pixel_displays (splash); + ply_list_free (splash->pixel_displays); + + remove_text_displays (splash); + ply_list_free (splash->text_displays); - if (splash->module_handle != NULL) ply_boot_splash_unload (splash); + } if (splash->idle_trigger != NULL) ply_trigger_free (splash->idle_trigger); diff --git a/src/libply-splash-core/ply-boot-splash.h b/src/libply-splash-core/ply-boot-splash.h index 0ad6f22..b66ca47 100644 --- a/src/libply-splash-core/ply-boot-splash.h +++ b/src/libply-splash-core/ply-boot-splash.h @@ -33,12 +33,10 @@ #include "ply-pixel-display.h" #include "ply-text-display.h" #include "ply-progress.h" -#include "ply-seat.h" #include "ply-boot-splash-plugin.h" typedef struct _ply_boot_splash ply_boot_splash_t; -typedef struct _ply_seat ply_seat_t; typedef void (*ply_boot_splash_on_idle_handler_t) (void *user_data); @@ -50,10 +48,17 @@ ply_boot_splash_t *ply_boot_splash_new (const char *theme_path, bool ply_boot_splash_load (ply_boot_splash_t *splash); bool ply_boot_splash_load_built_in (ply_boot_splash_t *splash); void ply_boot_splash_unload (ply_boot_splash_t *splash); -void ply_boot_splash_attach_to_seat (ply_boot_splash_t *splash, - ply_seat_t *seat); -void ply_boot_splash_detach_from_seat (ply_boot_splash_t *splash, - ply_seat_t *seat); +void ply_boot_splash_set_keyboard (ply_boot_splash_t *splash, + ply_keyboard_t *keyboard); +void ply_boot_splash_unset_keyboard (ply_boot_splash_t *splash); +void ply_boot_splash_add_pixel_display (ply_boot_splash_t *splash, + ply_pixel_display_t *pixel_display); +void ply_boot_splash_remove_pixel_display (ply_boot_splash_t *splash, + ply_pixel_display_t *pixel_display); +void ply_boot_splash_add_text_display (ply_boot_splash_t *splash, + ply_text_display_t *text_display); +void ply_boot_splash_remove_text_display (ply_boot_splash_t *splash, + ply_text_display_t *text_display); void ply_boot_splash_free (ply_boot_splash_t *splash); bool ply_boot_splash_show (ply_boot_splash_t *splash, ply_boot_splash_mode_t mode); diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c index 67eba32..b4c33d4 100644 --- a/src/libply-splash-core/ply-device-manager.c +++ b/src/libply-splash-core/ply-device-manager.c @@ -30,7 +30,9 @@ #include #include +#ifdef HAVE_UDEV #include +#endif #include "ply-logger.h" #include "ply-event-loop.h" @@ -41,27 +43,40 @@ #define SUBSYSTEM_DRM "drm" #define SUBSYSTEM_FRAME_BUFFER "graphics" -static void create_seat_for_terminal_and_renderer_type (ply_device_manager_t *manager, - const char *device_path, - ply_terminal_t *terminal, - ply_renderer_type_t renderer_type); +#ifdef HAVE_UDEV +static void create_devices_from_udev (ply_device_manager_t *manager); +#endif + +static void create_devices_for_terminal_and_renderer_type (ply_device_manager_t *manager, + const char *device_path, + ply_terminal_t *terminal, + ply_renderer_type_t renderer_type); struct _ply_device_manager { ply_device_manager_flags_t flags; ply_event_loop_t *loop; ply_hashtable_t *terminals; + ply_hashtable_t *renderers; ply_terminal_t *local_console_terminal; - ply_seat_t *local_console_seat; - ply_list_t *seats; + ply_list_t *keyboards; + ply_list_t *text_displays; + ply_list_t *pixel_displays; struct udev *udev_context; - struct udev_queue *udev_queue; - int udev_queue_fd; - ply_fd_watch_t *udev_queue_fd_watch; struct udev_monitor *udev_monitor; - ply_seat_added_handler_t seat_added_handler; - ply_seat_removed_handler_t seat_removed_handler; - void *seat_event_handler_data; + ply_keyboard_added_handler_t keyboard_added_handler; + ply_keyboard_removed_handler_t keyboard_removed_handler; + ply_pixel_display_added_handler_t pixel_display_added_handler; + ply_pixel_display_removed_handler_t pixel_display_removed_handler; + ply_text_display_added_handler_t text_display_added_handler; + ply_text_display_removed_handler_t text_display_removed_handler; + void *event_handler_data; + + uint32_t local_console_managed : 1; + uint32_t local_console_is_text : 1; + uint32_t serial_consoles_detected : 1; + uint32_t renderers_activated : 1; + uint32_t keyboards_activated : 1; }; static void @@ -87,64 +102,66 @@ attach_to_event_loop (ply_device_manager_t *manager, manager); } -static bool -device_is_for_local_console (ply_device_manager_t *manager, - struct udev_device *device) -{ - const char *device_path; - struct udev_device *bus_device; - char *bus_device_path; - const char *boot_vga; - bool for_local_console; - - /* Look at the associated bus device to see if this card is the - * card the kernel is using for its console. */ - device_path = udev_device_get_syspath (device); - asprintf (&bus_device_path, "%s/device", device_path); - bus_device = udev_device_new_from_syspath (manager->udev_context, bus_device_path); - - boot_vga = udev_device_get_sysattr_value (bus_device, "boot_vga"); - free (bus_device_path); - - if (boot_vga != NULL && strcmp (boot_vga, "1") == 0) - for_local_console = true; - else - for_local_console = false; - - return for_local_console; -} - -static bool -drm_device_in_use (ply_device_manager_t *manager, - const char *device_path) +static void +free_displays_for_renderer (ply_device_manager_t *manager, + ply_renderer_t *renderer) { ply_list_node_t *node; - node = ply_list_get_first_node (manager->seats); + node = ply_list_get_first_node (manager->pixel_displays); while (node != NULL) { - ply_seat_t *seat; - ply_renderer_t *renderer; ply_list_node_t *next_node; - const char *renderer_device_path; + ply_pixel_display_t *display; + ply_renderer_t *display_renderer; - seat = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (manager->seats, node); - renderer = ply_seat_get_renderer (seat); + display = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (manager->pixel_displays, node); + display_renderer = ply_pixel_display_get_renderer (display); - if (renderer != NULL) { - renderer_device_path = ply_renderer_get_device_name (renderer); + if (display_renderer == renderer) { + if (manager->pixel_display_removed_handler != NULL) + manager->pixel_display_removed_handler (manager->event_handler_data, display); + ply_pixel_display_free (display); + ply_list_remove_node (manager->pixel_displays, node); - if (renderer_device_path != NULL) { - if (strcmp (device_path, renderer_device_path) == 0) { - return true; - } - } } node = next_node; } +} - return false; +static void +free_devices_from_device_path (ply_device_manager_t *manager, + const char *device_path) +{ + char *key = NULL; + ply_renderer_t *renderer = NULL; + + ply_hashtable_lookup_full (manager->renderers, + (void *) device_path, + (void **) &key, + (void **) &renderer); + + if (renderer == NULL) + return; + + free_displays_for_renderer (manager, renderer); + + ply_hashtable_remove (manager->renderers, (void *) device_path); + free (key); + ply_renderer_free (renderer); +} + +#ifdef HAVE_UDEV +static bool +drm_device_in_use (ply_device_manager_t *manager, + const char *device_path) +{ + ply_renderer_t *renderer; + + renderer = ply_hashtable_lookup (manager->renderers, (void *) device_path); + + return renderer != NULL; } static bool @@ -196,19 +213,10 @@ fb_device_has_drm_device (ply_device_manager_t *manager, } static void -create_seat_for_udev_device (ply_device_manager_t *manager, - struct udev_device *device) +create_devices_for_udev_device (ply_device_manager_t *manager, + struct udev_device *device) { - bool for_local_console; const char *device_path; - ply_terminal_t *terminal = NULL; - - for_local_console = device_is_for_local_console (manager, device); - - ply_trace ("device is for local console: %s", for_local_console ? "yes" : "no"); - - if (for_local_console) - terminal = manager->local_console_terminal; device_path = udev_device_get_devnode (device); @@ -231,7 +239,13 @@ create_seat_for_udev_device (ply_device_manager_t *manager, } if (renderer_type != PLY_RENDERER_TYPE_NONE) { - create_seat_for_terminal_and_renderer_type (manager, + ply_terminal_t *terminal = NULL; + + if (!manager->local_console_managed) { + terminal = manager->local_console_terminal; + } + + create_devices_for_terminal_and_renderer_type (manager, device_path, terminal, renderer_type); @@ -240,64 +254,26 @@ create_seat_for_udev_device (ply_device_manager_t *manager, } static void -free_seat_from_device_path (ply_device_manager_t *manager, - const char *device_path) -{ - ply_list_node_t *node; - - node = ply_list_get_first_node (manager->seats); - while (node != NULL) { - ply_seat_t *seat; - ply_renderer_t *renderer; - ply_list_node_t *next_node; - const char *renderer_device_path; - - seat = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (manager->seats, node); - renderer = ply_seat_get_renderer (seat); - - if (renderer != NULL) { - renderer_device_path = ply_renderer_get_device_name (renderer); - - if (renderer_device_path != NULL) { - if (strcmp (device_path, renderer_device_path) == 0) { - ply_trace ("removing seat associated with %s", device_path); - - if (manager->seat_removed_handler != NULL) - manager->seat_removed_handler (manager->seat_event_handler_data, seat); - - ply_seat_free (seat); - ply_list_remove_node (manager->seats, node); - break; - } - } - } - - node = next_node; - } -} - -static void -free_seat_for_udev_device (ply_device_manager_t *manager, - struct udev_device *device) +free_devices_for_udev_device (ply_device_manager_t *manager, + struct udev_device *device) { const char *device_path; device_path = udev_device_get_devnode (device); if (device_path != NULL) - free_seat_from_device_path (manager, device_path); + free_devices_from_device_path (manager, device_path); } static bool -create_seats_for_subsystem (ply_device_manager_t *manager, - const char *subsystem) +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; - ply_trace ("creating seats for %s devices", + ply_trace ("creating objects for %s devices", strcmp (subsystem, SUBSYSTEM_FRAME_BUFFER) == 0 ? "frame buffer" : subsystem); @@ -326,7 +302,7 @@ create_seats_for_subsystem (ply_device_manager_t *manager, if (udev_device_get_is_initialized (device)) { ply_trace ("device is initialized"); - /* We only care about devices assigned to a (any) seat. Floating + /* We only care about devices assigned to a (any) devices. Floating * devices should be ignored. */ if (udev_device_has_tag (device, "seat")) { @@ -335,10 +311,10 @@ create_seats_for_subsystem (ply_device_manager_t *manager, if (node != NULL) { ply_trace ("found node %s", node); found_device = true; - create_seat_for_udev_device (manager, device); + create_devices_for_udev_device (manager, device); } } else { - ply_trace ("device doesn't have a seat tag"); + ply_trace ("device doesn't have a devices tag"); } } else { ply_trace ("it's not initialized"); @@ -371,17 +347,19 @@ on_udev_event (ply_device_manager_t *manager) if (strcmp (action, "add") == 0) { const char *subsystem; - bool coldplug_complete = manager->udev_queue_fd_watch == NULL; subsystem = udev_device_get_subsystem (device); - if (strcmp (subsystem, SUBSYSTEM_DRM) == 0 || - coldplug_complete) - create_seat_for_udev_device (manager, device); - else - ply_trace ("ignoring since we only handle subsystem %s devices after coldplug completes", subsystem); + if (strcmp (subsystem, SUBSYSTEM_DRM) == 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) { - free_seat_for_udev_device (manager, device); + free_devices_for_udev_device (manager, device); } udev_device_unref (device); @@ -413,30 +391,7 @@ watch_for_udev_events (ply_device_manager_t *manager) NULL, manager); } - -static void -free_seats (ply_device_manager_t *manager) -{ - ply_list_node_t *node; - - ply_trace ("removing seats"); - node = ply_list_get_first_node (manager->seats); - while (node != NULL) { - ply_seat_t *seat; - ply_list_node_t *next_node; - - seat = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (manager->seats, node); - - if (manager->seat_removed_handler != NULL) - manager->seat_removed_handler (manager->seat_event_handler_data, seat); - - ply_seat_free (seat); - ply_list_remove_node (manager->seats, node); - - node = next_node; - } -} +#endif static void free_terminal (char *device, @@ -473,6 +428,10 @@ get_terminal (ply_device_manager_t *manager, strcmp (full_name, "/dev/tty") == 0 || strcmp (full_name, ply_terminal_get_name (manager->local_console_terminal)) == 0) { terminal = manager->local_console_terminal; + + ply_hashtable_insert (manager->terminals, + (void *) ply_terminal_get_name (terminal), + terminal); goto done; } @@ -491,6 +450,23 @@ done: return terminal; } +static void +free_renderer (char *device_path, + ply_renderer_t *renderer, + ply_device_manager_t *manager) +{ + free_devices_from_device_path (manager, device_path); +} + +static void +free_renderers (ply_device_manager_t *manager) +{ + ply_hashtable_foreach (manager->renderers, + (ply_hashtable_foreach_func_t *) + free_renderer, + manager); +} + ply_device_manager_t * ply_device_manager_new (const char *default_tty, ply_device_manager_flags_t flags) @@ -500,15 +476,19 @@ ply_device_manager_new (const char *default_tty, manager = calloc (1, sizeof(ply_device_manager_t)); manager->loop = NULL; manager->terminals = ply_hashtable_new (ply_hashtable_string_hash, ply_hashtable_string_compare); + manager->renderers = ply_hashtable_new (ply_hashtable_string_hash, ply_hashtable_string_compare); manager->local_console_terminal = ply_terminal_new (default_tty); - ply_hashtable_insert (manager->terminals, - (void *) ply_terminal_get_name (manager->local_console_terminal), - manager->local_console_terminal); - manager->seats = ply_list_new (); + manager->keyboards = ply_list_new (); + manager->text_displays = ply_list_new (); + manager->pixel_displays = ply_list_new (); manager->flags = flags; +#ifdef HAVE_UDEV if (!(flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV)) manager->udev_context = udev_new (); +#else + manager->flags |= PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV; +#endif attach_to_event_loop (manager, ply_event_loop_get_default ()); @@ -527,17 +507,24 @@ ply_device_manager_free (ply_device_manager_t *manager) (ply_event_loop_exit_handler_t) detach_from_event_loop, manager); - free_seats (manager); - ply_list_free (manager->seats); free_terminals (manager); ply_hashtable_free (manager->terminals); + free_renderers (manager); + ply_hashtable_free (manager->renderers); + +#ifdef HAVE_UDEV + ply_event_loop_stop_watching_for_timeout (manager->loop, + (ply_event_loop_timeout_handler_t) + create_devices_from_udev, manager); + if (manager->udev_monitor != NULL) udev_monitor_unref (manager->udev_monitor); if (manager->udev_context != NULL) udev_unref (manager->udev_context); +#endif free (manager); } @@ -615,53 +602,161 @@ add_consoles_from_file (ply_device_manager_t *manager, } static void -create_seat_for_terminal_and_renderer_type (ply_device_manager_t *manager, - const char *device_path, - ply_terminal_t *terminal, - ply_renderer_type_t renderer_type) +create_pixel_displays_for_renderer (ply_device_manager_t *manager, + ply_renderer_t *renderer) { - ply_seat_t *seat; - bool is_local_terminal = false; + ply_list_t *heads; + ply_list_node_t *node; + + heads = ply_renderer_get_heads (renderer); - if (terminal != NULL && manager->local_console_terminal == terminal) - is_local_terminal = true; + ply_trace ("Adding displays for %d heads", + ply_list_get_length (heads)); + + node = ply_list_get_first_node (heads); + while (node != NULL) { + ply_list_node_t *next_node; + ply_renderer_head_t *head; + ply_pixel_display_t *display; + + head = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (heads, node); + + display = ply_pixel_display_new (renderer, head); + + ply_list_append_data (manager->pixel_displays, display); + + if (manager->pixel_display_added_handler != NULL) + manager->pixel_display_added_handler (manager->event_handler_data, display); + node = next_node; + } +} + +static void +create_text_displays_for_terminal (ply_device_manager_t *manager, + ply_terminal_t *terminal) +{ + ply_text_display_t *display; - if (is_local_terminal && manager->local_console_seat != NULL) { - ply_trace ("trying to create seat for local console when one already exists"); + if (!ply_terminal_is_open (terminal)) { + if (!ply_terminal_open (terminal)) { + ply_trace ("could not add terminal %s: %m", + ply_terminal_get_name (terminal)); + return; + } + } + + ply_trace ("adding text display for terminal %s", + ply_terminal_get_name (terminal)); + + display = ply_text_display_new (terminal); + ply_list_append_data (manager->text_displays, display); + + if (manager->text_display_added_handler != NULL) + manager->text_display_added_handler (manager->event_handler_data, display); +} + +static void +create_devices_for_terminal_and_renderer_type (ply_device_manager_t *manager, + const char *device_path, + ply_terminal_t *terminal, + ply_renderer_type_t renderer_type) +{ + ply_renderer_t *renderer = NULL; + ply_keyboard_t *keyboard = NULL; + + if (device_path != NULL) + renderer = ply_hashtable_lookup (manager->renderers, (void *) device_path); + + if (renderer != NULL) { + ply_trace ("ignoring device %s since it's already managed", device_path); return; } - ply_trace ("creating seat for %s (renderer type: %u) (terminal: %s)", + ply_trace ("creating devices for %s (renderer type: %u) (terminal: %s)", device_path ? : "", renderer_type, terminal ? ply_terminal_get_name (terminal) : "none"); - seat = ply_seat_new (terminal); - if (!ply_seat_open (seat, renderer_type, device_path)) { - ply_trace ("could not create seat"); - ply_seat_free (seat); - return; + if (renderer_type != PLY_RENDERER_TYPE_NONE) { + ply_renderer_t *old_renderer = NULL; + renderer = ply_renderer_new (renderer_type, device_path, terminal); + + if (renderer != NULL && !ply_renderer_open (renderer)) { + ply_trace ("could not open renderer for %s", device_path); + ply_renderer_free (renderer); + renderer = NULL; + + if (renderer_type != PLY_RENDERER_TYPE_AUTO) + return; + } + + if (renderer != NULL) { + old_renderer = ply_hashtable_lookup (manager->renderers, + (void *) ply_renderer_get_device_name (renderer)); + + if (old_renderer != NULL) { + ply_trace ("ignoring device %s since it's alerady managed", + ply_renderer_get_device_name (renderer)); + ply_renderer_free (renderer); + + renderer = NULL; + return; + } + } + } + + if (renderer != NULL) { + keyboard = ply_keyboard_new_for_renderer (renderer); + ply_list_append_data (manager->keyboards, keyboard); + + if (manager->keyboard_added_handler != NULL) + manager->keyboard_added_handler (manager->event_handler_data, keyboard); + + create_pixel_displays_for_renderer (manager, renderer); + ply_hashtable_insert (manager->renderers, strdup (ply_renderer_get_device_name (renderer)), renderer); + create_pixel_displays_for_renderer (manager, renderer); + + if (manager->renderers_activated) { + ply_trace ("activating renderer"); + ply_renderer_activate (renderer); + } + + if (terminal != NULL) + ply_terminal_refresh_geometry (terminal); + } else if (terminal != NULL) { + keyboard = ply_keyboard_new_for_terminal (terminal); + ply_list_append_data (manager->keyboards, keyboard); + + if (manager->keyboard_added_handler != NULL) + manager->keyboard_added_handler (manager->event_handler_data, keyboard); } - ply_list_append_data (manager->seats, seat); + if (terminal != NULL) { + create_text_displays_for_terminal (manager, terminal); - if (is_local_terminal) - manager->local_console_seat = seat; + if (terminal == manager->local_console_terminal) { + manager->local_console_is_text = renderer == NULL; + manager->local_console_managed = true; + } + } - if (manager->seat_added_handler != NULL) - manager->seat_added_handler (manager->seat_event_handler_data, seat); + if (keyboard != NULL && manager->keyboards_activated) { + ply_trace ("activating keyboards"); + ply_keyboard_watch_for_input (keyboard); + } } static void -create_seat_for_terminal (const char *device_path, - ply_terminal_t *terminal, - ply_device_manager_t *manager) +create_devices_for_terminal (const char *device_path, + ply_terminal_t *terminal, + ply_device_manager_t *manager) { - create_seat_for_terminal_and_renderer_type (manager, - device_path, - terminal, - PLY_RENDERER_TYPE_NONE); + create_devices_for_terminal_and_renderer_type (manager, + NULL, + terminal, + PLY_RENDERER_TYPE_NONE); } static bool -create_seats_from_terminals (ply_device_manager_t *manager) +create_devices_from_terminals (ply_device_manager_t *manager) { bool has_serial_consoles; @@ -676,9 +771,11 @@ create_seats_from_terminals (ply_device_manager_t *manager) if (has_serial_consoles) { ply_trace ("serial consoles detected, managing them with details forced"); + manager->serial_consoles_detected = true; + ply_hashtable_foreach (manager->terminals, (ply_hashtable_foreach_func_t *) - create_seat_for_terminal, + create_devices_for_terminal, manager); return true; } @@ -686,145 +783,104 @@ create_seats_from_terminals (ply_device_manager_t *manager) return false; } +#ifdef HAVE_UDEV static void -create_seats_from_udev (ply_device_manager_t *manager) +create_devices_from_udev (ply_device_manager_t *manager) { bool found_drm_device, found_fb_device; - ply_trace ("Looking for devices from udev"); + ply_trace ("Timeout elapsed, looking for devices from udev"); - found_drm_device = create_seats_for_subsystem (manager, SUBSYSTEM_DRM); - found_fb_device = create_seats_for_subsystem (manager, SUBSYSTEM_FRAME_BUFFER); + found_drm_device = create_devices_for_subsystem (manager, SUBSYSTEM_DRM); + found_fb_device = create_devices_for_subsystem (manager, SUBSYSTEM_FRAME_BUFFER); if (found_drm_device || found_fb_device) return; - ply_trace ("Creating non-graphical seat, since there's no suitable graphics hardware"); - create_seat_for_terminal_and_renderer_type (manager, - ply_terminal_get_name (manager->local_console_terminal), - manager->local_console_terminal, - PLY_RENDERER_TYPE_NONE); -} - -static void -create_fallback_seat (ply_device_manager_t *manager) -{ - create_seat_for_terminal_and_renderer_type (manager, - ply_terminal_get_name (manager->local_console_terminal), - manager->local_console_terminal, - PLY_RENDERER_TYPE_AUTO); + ply_trace ("Creating non-graphical devices, since there's no suitable graphics hardware"); + create_devices_for_terminal_and_renderer_type (manager, + NULL, + manager->local_console_terminal, + PLY_RENDERER_TYPE_NONE); } +#endif static void -on_udev_queue_changed (ply_device_manager_t *manager) +create_fallback_devices (ply_device_manager_t *manager) { - if (!udev_queue_get_queue_is_empty (manager->udev_queue)) - return; - - ply_trace ("udev coldplug complete"); - ply_event_loop_stop_watching_fd (manager->loop, manager->udev_queue_fd_watch); - manager->udev_queue_fd_watch = NULL; - udev_queue_unref (manager->udev_queue); - - close (manager->udev_queue_fd); - manager->udev_queue_fd = -1; - - manager->udev_queue = NULL; - - create_seats_from_udev (manager); -} - -static void -watch_for_coldplug_completion (ply_device_manager_t *manager) -{ - int fd; - int result; - - manager->udev_queue = udev_queue_new (manager->udev_context); - - if (udev_queue_get_queue_is_empty (manager->udev_queue)) { - ply_trace ("udev coldplug completed already "); - create_seats_from_udev (manager); - return; - } - - fd = inotify_init1 (IN_CLOEXEC); - result = inotify_add_watch (fd, "/run/udev", IN_MOVED_TO| IN_DELETE); - - if (result < 0) { - ply_trace ("could not watch for udev to show up: %m"); - close (fd); - - create_fallback_seat (manager); - return; - } - - manager->udev_queue_fd = fd; - - manager->udev_queue_fd_watch = ply_event_loop_watch_fd (manager->loop, - fd, - PLY_EVENT_LOOP_FD_STATUS_HAS_DATA, - (ply_event_handler_t) - on_udev_queue_changed, - NULL, - manager); + create_devices_for_terminal_and_renderer_type (manager, + NULL, + manager->local_console_terminal, + PLY_RENDERER_TYPE_AUTO); } void -ply_device_manager_watch_seats (ply_device_manager_t *manager, - ply_seat_added_handler_t seat_added_handler, - ply_seat_removed_handler_t seat_removed_handler, - void *data) -{ - bool done_with_initial_seat_setup; - - manager->seat_added_handler = seat_added_handler; - manager->seat_removed_handler = seat_removed_handler; - manager->seat_event_handler_data = data; - - /* Try to create seats for each serial device right away, if possible +ply_device_manager_watch_devices (ply_device_manager_t *manager, + double device_timeout, + ply_keyboard_added_handler_t keyboard_added_handler, + ply_keyboard_removed_handler_t keyboard_removed_handler, + ply_pixel_display_added_handler_t pixel_display_added_handler, + ply_pixel_display_removed_handler_t pixel_display_removed_handler, + ply_text_display_added_handler_t text_display_added_handler, + ply_text_display_removed_handler_t text_display_removed_handler, + void *data) +{ + bool done_with_initial_devices_setup; + + manager->keyboard_added_handler = keyboard_added_handler; + manager->keyboard_removed_handler = keyboard_removed_handler; + manager->pixel_display_added_handler = pixel_display_added_handler; + manager->pixel_display_removed_handler = pixel_display_removed_handler; + manager->text_display_added_handler = text_display_added_handler; + manager->text_display_removed_handler = text_display_removed_handler; + manager->event_handler_data = data; + + /* Try to create devices for each serial device right away, if possible */ - done_with_initial_seat_setup = create_seats_from_terminals (manager); + done_with_initial_devices_setup = create_devices_from_terminals (manager); - if (done_with_initial_seat_setup) + if (done_with_initial_devices_setup) return; if ((manager->flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV)) { - ply_trace ("udev support disabled, creating fallback seat"); - create_fallback_seat (manager); + ply_trace ("udev support disabled, creating fallback devices"); + create_fallback_devices (manager); return; } +#ifdef HAVE_UDEV watch_for_udev_events (manager); - watch_for_coldplug_completion (manager); + create_devices_for_subsystem (manager, SUBSYSTEM_DRM); + ply_event_loop_watch_for_timeout (manager->loop, + device_timeout, + (ply_event_loop_timeout_handler_t) + create_devices_from_udev, manager); +#endif } bool -ply_device_manager_has_open_seats (ply_device_manager_t *manager) +ply_device_manager_has_displays (ply_device_manager_t *manager) { - ply_list_node_t *node; - - node = ply_list_get_first_node (manager->seats); - while (node != NULL) { - ply_seat_t *seat; - ply_list_node_t *next_node; - - seat = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (manager->seats, node); - - if (ply_seat_is_open (seat)) - return true; + return ply_list_get_length (manager->pixel_displays) > 0 || + ply_list_get_length (manager->text_displays) > 0; +} - node = next_node; - } +ply_list_t * +ply_device_manager_get_keyboards (ply_device_manager_t *manager) +{ + return manager->keyboards; +} - return false; +ply_list_t * +ply_device_manager_get_pixel_displays (ply_device_manager_t *manager) +{ + return manager->pixel_displays; } ply_list_t * -ply_device_manager_get_seats (ply_device_manager_t *manager) +ply_device_manager_get_text_displays (ply_device_manager_t *manager) { - return manager->seats; + return manager->text_displays; } ply_terminal_t * @@ -833,44 +889,49 @@ ply_device_manager_get_default_terminal (ply_device_manager_t *manager) return manager->local_console_terminal; } +bool +ply_device_manager_has_serial_consoles (ply_device_manager_t *manager) +{ + return manager->serial_consoles_detected; +} + +static void +activate_renderer (char *device_path, + ply_renderer_t *renderer, + ply_device_manager_t *manager) +{ + ply_renderer_activate (renderer); +} + void ply_device_manager_activate_renderers (ply_device_manager_t *manager) { - ply_list_node_t *node; - ply_trace ("activating renderers"); - node = ply_list_get_first_node (manager->seats); - while (node != NULL) { - ply_seat_t *seat; - ply_list_node_t *next_node; - - seat = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (manager->seats, node); + ply_hashtable_foreach (manager->renderers, + (ply_hashtable_foreach_func_t *) + activate_renderer, + manager); - ply_seat_activate_renderer (seat); + manager->renderers_activated = true; +} - node = next_node; - } +static void +deactivate_renderer (char *device_path, + ply_renderer_t *renderer, + ply_device_manager_t *manager) +{ + ply_renderer_deactivate (renderer); } void ply_device_manager_deactivate_renderers (ply_device_manager_t *manager) { - ply_list_node_t *node; - - ply_trace ("deactivating renderers"); - node = ply_list_get_first_node (manager->seats); - while (node != NULL) { - ply_seat_t *seat; - ply_list_node_t *next_node; - - seat = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (manager->seats, node); - - ply_seat_deactivate_renderer (seat); + ply_hashtable_foreach (manager->renderers, + (ply_hashtable_foreach_func_t *) + deactivate_renderer, + manager); - node = next_node; - } + manager->renderers_activated = false; } void @@ -879,18 +940,20 @@ ply_device_manager_activate_keyboards (ply_device_manager_t *manager) ply_list_node_t *node; ply_trace ("activating keyboards"); - node = ply_list_get_first_node (manager->seats); + node = ply_list_get_first_node (manager->keyboards); while (node != NULL) { - ply_seat_t *seat; + ply_keyboard_t *keyboard; ply_list_node_t *next_node; - seat = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (manager->seats, node); + keyboard = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (manager->keyboards, node); - ply_seat_activate_keyboard (seat); + ply_keyboard_watch_for_input (keyboard); node = next_node; } + + manager->keyboards_activated = true; } void @@ -899,16 +962,18 @@ ply_device_manager_deactivate_keyboards (ply_device_manager_t *manager) ply_list_node_t *node; ply_trace ("deactivating keyboards"); - node = ply_list_get_first_node (manager->seats); + node = ply_list_get_first_node (manager->keyboards); while (node != NULL) { - ply_seat_t *seat; + ply_keyboard_t *keyboard; ply_list_node_t *next_node; - seat = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (manager->seats, node); + keyboard = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (manager->keyboards, node); - ply_seat_deactivate_keyboard (seat); + ply_keyboard_stop_watching_for_input (keyboard); node = next_node; } + + manager->keyboards_activated = false; } diff --git a/src/libply-splash-core/ply-device-manager.h b/src/libply-splash-core/ply-device-manager.h index c3e6487..058f6e8 100644 --- a/src/libply-splash-core/ply-device-manager.h +++ b/src/libply-splash-core/ply-device-manager.h @@ -21,7 +21,11 @@ #define PLY_DEVICE_MANAGER_H #include -#include "ply-seat.h" + +#include "ply-keyboard.h" +#include "ply-pixel-display.h" +#include "ply-renderer.h" +#include "ply-text-display.h" typedef enum { @@ -31,20 +35,30 @@ typedef enum } ply_device_manager_flags_t; typedef struct _ply_device_manager ply_device_manager_t; -typedef void (*ply_seat_added_handler_t) (void *, - ply_seat_t *); -typedef void (*ply_seat_removed_handler_t) (void *, - ply_seat_t *); +typedef void (* ply_keyboard_added_handler_t) (void *, ply_keyboard_t *); +typedef void (* ply_keyboard_removed_handler_t) (void *, ply_keyboard_t *); +typedef void (* ply_pixel_display_added_handler_t) (void *, ply_pixel_display_t *); +typedef void (* ply_pixel_display_removed_handler_t) (void *, ply_pixel_display_t *); +typedef void (* ply_text_display_added_handler_t) (void *, ply_text_display_t *); +typedef void (* ply_text_display_removed_handler_t) (void *, ply_text_display_t *); #ifndef PLY_HIDE_FUNCTION_DECLARATIONS ply_device_manager_t *ply_device_manager_new (const char *default_tty, ply_device_manager_flags_t flags); -void ply_device_manager_watch_seats (ply_device_manager_t *manager, - ply_seat_added_handler_t seat_added_handler, - ply_seat_removed_handler_t seat_removed_handler, - void *data); -bool ply_device_manager_has_open_seats (ply_device_manager_t *manager); -ply_list_t *ply_device_manager_get_seats (ply_device_manager_t *manager); +void ply_device_manager_watch_devices (ply_device_manager_t *manager, + double device_timeout, + ply_keyboard_added_handler_t keyboard_added_handler, + ply_keyboard_removed_handler_t keyboard_removed_handler, + ply_pixel_display_added_handler_t pixel_display_added_handler, + ply_pixel_display_removed_handler_t pixel_display_removed_handler, + ply_text_display_added_handler_t text_display_added_handler, + ply_text_display_removed_handler_t text_display_removed_handler, + void *data); +bool ply_device_manager_has_serial_consoles (ply_device_manager_t *manager); +bool ply_device_manager_has_displays (ply_device_manager_t *manager); +ply_list_t *ply_device_manager_get_keyboards (ply_device_manager_t *manager); +ply_list_t *ply_device_manager_get_pixel_displays (ply_device_manager_t *manager); +ply_list_t *ply_device_manager_get_text_displays (ply_device_manager_t *manager); void ply_device_manager_free (ply_device_manager_t *manager); void ply_device_manager_activate_keyboards (ply_device_manager_t *manager); void ply_device_manager_deactivate_keyboards (ply_device_manager_t *manager); diff --git a/src/libply-splash-core/ply-keyboard.c b/src/libply-splash-core/ply-keyboard.c index ccf08e8..80f7694 100644 --- a/src/libply-splash-core/ply-keyboard.c +++ b/src/libply-splash-core/ply-keyboard.c @@ -93,6 +93,8 @@ struct _ply_keyboard ply_list_t *backspace_handler_list; ply_list_t *escape_handler_list; ply_list_t *enter_handler_list; + + uint32_t is_active : 1; }; static bool ply_keyboard_watch_for_terminal_input (ply_keyboard_t *keyboard); @@ -323,6 +325,12 @@ ply_keyboard_stop_watching_for_renderer_input (ply_keyboard_t *keyboard) keyboard->provider.if_renderer->input_source); } +bool +ply_keyboard_is_active (ply_keyboard_t *keyboard) +{ + return keyboard->is_active; +} + static void on_terminal_data (ply_keyboard_t *keyboard) { @@ -369,15 +377,20 @@ ply_keyboard_watch_for_input (ply_keyboard_t *keyboard) { assert (keyboard != NULL); + if (keyboard->is_active) + return true; + switch (keyboard->provider_type) { case PLY_KEYBOARD_PROVIDER_TYPE_RENDERER: - return ply_keyboard_watch_for_renderer_input (keyboard); + keyboard->is_active = ply_keyboard_watch_for_renderer_input (keyboard); + break; case PLY_KEYBOARD_PROVIDER_TYPE_TERMINAL: - return ply_keyboard_watch_for_terminal_input (keyboard); + keyboard->is_active = ply_keyboard_watch_for_terminal_input (keyboard); + break; } - return false; + return keyboard->is_active; } void @@ -385,6 +398,9 @@ ply_keyboard_stop_watching_for_input (ply_keyboard_t *keyboard) { assert (keyboard != NULL); + if (!keyboard->is_active) + return; + switch (keyboard->provider_type) { case PLY_KEYBOARD_PROVIDER_TYPE_RENDERER: ply_keyboard_stop_watching_for_renderer_input (keyboard); @@ -394,6 +410,8 @@ ply_keyboard_stop_watching_for_input (ply_keyboard_t *keyboard) ply_keyboard_stop_watching_for_terminal_input (keyboard); break; } + + keyboard->is_active = false; } void diff --git a/src/libply-splash-core/ply-keyboard.h b/src/libply-splash-core/ply-keyboard.h index 23497d9..6147cc7 100644 --- a/src/libply-splash-core/ply-keyboard.h +++ b/src/libply-splash-core/ply-keyboard.h @@ -71,6 +71,7 @@ void ply_keyboard_remove_enter_handler (ply_keyboard_t *keyboard, bool ply_keyboard_watch_for_input (ply_keyboard_t *keyboard); void ply_keyboard_stop_watching_for_input (ply_keyboard_t *keyboard); +bool ply_keyboard_is_active (ply_keyboard_t *keyboard); #endif diff --git a/src/libply-splash-core/ply-pixel-buffer.c b/src/libply-splash-core/ply-pixel-buffer.c index c1825cc..52a3f86 100644 --- a/src/libply-splash-core/ply-pixel-buffer.c +++ b/src/libply-splash-core/ply-pixel-buffer.c @@ -37,14 +37,19 @@ #include #include +#define ALPHA_MASK 0xff000000 + struct _ply_pixel_buffer { uint32_t *bytes; - ply_rectangle_t area; - ply_list_t *clip_areas; + ply_rectangle_t area; /* in device pixels */ + ply_rectangle_t logical_area; /* in logical pixels */ + ply_list_t *clip_areas; /* in device pixels */ - ply_region_t *updated_areas; + ply_region_t *updated_areas; /* in device pixels */ + uint32_t is_opaque : 1; + int device_scale; }; static inline void ply_pixel_buffer_blend_value_at_pixel (ply_pixel_buffer_t *buffer, @@ -166,6 +171,34 @@ ply_pixel_buffer_blend_value_at_pixel (ply_pixel_buffer_t *buffer, } static void +ply_rectangle_upscale (ply_rectangle_t *area, + int scale) +{ + area->x *= scale; + area->y *= scale; + area->width *= scale; + area->height *= scale; +} + +static void +ply_rectangle_downscale (ply_rectangle_t *area, + int scale) +{ + area->x /= scale; + area->y /= scale; + area->width /= scale; + area->height /= scale; +} + +static void +ply_pixel_buffer_adjust_area_for_device_scale (ply_pixel_buffer_t *buffer, + ply_rectangle_t *area) +{ + ply_rectangle_upscale (area, buffer->device_scale); +} + +/* this function will also convert logical pixels to device pixels */ +static void ply_pixel_buffer_crop_area_to_clip_area (ply_pixel_buffer_t *buffer, ply_rectangle_t *area, ply_rectangle_t *cropped_area) @@ -173,6 +206,7 @@ ply_pixel_buffer_crop_area_to_clip_area (ply_pixel_buffer_t *buffer, ply_list_node_t *node; *cropped_area = *area; + ply_pixel_buffer_adjust_area_for_device_scale (buffer, cropped_area); node = ply_list_get_first_node (buffer->clip_areas); while (node != NULL) { @@ -196,8 +230,19 @@ ply_pixel_buffer_fill_area_with_pixel_value (ply_pixel_buffer_t *buffer, unsigned long row, column; ply_rectangle_t cropped_area; + if (fill_area == NULL) + fill_area = &buffer->logical_area; + ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area); + /* If we're filling the entire buffer with a fully opaque color, + * then make note of it + */ + if (fill_area == &buffer->area && + (pixel_value >> 24) == 0xff) { + buffer->is_opaque = true; + } + for (row = cropped_area.y; row < cropped_area.y + cropped_area.height; row++) { for (column = cropped_area.x; column < cropped_area.x + cropped_area.width; column++) { ply_pixel_buffer_blend_value_at_pixel (buffer, @@ -205,6 +250,8 @@ ply_pixel_buffer_fill_area_with_pixel_value (ply_pixel_buffer_t *buffer, pixel_value); } } + + ply_region_add_rectangle (buffer->updated_areas, &cropped_area); } void @@ -216,6 +263,8 @@ ply_pixel_buffer_push_clip_area (ply_pixel_buffer_t *buffer, new_clip_area = malloc (sizeof(*new_clip_area)); *new_clip_area = *clip_area; + ply_pixel_buffer_adjust_area_for_device_scale (buffer, new_clip_area); + ply_list_append_data (buffer->clip_areas, new_clip_area); } @@ -241,9 +290,12 @@ ply_pixel_buffer_new (unsigned long width, buffer->bytes = (uint32_t *) calloc (height, width * sizeof(uint32_t)); buffer->area.width = width; buffer->area.height = height; + buffer->logical_area = buffer->area; + buffer->device_scale = 1; buffer->clip_areas = ply_list_new (); ply_pixel_buffer_push_clip_area (buffer, &buffer->area); + buffer->is_opaque = false; return buffer; } @@ -278,21 +330,36 @@ ply_pixel_buffer_get_size (ply_pixel_buffer_t *buffer, assert (buffer != NULL); assert (size != NULL); - *size = buffer->area; + *size = buffer->logical_area; } unsigned long ply_pixel_buffer_get_width (ply_pixel_buffer_t *buffer) { assert (buffer != NULL); - return buffer->area.width; + return buffer->logical_area.width; } unsigned long ply_pixel_buffer_get_height (ply_pixel_buffer_t *buffer) { assert (buffer != NULL); - return buffer->area.height; + return buffer->logical_area.height; +} + +bool +ply_pixel_buffer_is_opaque (ply_pixel_buffer_t *buffer) +{ + assert (buffer != NULL); + return buffer->is_opaque; +} + +void +ply_pixel_buffer_set_opaque (ply_pixel_buffer_t *buffer, + bool is_opaque) +{ + assert (buffer != NULL); + buffer->is_opaque = is_opaque; } ply_region_t * @@ -359,7 +426,7 @@ ply_pixel_buffer_fill_with_gradient (ply_pixel_buffer_t *buffer, ply_rectangle_t cropped_area; if (fill_area == NULL) - fill_area = &buffer->area; + fill_area = &buffer->logical_area; ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area); @@ -430,24 +497,16 @@ ply_pixel_buffer_fill_with_color (ply_pixel_buffer_t *buffer, double alpha) { uint32_t pixel_value; - ply_rectangle_t cropped_area; assert (buffer != NULL); - if (fill_area == NULL) - fill_area = &buffer->area; - - ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area); - red *= alpha; green *= alpha; blue *= alpha; pixel_value = PLY_PIXEL_BUFFER_COLOR_TO_PIXEL_VALUE (red, green, blue, alpha); - ply_pixel_buffer_fill_area_with_pixel_value (buffer, &cropped_area, pixel_value); - - ply_region_add_rectangle (buffer->updated_areas, &cropped_area); + ply_pixel_buffer_fill_area_with_pixel_value (buffer, fill_area, pixel_value); } void @@ -456,7 +515,6 @@ ply_pixel_buffer_fill_with_hex_color_at_opacity (ply_pixel_buffer_t *buffer, uint32_t hex_color, double opacity) { - ply_rectangle_t cropped_area; uint32_t pixel_value; double red; double green; @@ -465,11 +523,6 @@ ply_pixel_buffer_fill_with_hex_color_at_opacity (ply_pixel_buffer_t *buffer, assert (buffer != NULL); - if (fill_area == NULL) - fill_area = &buffer->area; - - ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area); - /* if they only gave an rgb hex number, assume an alpha of 0xff */ if ((hex_color & 0xff000000) == 0) @@ -488,9 +541,7 @@ ply_pixel_buffer_fill_with_hex_color_at_opacity (ply_pixel_buffer_t *buffer, pixel_value = PLY_PIXEL_BUFFER_COLOR_TO_PIXEL_VALUE (red, green, blue, alpha); - ply_pixel_buffer_fill_area_with_pixel_value (buffer, &cropped_area, pixel_value); - - ply_region_add_rectangle (buffer->updated_areas, &cropped_area); + ply_pixel_buffer_fill_area_with_pixel_value (buffer, fill_area, pixel_value); } void @@ -502,48 +553,120 @@ ply_pixel_buffer_fill_with_hex_color (ply_pixel_buffer_t *buffer, hex_color, 1.0); } +static inline uint32_t +ply_pixels_interpolate (uint32_t *bytes, + int width, + int height, + double x, + double y) +{ + int ix; + int iy; + int i; + int offset_x; + int offset_y; + uint32_t pixels[2][2]; + uint32_t reply = 0; + + for (offset_y = 0; offset_y < 2; offset_y++) { + for (offset_x = 0; offset_x < 2; offset_x++) { + ix = x + offset_x; + iy = y + offset_y; + + if (ix < 0 || ix >= width || iy < 0 || iy >= height) + pixels[offset_y][offset_x] = 0x00000000; + else + pixels[offset_y][offset_x] = bytes[ix + iy * width]; + } + } + if (!pixels[0][0] && !pixels[0][1] && !pixels[1][0] && !pixels[1][1]) return 0; + + ix = x; + iy = y; + x -= ix; + y -= iy; + for (i = 0; i < 4; i++) { + uint32_t value = 0; + uint32_t mask = 0xFF << (i * 8); + value += ((pixels[0][0]) & mask) * (1 - x) * (1 - y); + value += ((pixels[0][1]) & mask) * x * (1 - y); + value += ((pixels[1][0]) & mask) * (1 - x) * y; + value += ((pixels[1][1]) & mask) * x * y; + reply |= value & mask; + } + return reply; +} + void -ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_pixel_buffer_t *buffer, - ply_rectangle_t *fill_area, - ply_rectangle_t *clip_area, - uint32_t *data, - double opacity) +ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + ply_rectangle_t *clip_area, + uint32_t *data, + double opacity, + int scale) { unsigned long row, column; uint8_t opacity_as_byte; + ply_rectangle_t logical_fill_area; ply_rectangle_t cropped_area; unsigned long x; unsigned long y; + double scale_factor; assert (buffer != NULL); - if (fill_area == NULL) - fill_area = &buffer->area; + if (fill_area == NULL) { + fill_area = &buffer->logical_area; + logical_fill_area = buffer->logical_area; + } else { + logical_fill_area = *fill_area; + ply_rectangle_downscale (&logical_fill_area, scale); + } - ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area); + ply_pixel_buffer_crop_area_to_clip_area (buffer, &logical_fill_area, &cropped_area); + + if (clip_area) { + ply_rectangle_t device_clip_area; - if (clip_area) - ply_rectangle_intersect (&cropped_area, clip_area, &cropped_area); + device_clip_area = *clip_area; + ply_rectangle_downscale (&device_clip_area, scale); + ply_pixel_buffer_adjust_area_for_device_scale (buffer, &device_clip_area); + ply_rectangle_intersect (&cropped_area, &device_clip_area, &cropped_area); + } if (cropped_area.width == 0 || cropped_area.height == 0) return; - x = cropped_area.x - fill_area->x; - y = cropped_area.y - fill_area->y; opacity_as_byte = (uint8_t) (opacity * 255.0); + scale_factor = (double)scale / buffer->device_scale; + x = cropped_area.x; + y = cropped_area.y; + /* column, row are the point we want to write into, in + pixel_buffer coordinate space (device pixels) + + scale_factor * (column - fill_area->x), scale_factor * (row - fill_area->y) + is the point we want to source from, in the data coordinate + space */ for (row = y; row < y + cropped_area.height; row++) { for (column = x; column < x + cropped_area.width; column++) { uint32_t pixel_value; - pixel_value = data[fill_area->width * row + column]; + if (buffer->device_scale == scale) + pixel_value = data[fill_area->width * (row - fill_area->y) + + column - fill_area->x]; + else + pixel_value = ply_pixels_interpolate (data, + fill_area->width, + fill_area->height, + scale_factor * column - fill_area->x, + scale_factor * row - fill_area->y); if ((pixel_value >> 24) == 0x00) continue; pixel_value = make_pixel_value_translucent (pixel_value, opacity_as_byte); ply_pixel_buffer_blend_value_at_pixel (buffer, - cropped_area.x + (column - x), - cropped_area.y + (row - y), + column, row, pixel_value); } } @@ -552,15 +675,30 @@ ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_pixel_buffer_t } void +ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + ply_rectangle_t *clip_area, + uint32_t *data, + double opacity) +{ + ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (buffer, + fill_area, + clip_area, + data, + opacity, + 1); +} + +void ply_pixel_buffer_fill_with_argb32_data_at_opacity (ply_pixel_buffer_t *buffer, ply_rectangle_t *fill_area, uint32_t *data, double opacity) { - ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer, - fill_area, - NULL, - data, opacity); + ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (buffer, + fill_area, + NULL, + data, opacity, 1); } void @@ -568,10 +706,10 @@ ply_pixel_buffer_fill_with_argb32_data (ply_pixel_buffer_t *buffer, ply_rectangle_t *fill_area, uint32_t *data) { - ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer, - fill_area, - NULL, - data, 1.0); + ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (buffer, + fill_area, + NULL, + data, 1.0, 1); } void @@ -580,10 +718,25 @@ ply_pixel_buffer_fill_with_argb32_data_with_clip (ply_pixel_buffer_t *buffer, ply_rectangle_t *clip_area, uint32_t *data) { - ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer, - fill_area, - clip_area, - data, 1.0); + ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (buffer, + fill_area, + clip_area, + data, 1.0, 1); +} + +static void +ply_pixel_buffer_copy_area (ply_pixel_buffer_t *canvas, + ply_pixel_buffer_t *source, + int x, int y, + ply_rectangle_t *cropped_area) +{ + unsigned long row; + + for (row = y; row < y + cropped_area->height; row++) { + memcpy (canvas->bytes + (cropped_area->y + row - y) * canvas->area.width + cropped_area->x, + source->bytes + (row * source->area.width) + x, + cropped_area->width * 4); + } } void @@ -594,51 +747,51 @@ ply_pixel_buffer_fill_with_buffer_at_opacity_with_clip (ply_pixel_buffer_t *canv ply_rectangle_t *clip_area, float opacity) { - unsigned long row, column; - uint8_t opacity_as_byte; - ply_rectangle_t cropped_area; + ply_rectangle_t fill_area; unsigned long x; unsigned long y; assert (canvas != NULL); assert (source != NULL); - cropped_area.x = x_offset; - cropped_area.y = y_offset; - cropped_area.width = source->area.width; - cropped_area.height = source->area.height; + /* Fast path to memcpy if we need no blending or scaling */ + if (opacity == 1.0 && ply_pixel_buffer_is_opaque (source) && + canvas->device_scale == source->device_scale) { + ply_rectangle_t cropped_area; - ply_pixel_buffer_crop_area_to_clip_area (canvas, &cropped_area, &cropped_area); + cropped_area.x = x_offset; + cropped_area.y = y_offset; + cropped_area.width = source->logical_area.width; + cropped_area.height = source->logical_area.height; - if (clip_area) - ply_rectangle_intersect (&cropped_area, clip_area, &cropped_area); + ply_pixel_buffer_crop_area_to_clip_area (canvas, &cropped_area, &cropped_area); - if (cropped_area.width == 0 || cropped_area.height == 0) - return; - - x = cropped_area.x - x_offset; - y = cropped_area.y - y_offset; - opacity_as_byte = (uint8_t) (opacity * 255.0); - - for (row = y; row < y + cropped_area.height; row++) { - for (column = x; column < x + cropped_area.width; column++) { - uint32_t pixel_value; + /* clip_area is in source device pixels, which are also canvas device pixels */ + if (clip_area) + ply_rectangle_intersect (&cropped_area, clip_area, &cropped_area); - pixel_value = source->bytes[row * source->area.width + column]; + if (cropped_area.width == 0 || cropped_area.height == 0) + return; - pixel_value = make_pixel_value_translucent (pixel_value, opacity_as_byte); + x = cropped_area.x - x_offset; + y = cropped_area.y - y_offset; - if ((pixel_value >> 24) == 0x00) - continue; + ply_pixel_buffer_copy_area (canvas, source, x, y, &cropped_area); - ply_pixel_buffer_blend_value_at_pixel (canvas, - cropped_area.x + (column - x), - cropped_area.y + (row - y), - pixel_value); - } + ply_region_add_rectangle (canvas->updated_areas, &cropped_area); + } else { + fill_area.x = x_offset * source->device_scale; + fill_area.y = y_offset * source->device_scale; + fill_area.width = source->area.width; + fill_area.height = source->area.height; + + ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (canvas, + &fill_area, + clip_area, + source->bytes, + opacity, + source->device_scale); } - - ply_region_add_rectangle (canvas->updated_areas, &cropped_area); } void @@ -696,52 +849,15 @@ ply_pixel_buffer_interpolate (ply_pixel_buffer_t *buffer, double x, double y) { - int ix; - int iy; int width; int height; - - int i; - - int offset_x; - int offset_y; - uint32_t pixels[2][2]; - uint32_t reply = 0; uint32_t *bytes; width = buffer->area.width; height = buffer->area.height; - - bytes = ply_pixel_buffer_get_argb32_data (buffer); - for (offset_y = 0; offset_y < 2; offset_y++) { - for (offset_x = 0; offset_x < 2; offset_x++) { - ix = x + offset_x; - iy = y + offset_y; - - if (ix < 0 || ix >= width || iy < 0 || iy >= height) - pixels[offset_y][offset_x] = 0x00000000; - else - pixels[offset_y][offset_x] = bytes[ix + iy * width]; - } - } - if (!pixels[0][0] && !pixels[0][1] && !pixels[1][0] && !pixels[1][1]) return 0; - - ix = x; - iy = y; - x -= ix; - y -= iy; - for (i = 0; i < 4; i++) { - uint32_t value = 0; - uint32_t mask = 0xFF << (i * 8); - value += ((pixels[0][0]) & mask) * (1 - x) * (1 - y); - value += ((pixels[0][1]) & mask) * x * (1 - y); - value += ((pixels[1][0]) & mask) * (1 - x) * y; - value += ((pixels[1][1]) & mask) * x * y; - reply |= value & mask; - } - return reply; + return ply_pixels_interpolate (bytes, width, height, x, y); } ply_pixel_buffer_t * @@ -753,7 +869,7 @@ ply_pixel_buffer_resize (ply_pixel_buffer_t *old_buffer, int x, y; double old_x, old_y; int old_width, old_height; - float scale_x, scale_y; + double scale_x, scale_y; uint32_t *bytes; buffer = ply_pixel_buffer_new (width, height); @@ -852,4 +968,20 @@ ply_pixel_buffer_tile (ply_pixel_buffer_t *old_buffer, return buffer; } +int +ply_pixel_buffer_get_device_scale (ply_pixel_buffer_t *buffer) +{ + return buffer->device_scale; +} + +void +ply_pixel_buffer_set_device_scale (ply_pixel_buffer_t *buffer, + int scale) +{ + buffer->device_scale = scale; + + buffer->logical_area.width = buffer->area.width / scale; + buffer->logical_area.height = buffer->area.height / scale; +} + /* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ diff --git a/src/libply-splash-core/ply-pixel-buffer.h b/src/libply-splash-core/ply-pixel-buffer.h index 7848a98..595e9bd 100644 --- a/src/libply-splash-core/ply-pixel-buffer.h +++ b/src/libply-splash-core/ply-pixel-buffer.h @@ -43,10 +43,17 @@ ply_pixel_buffer_t *ply_pixel_buffer_new (unsigned long width, void ply_pixel_buffer_free (ply_pixel_buffer_t *buffer); void ply_pixel_buffer_get_size (ply_pixel_buffer_t *buffer, ply_rectangle_t *size); +int ply_pixel_buffer_get_device_scale (ply_pixel_buffer_t *buffer); +void ply_pixel_buffer_set_device_scale (ply_pixel_buffer_t *buffer, + int scale); unsigned long ply_pixel_buffer_get_width (ply_pixel_buffer_t *buffer); unsigned long ply_pixel_buffer_get_height (ply_pixel_buffer_t *buffer); +bool ply_pixel_buffer_is_opaque (ply_pixel_buffer_t *buffer); +void ply_pixel_buffer_set_opaque (ply_pixel_buffer_t *buffer, + bool is_opaque); + ply_region_t *ply_pixel_buffer_get_updated_areas (ply_pixel_buffer_t *buffer); void ply_pixel_buffer_fill_with_color (ply_pixel_buffer_t *buffer, @@ -86,6 +93,12 @@ void ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_pixel_buff ply_rectangle_t *clip_area, uint32_t *data, double opacity); +void ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + ply_rectangle_t *clip_area, + uint32_t *data, + double opacity, + int scale); void ply_pixel_buffer_fill_with_buffer_at_opacity_with_clip (ply_pixel_buffer_t *canvas, ply_pixel_buffer_t *source, diff --git a/src/libply-splash-core/ply-pixel-display.c b/src/libply-splash-core/ply-pixel-display.c index b061bfc..cb01a2c 100644 --- a/src/libply-splash-core/ply-pixel-display.c +++ b/src/libply-splash-core/ply-pixel-display.c @@ -81,6 +81,18 @@ ply_pixel_display_new (ply_renderer_t *renderer, return display; } +ply_renderer_t * +ply_pixel_display_get_renderer (ply_pixel_display_t *display) +{ + return display->renderer; +} + +ply_renderer_head_t * +ply_pixel_display_get_renderer_head (ply_pixel_display_t *display) +{ + return display->head; +} + unsigned long ply_pixel_display_get_width (ply_pixel_display_t *display) { diff --git a/src/libply-splash-core/ply-pixel-display.h b/src/libply-splash-core/ply-pixel-display.h index 62a36da..675c181 100644 --- a/src/libply-splash-core/ply-pixel-display.h +++ b/src/libply-splash-core/ply-pixel-display.h @@ -46,6 +46,9 @@ ply_pixel_display_t *ply_pixel_display_new (ply_renderer_t *renderer, void ply_pixel_display_free (ply_pixel_display_t *display); +ply_renderer_t *ply_pixel_display_get_renderer (ply_pixel_display_t *display); +ply_renderer_head_t *ply_pixel_display_get_renderer_head (ply_pixel_display_t *display); + unsigned long ply_pixel_display_get_width (ply_pixel_display_t *display); unsigned long ply_pixel_display_get_height (ply_pixel_display_t *display); diff --git a/src/libply-splash-core/ply-renderer-plugin.h b/src/libply-splash-core/ply-renderer-plugin.h index 82ef913..f1455d3 100644 --- a/src/libply-splash-core/ply-renderer-plugin.h +++ b/src/libply-splash-core/ply-renderer-plugin.h @@ -66,6 +66,8 @@ typedef struct void (*close_input_source)(ply_renderer_backend_t *backend, ply_renderer_input_source_t *input_source); + + const char * (*get_device_name)(ply_renderer_backend_t *backend); } ply_renderer_plugin_interface_t; #endif /* PLY_RENDERER_PLUGIN_H */ diff --git a/src/libply-splash-core/ply-renderer.c b/src/libply-splash-core/ply-renderer.c index f64eac5..b9059ef 100644 --- a/src/libply-splash-core/ply-renderer.c +++ b/src/libply-splash-core/ply-renderer.c @@ -55,6 +55,7 @@ struct _ply_renderer uint32_t input_source_is_open : 1; uint32_t is_mapped : 1; + uint32_t is_active : 1; }; typedef const ply_renderer_plugin_interface_t * @@ -154,6 +155,11 @@ ply_renderer_load_plugin (ply_renderer_t *renderer, return false; } + if (renderer->plugin_interface->get_device_name != NULL) { + free (renderer->device_name); + renderer->device_name = strdup (renderer->plugin_interface->get_device_name (renderer->backend)); + } + return true; } @@ -268,15 +274,19 @@ ply_renderer_open (ply_renderer_t *renderer) { PLY_RENDERER_TYPE_NONE, NULL } }; + renderer->is_active = false; 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)) - return true; + if (ply_renderer_open_plugin (renderer, known_plugins[i].path)) { + renderer->is_active = true; + goto out; + } } ply_trace ("could not find suitable rendering plugin"); - return false; +out: + return renderer->is_active; } void @@ -284,6 +294,7 @@ ply_renderer_close (ply_renderer_t *renderer) { ply_renderer_unmap_from_device (renderer); ply_renderer_close_device (renderer); + renderer->is_active = false; } void @@ -291,7 +302,11 @@ ply_renderer_activate (ply_renderer_t *renderer) { assert (renderer->plugin_interface != NULL); - return renderer->plugin_interface->activate (renderer->backend); + if (renderer->is_active) + return; + + renderer->plugin_interface->activate (renderer->backend); + renderer->is_active = true; } void @@ -302,6 +317,12 @@ ply_renderer_deactivate (ply_renderer_t *renderer) return renderer->plugin_interface->deactivate (renderer->backend); } +bool +ply_renderer_is_active (ply_renderer_t *renderer) +{ + return renderer->is_active; +} + ply_list_t * ply_renderer_get_heads (ply_renderer_t *renderer) { diff --git a/src/libply-splash-core/ply-renderer.h b/src/libply-splash-core/ply-renderer.h index a019a4d..59391e1 100644 --- a/src/libply-splash-core/ply-renderer.h +++ b/src/libply-splash-core/ply-renderer.h @@ -57,6 +57,7 @@ bool ply_renderer_open (ply_renderer_t *renderer); void ply_renderer_close (ply_renderer_t *renderer); 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_list_t *ply_renderer_get_heads (ply_renderer_t *renderer); ply_pixel_buffer_t *ply_renderer_get_buffer_for_head (ply_renderer_t *renderer, diff --git a/src/libply-splash-core/ply-seat.c b/src/libply-splash-core/ply-seat.c deleted file mode 100644 index 700332f..0000000 --- a/src/libply-splash-core/ply-seat.c +++ /dev/null @@ -1,381 +0,0 @@ -/* ply-seat.c - APIs for encapsulating a keyboard and one or more displays - * - * Copyright (C) 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: Ray Strode - */ -#include "config.h" -#include "ply-seat.h" - -#include -#include -#include -#include -#include -#include - -#include "ply-boot-splash.h" -#include "ply-event-loop.h" -#include "ply-keyboard.h" -#include "ply-pixel-display.h" -#include "ply-text-display.h" -#include "ply-list.h" -#include "ply-logger.h" -#include "ply-utils.h" - -struct _ply_seat -{ - ply_event_loop_t *loop; - - ply_boot_splash_t *splash; - ply_terminal_t *terminal; - ply_renderer_t *renderer; - ply_keyboard_t *keyboard; - ply_list_t *text_displays; - ply_list_t *pixel_displays; - - uint32_t renderer_active : 1; - uint32_t keyboard_active : 1; -}; - -ply_seat_t * -ply_seat_new (ply_terminal_t *terminal) -{ - ply_seat_t *seat; - - seat = calloc (1, sizeof(ply_seat_t)); - - seat->loop = ply_event_loop_get_default (); - seat->terminal = terminal; - seat->text_displays = ply_list_new (); - seat->pixel_displays = ply_list_new (); - - return seat; -} - -static void -add_pixel_displays (ply_seat_t *seat) -{ - ply_list_t *heads; - ply_list_node_t *node; - - heads = ply_renderer_get_heads (seat->renderer); - - ply_trace ("Adding displays for %d heads", - ply_list_get_length (heads)); - - node = ply_list_get_first_node (heads); - while (node != NULL) { - ply_list_node_t *next_node; - ply_renderer_head_t *head; - ply_pixel_display_t *display; - - head = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (heads, node); - - display = ply_pixel_display_new (seat->renderer, head); - - ply_list_append_data (seat->pixel_displays, display); - - node = next_node; - } -} - -static void -add_text_displays (ply_seat_t *seat) -{ - ply_text_display_t *display; - - if (!ply_terminal_is_open (seat->terminal)) { - if (!ply_terminal_open (seat->terminal)) { - ply_trace ("could not add terminal %s: %m", - ply_terminal_get_name (seat->terminal)); - return; - } - } - - ply_trace ("adding text display for terminal %s", - ply_terminal_get_name (seat->terminal)); - - display = ply_text_display_new (seat->terminal); - ply_list_append_data (seat->text_displays, display); -} - -bool -ply_seat_open (ply_seat_t *seat, - ply_renderer_type_t renderer_type, - const char *device) -{ - if (renderer_type != PLY_RENDERER_TYPE_NONE) { - ply_renderer_t *renderer; - - renderer = ply_renderer_new (renderer_type, device, seat->terminal); - - if (!ply_renderer_open (renderer)) { - ply_trace ("could not open renderer for %s", device); - ply_renderer_free (renderer); - - seat->renderer = NULL; - seat->renderer_active = false; - - if (renderer_type != PLY_RENDERER_TYPE_AUTO) - return false; - } else { - seat->renderer = renderer; - seat->renderer_active = true; - } - } - - if (seat->renderer != NULL) { - seat->keyboard = ply_keyboard_new_for_renderer (seat->renderer); - add_pixel_displays (seat); - } else if (seat->terminal != NULL) { - seat->keyboard = ply_keyboard_new_for_terminal (seat->terminal); - } - - if (seat->terminal != NULL) { - add_text_displays (seat); - } else { - ply_trace ("not adding text display for seat, since seat has no associated terminal"); - } - - if (seat->keyboard != NULL) { - ply_keyboard_watch_for_input (seat->keyboard); - seat->keyboard_active = true; - } else { - ply_trace ("not watching seat for input"); - } - - return true; -} - -bool -ply_seat_is_open (ply_seat_t *seat) -{ - return ply_list_get_length (seat->pixel_displays) > 0 || - ply_list_get_length (seat->text_displays) > 0; -} - -void -ply_seat_deactivate_keyboard (ply_seat_t *seat) -{ - if (!seat->keyboard_active) - return; - - seat->keyboard_active = false; - - if (seat->keyboard == NULL) - return; - - ply_trace ("deactivating keyboard"); - ply_keyboard_stop_watching_for_input (seat->keyboard); -} - -void -ply_seat_deactivate_renderer (ply_seat_t *seat) -{ - if (!seat->renderer_active) - return; - - seat->renderer_active = false; - - if (seat->renderer == NULL) - return; - - ply_trace ("deactivating renderer"); - ply_renderer_deactivate (seat->renderer); -} - -void -ply_seat_activate_keyboard (ply_seat_t *seat) -{ - if (seat->keyboard_active) - return; - - if (seat->keyboard == NULL) - return; - - ply_trace ("activating keyboard"); - ply_keyboard_watch_for_input (seat->keyboard); - - seat->keyboard_active = true; -} - -void -ply_seat_activate_renderer (ply_seat_t *seat) -{ - if (seat->renderer_active) - return; - - if (seat->renderer == NULL) - return; - - ply_trace ("activating renderer"); - ply_renderer_activate (seat->renderer); - - seat->renderer_active = true; -} - -void -ply_seat_refresh_displays (ply_seat_t *seat) -{ - ply_list_node_t *node; - - node = ply_list_get_first_node (seat->pixel_displays); - while (node != NULL) { - ply_pixel_display_t *display; - ply_list_node_t *next_node; - unsigned long width, height; - - display = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (seat->pixel_displays, node); - - width = ply_pixel_display_get_width (display); - height = ply_pixel_display_get_height (display); - - ply_pixel_display_draw_area (display, 0, 0, width, height); - node = next_node; - } - - node = ply_list_get_first_node (seat->text_displays); - while (node != NULL) { - ply_text_display_t *display; - ply_list_node_t *next_node; - int number_of_columns, number_of_rows; - - display = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (seat->text_displays, node); - - number_of_columns = ply_text_display_get_number_of_columns (display); - number_of_rows = ply_text_display_get_number_of_rows (display); - - ply_text_display_draw_area (display, 0, 0, - number_of_columns, - number_of_rows); - node = next_node; - } -} - -void -ply_seat_close (ply_seat_t *seat) -{ - if (seat->renderer == NULL) - return; - - ply_trace ("destroying renderer"); - ply_renderer_close (seat->renderer); - ply_renderer_free (seat->renderer); - seat->renderer = NULL; -} - -void -ply_seat_set_splash (ply_seat_t *seat, - ply_boot_splash_t *splash) -{ - if (seat->splash == splash) - return; - - if (seat->splash != NULL) - ply_boot_splash_detach_from_seat (splash, seat); - - if (splash != NULL) - ply_boot_splash_attach_to_seat (splash, seat); - - seat->splash = splash; -} - -static void -free_pixel_displays (ply_seat_t *seat) -{ - ply_list_node_t *node; - - ply_trace ("freeing %d pixel displays", ply_list_get_length (seat->pixel_displays)); - node = ply_list_get_first_node (seat->pixel_displays); - while (node != NULL) { - ply_list_node_t *next_node; - ply_pixel_display_t *display; - - next_node = ply_list_get_next_node (seat->pixel_displays, node); - display = ply_list_node_get_data (node); - ply_pixel_display_free (display); - - ply_list_remove_node (seat->pixel_displays, node); - - node = next_node; - } -} - -static void -free_text_displays (ply_seat_t *seat) -{ - ply_list_node_t *node; - - ply_trace ("freeing %d text displays", ply_list_get_length (seat->text_displays)); - node = ply_list_get_first_node (seat->text_displays); - while (node != NULL) { - ply_list_node_t *next_node; - ply_text_display_t *display; - - next_node = ply_list_get_next_node (seat->text_displays, node); - display = ply_list_node_get_data (node); - ply_text_display_free (display); - - ply_list_remove_node (seat->text_displays, node); - - node = next_node; - } -} - -void -ply_seat_free (ply_seat_t *seat) -{ - if (seat == NULL) - return; - - free_pixel_displays (seat); - free_text_displays (seat); - ply_keyboard_free (seat->keyboard); - - free (seat); -} - -ply_list_t * -ply_seat_get_pixel_displays (ply_seat_t *seat) -{ - return seat->pixel_displays; -} - -ply_list_t * -ply_seat_get_text_displays (ply_seat_t *seat) -{ - return seat->text_displays; -} - -ply_keyboard_t * -ply_seat_get_keyboard (ply_seat_t *seat) -{ - return seat->keyboard; -} - -ply_renderer_t * -ply_seat_get_renderer (ply_seat_t *seat) -{ - return seat->renderer; -} - -/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ diff --git a/src/libply-splash-core/ply-seat.h b/src/libply-splash-core/ply-seat.h deleted file mode 100644 index f9ed15d..0000000 --- a/src/libply-splash-core/ply-seat.h +++ /dev/null @@ -1,66 +0,0 @@ -/* ply-seat.h - APIs for encapsulating a keyboard and one or more displays - * - * Copyright (C) 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written By: Ray Strode - */ -#ifndef PLY_SEAT_H -#define PLY_SEAT_H - -#include -#include -#include -#include - -#include "ply-boot-splash.h" -#include "ply-buffer.h" -#include "ply-event-loop.h" -#include "ply-keyboard.h" -#include "ply-list.h" -#include "ply-pixel-display.h" -#include "ply-terminal.h" -#include "ply-text-display.h" - -typedef struct _ply_boot_splash ply_boot_splash_t; -typedef struct _ply_seat ply_seat_t; - -#ifndef PLY_HIDE_FUNCTION_DECLARATIONS -ply_seat_t *ply_seat_new (ply_terminal_t *terminal); - -void ply_seat_free (ply_seat_t *seat); -bool ply_seat_open (ply_seat_t *seat, - ply_renderer_type_t renderer_type, - const char *device); -bool ply_seat_is_open (ply_seat_t *seat); -void ply_seat_deactivate_keyboard (ply_seat_t *seat); -void ply_seat_activate_keyboard (ply_seat_t *seat); -void ply_seat_deactivate_renderer (ply_seat_t *seat); -void ply_seat_activate_renderer (ply_seat_t *seat); -void ply_seat_refresh_displays (ply_seat_t *seat); -void ply_seat_close (ply_seat_t *seat); -void ply_seat_set_splash (ply_seat_t *seat, - ply_boot_splash_t *splash); - -ply_list_t *ply_seat_get_pixel_displays (ply_seat_t *seat); -ply_list_t *ply_seat_get_text_displays (ply_seat_t *seat); -ply_keyboard_t *ply_seat_get_keyboard (ply_seat_t *seat); -ply_renderer_t *ply_seat_get_renderer (ply_seat_t *seat); -#endif - -#endif /* PLY_SEAT_H */ -/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ diff --git a/src/libply-splash-core/ply-terminal.c b/src/libply-splash-core/ply-terminal.c index 1bbeb42..a0954f2 100644 --- a/src/libply-splash-core/ply-terminal.c +++ b/src/libply-splash-core/ply-terminal.c @@ -387,8 +387,8 @@ on_tty_disconnected (ply_terminal_t *terminal) ply_terminal_reopen_device (terminal); } -static bool -ply_terminal_look_up_geometry (ply_terminal_t *terminal) +bool +ply_terminal_refresh_geometry (ply_terminal_t *terminal) { struct winsize terminal_size; @@ -551,7 +551,7 @@ ply_terminal_open_device (ply_terminal_t *terminal) assert (terminal->fd < 0); assert (terminal->fd_watch == NULL); - terminal->fd = open (terminal->name, O_RDWR | O_NOCTTY); + terminal->fd = open (terminal->name, O_RDWR | O_NOCTTY | O_NONBLOCK); if (terminal->fd < 0) { ply_trace ("Unable to open terminal device '%s': %m", terminal->name); @@ -570,6 +570,8 @@ ply_terminal_open_device (ply_terminal_t *terminal) return PLY_TERMINAL_OPEN_RESULT_FAILURE; } + ply_set_fd_as_blocking (terminal->fd); + terminal->fd_watch = ply_event_loop_watch_fd (terminal->loop, terminal->fd, PLY_EVENT_LOOP_FD_STATUS_HAS_DATA, (ply_event_handler_t) on_tty_input, @@ -605,7 +607,7 @@ ply_terminal_open (ply_terminal_t *terminal) return false; } - ply_terminal_look_up_geometry (terminal); + ply_terminal_refresh_geometry (terminal); ply_terminal_look_up_color_palette (terminal); ply_terminal_save_color_palette (terminal); @@ -613,7 +615,7 @@ ply_terminal_open (ply_terminal_t *terminal) ply_event_loop_watch_signal (terminal->loop, SIGWINCH, (ply_event_handler_t) - ply_terminal_look_up_geometry, + ply_terminal_refresh_geometry, terminal); if (ply_terminal_is_vt (terminal)) { diff --git a/src/libply-splash-core/ply-terminal.h b/src/libply-splash-core/ply-terminal.h index dc83ec3..7cfcc59 100644 --- a/src/libply-splash-core/ply-terminal.h +++ b/src/libply-splash-core/ply-terminal.h @@ -69,6 +69,7 @@ void ply_terminal_reset_colors (ply_terminal_t *terminal); bool ply_terminal_set_unbuffered_input (ply_terminal_t *terminal); bool ply_terminal_set_buffered_input (ply_terminal_t *terminal); +bool ply_terminal_refresh_geometry (ply_terminal_t *terminal); __attribute__((__format__ (__printf__, 2, 3))) void ply_terminal_write (ply_terminal_t *terminal, diff --git a/src/libply-splash-graphics/ply-animation.c b/src/libply-splash-graphics/ply-animation.c index 81348f9..323d9ed 100644 --- a/src/libply-splash-graphics/ply-animation.c +++ b/src/libply-splash-graphics/ply-animation.c @@ -353,6 +353,11 @@ ply_animation_stop_now (ply_animation_t *animation) void ply_animation_stop (ply_animation_t *animation) { + if (animation->is_stopped) { + ply_trace ("animation already stopped, ignoring stop request"); + return; + } + if (animation->stop_trigger == NULL) { ply_animation_stop_now (animation); return; diff --git a/src/libply-splash-graphics/ply-image.c b/src/libply-splash-graphics/ply-image.c index f838601..8b46978 100644 --- a/src/libply-splash-graphics/ply-image.c +++ b/src/libply-splash-graphics/ply-image.c @@ -99,10 +99,13 @@ transform_to_argb32 (png_struct *png, blue = data[i + 2]; alpha = data[i + 3]; - red = (uint8_t) CLAMP (((red / 255.0) * (alpha / 255.0)) * 255.0, 0, 255.0); - green = (uint8_t) CLAMP (((green / 255.0) * (alpha / 255.0)) * 255.0, - 0, 255.0); - blue = (uint8_t) CLAMP (((blue / 255.0) * (alpha / 255.0)) * 255.0, 0, 255.0); + /* pre-multiply the alpha if there's translucency */ + if (alpha != 0xff) { + red = (uint8_t) CLAMP (((red / 255.0) * (alpha / 255.0)) * 255.0, 0, 255.0); + green = (uint8_t) CLAMP (((green / 255.0) * (alpha / 255.0)) * 255.0, + 0, 255.0); + blue = (uint8_t) CLAMP (((blue / 255.0) * (alpha / 255.0)) * 255.0, 0, 255.0); + } pixel_value = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0); memcpy (data + i, &pixel_value, sizeof(uint32_t)); diff --git a/src/libply-splash-graphics/ply-throbber.c b/src/libply-splash-graphics/ply-throbber.c index c9c5bbd..f18feb6 100644 --- a/src/libply-splash-graphics/ply-throbber.c +++ b/src/libply-splash-graphics/ply-throbber.c @@ -337,6 +337,15 @@ void ply_throbber_stop (ply_throbber_t *throbber, ply_trigger_t *stop_trigger) { + if (throbber->is_stopped) { + ply_trace ("throbber already stopped"); + if (stop_trigger != NULL) { + ply_trace ("pulling stop trigger right away"); + ply_trigger_pull (stop_trigger, NULL); + } + return; + } + if (stop_trigger == NULL) { ply_throbber_stop_now (throbber); return; diff --git a/src/libply/ply-logger.h b/src/libply/ply-logger.h index de23181..545e64c 100644 --- a/src/libply/ply-logger.h +++ b/src/libply/ply-logger.h @@ -92,7 +92,7 @@ bool ply_logger_is_tracing_enabled (ply_logger_t *logger); ply_logger_flush (logger); \ errno = _old_errno; \ ply_logger_inject (logger, \ - "[%s:%d] %45.45s:" format "\r\n", \ + "[%s:%d] %45.45s:" format "\n", \ __FILE__, __LINE__, __func__, ## args); \ ply_logger_flush (logger); \ errno = _old_errno; \ diff --git a/src/libply/ply-utils.c b/src/libply/ply-utils.c index 5c8510c..89e37e9 100644 --- a/src/libply/ply-utils.c +++ b/src/libply/ply-utils.c @@ -78,6 +78,8 @@ static int errno_stack[PLY_ERRNO_STACK_SIZE]; static int errno_stack_position = 0; +static int overridden_device_scale = 0; + bool ply_open_unidirectional_pipe (int *sender_fd, int *receiver_fd) @@ -421,6 +423,29 @@ ply_fd_may_block (int fd) return (flags & O_NONBLOCK) != 0; } +bool +ply_set_fd_as_blocking (int fd) +{ + int flags; + int ret = 0; + + assert (fd >= 0); + + flags = fcntl (fd, F_GETFL); + + if (flags == -1) { + return false; + } + + if (flags & O_NONBLOCK) { + flags &= ~O_NONBLOCK; + + ret = fcntl (fd, F_SETFL, flags); + } + + return ret == 0; +} + char ** ply_copy_string_array (const char *const *array) { @@ -936,4 +961,58 @@ out: return (pid_t) ppid; } + +void +ply_set_device_scale (int device_scale) +{ + overridden_device_scale = device_scale; + ply_trace ("Device scale is set to %d", device_scale); +} + +/* The minimum resolution at which we turn on a device-scale of 2 */ +#define HIDPI_LIMIT 192 +#define HIDPI_MIN_HEIGHT 1200 + +int +ply_get_device_scale (uint32_t width, + uint32_t height, + uint32_t width_mm, + uint32_t height_mm) +{ + int device_scale; + double dpi_x, dpi_y; + const char *force_device_scale; + + device_scale = 1; + + if ((force_device_scale = getenv ("PLYMOUTH_FORCE_SCALE"))) + return strtoul (force_device_scale, NULL, 0); + + if (overridden_device_scale != 0) + return overridden_device_scale; + + if (height < HIDPI_MIN_HEIGHT) + return 1; + + /* Somebody encoded the aspect ratio (16/9 or 16/10) + * instead of the physical size */ + if ((width_mm == 160 && height_mm == 90) || + (width_mm == 160 && height_mm == 100) || + (width_mm == 16 && height_mm == 9) || + (width_mm == 16 && height_mm == 10)) + return 1; + + if (width_mm > 0 && height_mm > 0) { + dpi_x = (double)width / (width_mm / 25.4); + dpi_y = (double)height / (height_mm / 25.4); + /* We don't completely trust these values so both + must be high, and never pick higher ratio than + 2 automatically */ + if (dpi_x > HIDPI_LIMIT && dpi_y > HIDPI_LIMIT) + device_scale = 2; + } + + return device_scale; +} + /* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/libply/ply-utils.h b/src/libply/ply-utils.h index b9a28d0..c46603e 100644 --- a/src/libply/ply-utils.h +++ b/src/libply/ply-utils.h @@ -82,6 +82,7 @@ bool ply_read_uint32 (int fd, bool ply_fd_has_data (int fd); bool ply_fd_can_take_data (int fd); bool ply_fd_may_block (int fd); +bool ply_set_fd_as_blocking (int fd); char **ply_copy_string_array (const char *const *array); void ply_free_string_array (char **array); bool ply_string_has_prefix (const char *string, @@ -120,6 +121,13 @@ int ply_utf8_string_get_length (const char *string, char *ply_get_process_command_line (pid_t pid); pid_t ply_get_process_parent_pid (pid_t pid); +void ply_set_device_scale (int device_scale); + +int ply_get_device_scale (uint32_t width, + uint32_t height, + uint32_t width_mm, + uint32_t height_mm); + #endif #endif /* PLY_UTILS_H */ diff --git a/src/main.c b/src/main.c index da6e95d..0864e5e 100644 --- a/src/main.c +++ b/src/main.c @@ -107,6 +107,7 @@ typedef struct double start_time; double splash_delay; + double device_timeout; char kernel_command_line[PLY_MAX_COMMAND_LINE_SIZE]; uint32_t kernel_command_line_is_set : 1; @@ -136,8 +137,8 @@ static ply_boot_splash_t *load_theme (state_t *state, static ply_boot_splash_t *show_theme (state_t *state, const char *theme_path); -static void attach_splash_to_seats (state_t *state, - ply_boot_splash_t *splash); +static void attach_splash_to_devices (state_t *state, + ply_boot_splash_t *splash); static bool attach_to_running_session (state_t *state); static void detach_from_running_session (state_t *state); static void on_escape_pressed (state_t *state); @@ -293,8 +294,8 @@ load_settings (state_t *state, char **theme_path) { ply_key_file_t *key_file = NULL; - const char *delay_string; bool settings_loaded = false; + const char *scale_string; const char *splash_string; ply_trace ("Trying to load %s", path); @@ -313,6 +314,8 @@ load_settings (state_t *state, splash_string, splash_string); if (isnan (state->splash_delay)) { + const char *delay_string; + delay_string = ply_key_file_get_value (key_file, "Daemon", "ShowDelay"); if (delay_string != NULL) { @@ -321,6 +324,23 @@ load_settings (state_t *state, } } + if (isnan (state->device_timeout)) { + const char *timeout_string; + + timeout_string = ply_key_file_get_value (key_file, "Daemon", "DeviceTimeout"); + + if (timeout_string != NULL) { + state->device_timeout = atof (timeout_string); + ply_trace ("Device timeout is set to %lf", state->device_timeout); + } + } + + scale_string = ply_key_file_get_value (key_file, "Daemon", "DeviceScale"); + + if (scale_string != NULL) { + ply_set_device_scale (strtoul (scale_string, NULL, 0)); + } + settings_loaded = true; out: ply_key_file_free (key_file); @@ -345,6 +365,8 @@ show_detailed_splash (state_t *state) } state->boot_splash = splash; + + show_messages (state); update_display (state); } @@ -419,6 +441,17 @@ find_override_splash (state_t *state) } static void +find_force_scale (state_t *state) +{ + const char *scale_string; + + scale_string = command_line_get_string_after_prefix (state->kernel_command_line, "plymouth.force-scale="); + + if (scale_string != NULL) + ply_set_device_scale (strtoul (scale_string, NULL, 0)); +} + +static void find_system_default_splash (state_t *state) { if (state->system_default_splash_path != NULL) @@ -492,6 +525,7 @@ show_default_splash (state_t *state) return; } + show_messages (state); update_display (state); } @@ -520,14 +554,14 @@ on_ask_for_password (state_t *state, * arrive shortly so just sit tight */ if (state->is_shown) { - bool has_open_seats; + bool has_displays; cancel_pending_delayed_show (state); - has_open_seats = ply_device_manager_has_open_seats (state->device_manager); + has_displays = ply_device_manager_has_displays (state->device_manager); - if (has_open_seats) { - ply_trace ("seats open now, showing splash immediately"); + if (has_displays) { + ply_trace ("displays available now, showing splash immediately"); show_splash (state); } else { ply_trace ("splash still coming up, waiting a bit"); @@ -891,7 +925,7 @@ plymouth_should_show_default_splash (state_t *state) static void on_show_splash (state_t *state) { - bool has_open_seats; + bool has_displays; if (state->is_shown) { ply_trace ("show splash called while already shown"); @@ -910,49 +944,20 @@ on_show_splash (state_t *state) } state->is_shown = true; - has_open_seats = ply_device_manager_has_open_seats (state->device_manager); + has_displays = ply_device_manager_has_displays (state->device_manager); - if (!state->is_attached && state->should_be_attached && has_open_seats) + if (!state->is_attached && state->should_be_attached && has_displays) attach_to_running_session (state); - if (has_open_seats) { - ply_trace ("at least one seat already open, so loading splash"); + if (has_displays) { + ply_trace ("at least one display already available, so loading splash"); show_splash (state); } else { - ply_trace ("no seats available to show splash on, waiting..."); + ply_trace ("no displays available to show splash on, waiting..."); } } static void -on_seat_removed (state_t *state, - ply_seat_t *seat) -{ - ply_keyboard_t *keyboard; - - keyboard = ply_seat_get_keyboard (seat); - - ply_trace ("no longer listening for keystrokes"); - ply_keyboard_remove_input_handler (keyboard, - (ply_keyboard_input_handler_t) - on_keyboard_input); - ply_trace ("no longer listening for escape"); - ply_keyboard_remove_escape_handler (keyboard, - (ply_keyboard_escape_handler_t) - on_escape_pressed); - ply_trace ("no longer listening for backspace"); - ply_keyboard_remove_backspace_handler (keyboard, - (ply_keyboard_backspace_handler_t) - on_backspace); - ply_trace ("no longer listening for enter"); - ply_keyboard_remove_enter_handler (keyboard, - (ply_keyboard_enter_handler_t) - on_enter); - - if (state->boot_splash != NULL) - ply_boot_splash_detach_from_seat (state->boot_splash, seat); -} - -static void show_splash (state_t *state) { if (state->boot_splash != NULL) @@ -991,23 +996,9 @@ show_splash (state_t *state) } static void -on_seat_added (state_t *state, - ply_seat_t *seat) +on_keyboard_added (state_t *state, + ply_keyboard_t *keyboard) { - ply_keyboard_t *keyboard; - - if (state->is_shown && !state->is_inactive) { - if (state->boot_splash == NULL) { - ply_trace ("seat added before splash loaded, so loading splash now"); - show_splash (state); - } else { - ply_trace ("seat added after splash loaded, so attaching to splash"); - ply_boot_splash_attach_to_seat (state->boot_splash, seat); - } - } - - keyboard = ply_seat_get_keyboard (seat); - ply_trace ("listening for keystrokes"); ply_keyboard_add_input_handler (keyboard, (ply_keyboard_input_handler_t) @@ -1024,6 +1015,90 @@ on_seat_added (state_t *state, ply_keyboard_add_enter_handler (keyboard, (ply_keyboard_enter_handler_t) on_enter, state); + + if (state->boot_splash != NULL) { + ply_trace ("keyboard set after splash loaded, so attaching to splash"); + ply_boot_splash_set_keyboard (state->boot_splash, keyboard); + } +} + +static void +on_keyboard_removed (state_t *state, + ply_keyboard_t *keyboard) +{ + ply_trace ("no longer listening for keystrokes"); + ply_keyboard_remove_input_handler (keyboard, + (ply_keyboard_input_handler_t) + on_keyboard_input); + ply_trace ("no longer listening for escape"); + ply_keyboard_remove_escape_handler (keyboard, + (ply_keyboard_escape_handler_t) + on_escape_pressed); + ply_trace ("no longer listening for backspace"); + ply_keyboard_remove_backspace_handler (keyboard, + (ply_keyboard_backspace_handler_t) + on_backspace); + ply_trace ("no longer listening for enter"); + ply_keyboard_remove_enter_handler (keyboard, + (ply_keyboard_enter_handler_t) + on_enter); + + if (state->boot_splash != NULL) + ply_boot_splash_unset_keyboard (state->boot_splash); +} + +static void +on_pixel_display_added (state_t *state, + ply_pixel_display_t *display) +{ + if (state->is_shown) { + if (state->boot_splash == NULL) { + ply_trace ("pixel display added before splash loaded, so loading splash now"); + show_splash (state); + } else { + ply_trace ("pixel display added after splash loaded, so attaching to splash"); + ply_boot_splash_add_pixel_display (state->boot_splash, display); + + update_display (state); + } + } +} + +static void +on_pixel_display_removed (state_t *state, + ply_pixel_display_t *display) +{ + if (state->boot_splash == NULL) + return; + + ply_boot_splash_remove_pixel_display (state->boot_splash, display); +} + +static void +on_text_display_added (state_t *state, + ply_text_display_t *display) +{ + if (state->is_shown) { + if (state->boot_splash == NULL) { + ply_trace ("text display added before splash loaded, so loading splash now"); + show_splash (state); + } else { + ply_trace ("text display added after splash loaded, so attaching to splash"); + ply_boot_splash_add_text_display (state->boot_splash, display); + + update_display (state); + } + } +} + +static void +on_text_display_removed (state_t *state, + ply_text_display_t *display) +{ + if (state->boot_splash == NULL) + return; + + ply_boot_splash_remove_text_display (state->boot_splash, display); } static void @@ -1033,12 +1108,25 @@ load_devices (state_t *state, state->device_manager = ply_device_manager_new (state->default_tty, flags); state->local_console_terminal = ply_device_manager_get_default_terminal (state->device_manager); - ply_device_manager_watch_seats (state->device_manager, - (ply_seat_added_handler_t) - on_seat_added, - (ply_seat_removed_handler_t) - on_seat_removed, - state); + ply_device_manager_watch_devices (state->device_manager, + state->device_timeout, + (ply_keyboard_added_handler_t) + on_keyboard_added, + (ply_keyboard_removed_handler_t) + on_keyboard_removed, + (ply_pixel_display_added_handler_t) + on_pixel_display_added, + (ply_pixel_display_removed_handler_t) + on_pixel_display_removed, + (ply_text_display_added_handler_t) + on_text_display_added, + (ply_text_display_removed_handler_t) + on_text_display_removed, + state); + + if (ply_device_manager_has_serial_consoles (state->device_manager)) { + state->should_force_details = true; + } } static void @@ -1507,22 +1595,52 @@ on_enter (state_t *state, } static void -attach_splash_to_seats (state_t *state, - ply_boot_splash_t *splash) +attach_splash_to_devices (state_t *state, + ply_boot_splash_t *splash) { - ply_list_t *seats; + ply_list_t *keyboards; + ply_list_t *pixel_displays; + ply_list_t *text_displays; ply_list_node_t *node; - seats = ply_device_manager_get_seats (state->device_manager); - node = ply_list_get_first_node (seats); + keyboards = ply_device_manager_get_keyboards (state->device_manager); + node = ply_list_get_first_node (keyboards); + while (node != NULL) { + ply_keyboard_t *keyboard; + ply_list_node_t *next_node; + + keyboard = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (keyboards, node); + + ply_boot_splash_set_keyboard (splash, keyboard); + + node = next_node; + } + + pixel_displays = ply_device_manager_get_pixel_displays (state->device_manager); + node = ply_list_get_first_node (pixel_displays); while (node != NULL) { - ply_seat_t *seat; + ply_pixel_display_t *pixel_display; ply_list_node_t *next_node; - seat = ply_list_node_get_data (node); - next_node = ply_list_get_next_node (seats, node); + pixel_display = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (pixel_displays, node); - ply_boot_splash_attach_to_seat (splash, seat); + ply_boot_splash_add_pixel_display (splash, pixel_display); + + node = next_node; + } + + text_displays = ply_device_manager_get_text_displays (state->device_manager); + node = ply_list_get_first_node (text_displays); + while (node != NULL) { + ply_text_display_t *text_display; + ply_list_node_t *next_node; + + text_display = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (text_displays, node); + + ply_boot_splash_add_text_display (splash, text_display); node = next_node; } @@ -1623,7 +1741,7 @@ show_theme (state_t *state, if (splash == NULL) return NULL; - attach_splash_to_seats (state, splash); + attach_splash_to_devices (state, splash); ply_device_manager_activate_renderers (state->device_manager); splash_mode = get_splash_mode_from_mode (state->mode); @@ -1641,7 +1759,6 @@ show_theme (state_t *state, #endif ply_device_manager_activate_keyboards (state->device_manager); - show_messages (state); return splash; } @@ -1978,12 +2095,15 @@ on_crash (int signum) { struct termios term_attributes; int fd; + static const char *show_cursor_sequence = "\033[?25h"; fd = open ("/dev/tty1", O_RDWR | O_NOCTTY); if (fd < 0) fd = open ("/dev/hvc0", O_RDWR | O_NOCTTY); ioctl (fd, KDSETMODE, KD_TEXT); + write (fd, show_cursor_sequence, sizeof (show_cursor_sequence) - 1); + tcgetattr (fd, &term_attributes); term_attributes.c_iflag |= BRKINT | IGNPAR | ICRNL | IXON; @@ -2191,6 +2311,7 @@ main (int argc, state.progress = ply_progress_new (); state.splash_delay = NAN; + state.device_timeout = NAN; ply_progress_load_cache (state.progress, get_cache_file_for_mode (state.mode)); @@ -2223,6 +2344,8 @@ main (int argc, state.splash_delay = NAN; } + find_force_scale (&state); + load_devices (&state, device_manager_flags); ply_trace ("entering event loop"); diff --git a/src/plugins/controls/label/plugin.c b/src/plugins/controls/label/plugin.c index 5edce3b..acba52b 100644 --- a/src/plugins/controls/label/plugin.c +++ b/src/plugins/controls/label/plugin.c @@ -113,15 +113,18 @@ get_cairo_context_for_pixel_buffer (ply_label_plugin_control_t *label, cairo_t *cairo_context; unsigned char *data; ply_rectangle_t size; + uint32_t scale; data = (unsigned char *) ply_pixel_buffer_get_argb32_data (pixel_buffer); ply_pixel_buffer_get_size (pixel_buffer, &size); + scale = ply_pixel_buffer_get_device_scale (pixel_buffer); cairo_surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32, - size.width, - size.height, - size.width * 4); + size.width * scale, + size.height * scale, + size.width * scale * 4); + cairo_surface_set_device_scale (cairo_surface, scale, scale); cairo_context = cairo_create (cairo_surface); cairo_surface_destroy (cairo_surface); diff --git a/src/plugins/renderers/drm/Makefile.am b/src/plugins/renderers/drm/Makefile.am index 747f202..271b17f 100644 --- a/src/plugins/renderers/drm/Makefile.am +++ b/src/plugins/renderers/drm/Makefile.am @@ -16,12 +16,7 @@ drm_la_LDFLAGS = -module -avoid-version -export-dynamic drm_la_LIBADD = $(PLYMOUTH_LIBS) $(DRM_LIBS) \ ../../../libply/libply.la \ ../../../libply-splash-core/libply-splash-core.la -drm_la_SOURCES = $(srcdir)/plugin.c \ - $(srcdir)/ply-renderer-driver.h -drm_la_SOURCES += $(srcdir)/ply-renderer-generic-driver.h \ - $(srcdir)/ply-renderer-generic-driver.c - - +drm_la_SOURCES = $(srcdir)/plugin.c endif diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c index 45aab7d..b93e8e4 100644 --- a/src/plugins/renderers/drm/plugin.c +++ b/src/plugins/renderers/drm/plugin.c @@ -54,12 +54,11 @@ #include "ply-hashtable.h" #include "ply-rectangle.h" #include "ply-region.h" +#include "ply-utils.h" #include "ply-terminal.h" #include "ply-renderer.h" #include "ply-renderer-plugin.h" -#include "ply-renderer-driver.h" -#include "ply-renderer-generic-driver.h" #define BYTES_PER_PIXEL (4) @@ -92,15 +91,27 @@ struct _ply_renderer_input_source void *user_data; }; +typedef struct +{ + uint32_t id; + + uint32_t handle; + uint32_t width; + uint32_t height; + uint32_t row_stride; + + void *map_address; + uint32_t map_size; + int map_count; + + uint32_t added_fb : 1; +} ply_renderer_buffer_t; + struct _ply_renderer_backend { ply_event_loop_t *loop; ply_terminal_t *terminal; - ply_renderer_driver_interface_t *driver_interface; - ply_renderer_driver_t *driver; - uint32_t driver_supports_mapping_console; - int device_fd; char *device_name; drmModeRes *resources; @@ -109,11 +120,14 @@ struct _ply_renderer_backend ply_list_t *heads; ply_hashtable_t *heads_by_connector_id; + ply_hashtable_t *output_buffers; + int32_t dither_red; int32_t dither_green; int32_t dither_blue; uint32_t is_active : 1; + uint32_t requires_explicit_flushing : 1; }; ply_renderer_plugin_interface_t *ply_renderer_backend_get_interface (void); @@ -127,6 +141,233 @@ static void flush_head (ply_renderer_backend_t *backend, ply_renderer_head_t *head); static bool +ply_renderer_buffer_map (ply_renderer_backend_t *backend, + ply_renderer_buffer_t *buffer) +{ + struct drm_mode_map_dumb map_dumb_buffer_request; + void *map_address; + + if (buffer->map_address != MAP_FAILED) { + buffer->map_count++; + return true; + } + + memset (&map_dumb_buffer_request, 0, sizeof(struct drm_mode_map_dumb)); + map_dumb_buffer_request.handle = buffer->handle; + if (drmIoctl (backend->device_fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb_buffer_request) < 0) { + ply_trace ("Could not map GEM object %u: %m", buffer->handle); + return false; + } + + map_address = mmap (0, buffer->map_size, + PROT_READ | PROT_WRITE, MAP_SHARED, + backend->device_fd, map_dumb_buffer_request.offset); + + if (map_address == MAP_FAILED) + return false; + + buffer->map_address = map_address; + buffer->map_count++; + + return true; +} + +static void +ply_renderer_buffer_unmap (ply_renderer_backend_t *backend, + ply_renderer_buffer_t *buffer) +{ + buffer->map_count--; + + assert (buffer->map_count >= 0); +} + +static ply_renderer_buffer_t * +ply_renderer_buffer_new (ply_renderer_backend_t *backend, + uint32_t width, + uint32_t height) +{ + ply_renderer_buffer_t *buffer; + struct drm_mode_create_dumb create_dumb_buffer_request; + + buffer = calloc (1, sizeof(ply_renderer_buffer_t)); + buffer->width = width; + buffer->height = height; + buffer->map_address = MAP_FAILED; + + memset (&create_dumb_buffer_request, 0, sizeof(struct drm_mode_create_dumb)); + + create_dumb_buffer_request.width = width; + create_dumb_buffer_request.height = height; + create_dumb_buffer_request.bpp = 32; + create_dumb_buffer_request.flags = 0; + + if (drmIoctl (backend->device_fd, + DRM_IOCTL_MODE_CREATE_DUMB, + &create_dumb_buffer_request) < 0) { + free (buffer); + ply_trace ("Could not allocate GEM object for frame buffer: %m"); + return NULL; + } + + buffer->handle = create_dumb_buffer_request.handle; + buffer->row_stride = create_dumb_buffer_request.pitch; + buffer->map_size = create_dumb_buffer_request.size; + + ply_trace ("returning %ux%u buffer with stride %u", + width, height, buffer->row_stride); + + return buffer; +} + +static void +ply_renderer_buffer_free (ply_renderer_backend_t *backend, + ply_renderer_buffer_t *buffer) +{ + struct drm_mode_destroy_dumb destroy_dumb_buffer_request; + + if (buffer->added_fb) + drmModeRmFB (backend->device_fd, buffer->id); + + if (buffer->map_address != MAP_FAILED) { + munmap (buffer->map_address, buffer->map_size); + buffer->map_address = MAP_FAILED; + } + + memset (&destroy_dumb_buffer_request, 0, sizeof(struct drm_mode_destroy_dumb)); + destroy_dumb_buffer_request.handle = buffer->handle; + + if (drmIoctl (backend->device_fd, + DRM_IOCTL_MODE_DESTROY_DUMB, + &destroy_dumb_buffer_request) < 0) + ply_trace ("Could not deallocate GEM object %u: %m", buffer->handle); + + free (buffer); +} + +static ply_renderer_buffer_t * +get_buffer_from_id (ply_renderer_backend_t *backend, + uint32_t id) +{ + static ply_renderer_buffer_t *buffer; + + buffer = ply_hashtable_lookup (backend->output_buffers, (void *) (uintptr_t) id); + + return buffer; +} + +static uint32_t +create_output_buffer (ply_renderer_backend_t *backend, + unsigned long width, + unsigned long height, + unsigned long *row_stride) +{ + ply_renderer_buffer_t *buffer; + + buffer = ply_renderer_buffer_new (backend, width, height); + + if (buffer == NULL) { + ply_trace ("Could not allocate GEM object for frame buffer: %m"); + return 0; + } + + if (drmModeAddFB (backend->device_fd, width, height, + 24, 32, buffer->row_stride, buffer->handle, + &buffer->id) != 0) { + ply_trace ("Could not set up GEM object as frame buffer: %m"); + ply_renderer_buffer_free (backend, buffer); + return 0; + } + + *row_stride = buffer->row_stride; + + buffer->added_fb = true; + ply_hashtable_insert (backend->output_buffers, + (void *) (uintptr_t) buffer->id, + buffer); + + return buffer->id; +} + +static bool +map_buffer (ply_renderer_backend_t *backend, + uint32_t buffer_id) +{ + ply_renderer_buffer_t *buffer; + + buffer = get_buffer_from_id (backend, buffer_id); + + assert (buffer != NULL); + + return ply_renderer_buffer_map (backend, buffer); +} + +static void +unmap_buffer (ply_renderer_backend_t *backend, + uint32_t buffer_id) +{ + ply_renderer_buffer_t *buffer; + + buffer = get_buffer_from_id (backend, buffer_id); + + assert (buffer != NULL); + + ply_renderer_buffer_unmap (backend, buffer); +} + +static char * +begin_flush (ply_renderer_backend_t *backend, + uint32_t buffer_id) +{ + ply_renderer_buffer_t *buffer; + + buffer = get_buffer_from_id (backend, buffer_id); + + assert (buffer != NULL); + + return buffer->map_address; +} + +static void +end_flush (ply_renderer_backend_t *backend, + uint32_t buffer_id) +{ + ply_renderer_buffer_t *buffer; + + buffer = get_buffer_from_id (backend, buffer_id); + + assert (buffer != NULL); + + if (backend->requires_explicit_flushing) { + struct drm_clip_rect flush_area; + int ret; + + flush_area.x1 = 0; + flush_area.y1 = 0; + flush_area.x2 = buffer->width; + flush_area.y2 = buffer->height; + + ret = drmModeDirtyFB (backend->device_fd, buffer->id, &flush_area, 1); + + if (ret == -ENOSYS) + backend->requires_explicit_flushing = false; + } +} + +static void +destroy_output_buffer (ply_renderer_backend_t *backend, + uint32_t buffer_id) +{ + ply_renderer_buffer_t *buffer; + + buffer = ply_hashtable_remove (backend->output_buffers, + (void *) (uintptr_t) buffer_id); + + assert (buffer != NULL); + + ply_renderer_buffer_free (backend, buffer); +} + +static bool ply_renderer_head_add_connector (ply_renderer_head_t *head, drmModeConnector *connector, int connector_mode_index) @@ -185,6 +426,11 @@ ply_renderer_head_new (ply_renderer_backend_t *backend, assert (ply_array_get_size (head->connector_ids) > 0); head->pixel_buffer = ply_pixel_buffer_new (head->area.width, head->area.height); + ply_pixel_buffer_set_device_scale (head->pixel_buffer, + ply_get_device_scale (head->area.width, + head->area.height, + connector->mmWidth, + connector->mmHeight)); ply_trace ("Creating %ldx%ld renderer head", head->area.width, head->area.height); ply_pixel_buffer_fill_with_color (head->pixel_buffer, NULL, @@ -241,25 +487,21 @@ ply_renderer_head_map (ply_renderer_backend_t *backend, assert (backend != NULL); assert (backend->device_fd >= 0); - assert (backend->driver_interface != NULL); - assert (backend->driver != NULL); + assert (backend != NULL); assert (head != NULL); ply_trace ("Creating buffer for %ldx%ld renderer head", head->area.width, head->area.height); - head->scan_out_buffer_id = - backend->driver_interface->create_buffer (backend->driver, - head->area.width, head->area.height, - &head->row_stride); + head->scan_out_buffer_id = create_output_buffer (backend, + head->area.width, head->area.height, + &head->row_stride); if (head->scan_out_buffer_id == 0) return false; ply_trace ("Mapping buffer for %ldx%ld renderer head", head->area.width, head->area.height); - if (!backend->driver_interface->map_buffer (backend->driver, - head->scan_out_buffer_id)) { - backend->driver_interface->destroy_buffer (backend->driver, - head->scan_out_buffer_id); + if (!map_buffer (backend, head->scan_out_buffer_id)) { + destroy_output_buffer (backend, head->scan_out_buffer_id); head->scan_out_buffer_id = 0; return false; } @@ -271,8 +513,7 @@ ply_renderer_head_map (ply_renderer_backend_t *backend, scan_out_set = reset_scan_out_buffer_if_needed (backend, head); if (!scan_out_set && backend->is_active) { - backend->driver_interface->destroy_buffer (backend->driver, - head->scan_out_buffer_id); + destroy_output_buffer (backend, head->scan_out_buffer_id); head->scan_out_buffer_id = 0; return false; } @@ -285,11 +526,9 @@ ply_renderer_head_unmap (ply_renderer_backend_t *backend, ply_renderer_head_t *head) { ply_trace ("unmapping %ldx%ld renderer head", head->area.width, head->area.height); - backend->driver_interface->unmap_buffer (backend->driver, - head->scan_out_buffer_id); + unmap_buffer (backend, head->scan_out_buffer_id); - backend->driver_interface->destroy_buffer (backend->driver, - head->scan_out_buffer_id); + destroy_output_buffer (backend, head->scan_out_buffer_id); head->scan_out_buffer_id = 0; } @@ -375,10 +614,19 @@ create_backend (const char *device_name, backend->heads = ply_list_new (); backend->input_source.key_buffer = ply_buffer_new (); backend->terminal = terminal; + backend->requires_explicit_flushing = true; + backend->output_buffers = ply_hashtable_new (ply_hashtable_direct_hash, + ply_hashtable_direct_compare); return backend; } +static const char * +get_device_name (ply_renderer_backend_t *backend) +{ + return backend->device_name; +} + static void destroy_backend (ply_renderer_backend_t *backend) { @@ -386,6 +634,9 @@ destroy_backend (ply_renderer_backend_t *backend) free_heads (backend); free (backend->device_name); + ply_hashtable_free (backend->output_buffers); + + drmModeFreeResources (backend->resources); free (backend); } @@ -455,44 +706,29 @@ load_driver (ply_renderer_backend_t *backend) return false; } - backend->driver_interface = ply_renderer_generic_driver_get_interface (device_fd); - backend->driver_supports_mapping_console = false; - - if (backend->driver_interface == NULL) { - close (device_fd); - return false; - } - - backend->driver = backend->driver_interface->create_driver (device_fd); - - if (backend->driver == NULL) { - close (device_fd); - return false; - } - backend->device_fd = device_fd; + drmDropMaster (device_fd); + return true; } static void -unload_driver (ply_renderer_backend_t *backend) +unload_backend (ply_renderer_backend_t *backend) { - if (backend->driver == NULL) + if (backend == NULL) return; - ply_trace ("unloading driver"); - assert (backend->driver_interface != NULL); - - backend->driver_interface->destroy_driver (backend->driver); - backend->driver = NULL; - - backend->driver_interface = NULL; + ply_trace ("unloading backend"); if (backend->device_fd >= 0) { drmClose (backend->device_fd); backend->device_fd = -1; } + + destroy_backend (backend); + backend = NULL; + } static bool @@ -540,7 +776,7 @@ close_device (ply_renderer_backend_t *backend) backend); } - unload_driver (backend); + unload_backend (backend); } static drmModeCrtc * @@ -732,34 +968,6 @@ create_heads_for_active_connectors (ply_renderer_backend_t *backend) ply_hashtable_free (heads_by_controller_id); -#ifdef PLY_ENABLE_DEPRECATED_GDM_TRANSITION - /* If the driver doesn't support mapping the fb console - * then we can't get a smooth crossfade transition to - * the display manager unless we use the /dev/fb interface - * or the plymouth deactivate interface. - * - * In multihead configurations, we'd rather have working - * multihead, but otherwise bail now. - */ - if (!backend->driver_supports_mapping_console && - ply_list_get_length (backend->heads) == 1) { - ply_list_node_t *node; - ply_renderer_head_t *head; - - node = ply_list_get_first_node (backend->heads); - head = (ply_renderer_head_t *) ply_list_node_get_data (node); - - if (ply_array_get_size (head->connector_ids) == 1) { - ply_trace ("Only one monitor configured, and driver doesn't " - "support mapping console, so letting frame-buffer " - "take over"); - - free_heads (backend); - return false; - } - } -#endif - return ply_list_get_length (backend->heads) > 0; } @@ -774,7 +982,7 @@ has_32bpp_support (ply_renderer_backend_t *backend) min_width = backend->resources->min_width; min_height = backend->resources->min_height; - /* Some drivers set min_width/min_height to 0, + /* Some backends set min_width/min_height to 0, * but 0x0 sized buffers don't work. */ if (min_width == 0) @@ -783,10 +991,7 @@ has_32bpp_support (ply_renderer_backend_t *backend) if (min_height == 0) min_height = 1; - buffer_id = backend->driver_interface->create_buffer (backend->driver, - min_width, - min_height, - &row_stride); + buffer_id = create_output_buffer (backend, min_width, min_height, &row_stride); if (buffer_id == 0) { ply_trace ("Could not create minimal (%ux%u) 32bpp dummy buffer", @@ -795,8 +1000,7 @@ has_32bpp_support (ply_renderer_backend_t *backend) return false; } - backend->driver_interface->destroy_buffer (backend->driver, - buffer_id); + destroy_output_buffer (backend, buffer_id); return true; } @@ -860,93 +1064,10 @@ map_to_device (ply_renderer_backend_t *backend) return head_mapped; } -static bool -ply_renderer_head_set_scan_out_buffer_to_console (ply_renderer_backend_t *backend, - ply_renderer_head_t *head, - bool should_set_to_black) -{ - unsigned long width; - unsigned long height; - unsigned long row_stride; - uint32_t *shadow_buffer; - ply_pixel_buffer_t *pixel_buffer; - char *map_address; - ply_rectangle_t area; - - if (!backend->driver_interface->fetch_buffer (backend->driver, - head->console_buffer_id, - &width, &height, &row_stride)) - return false; - - if (!backend->driver_interface->map_buffer (backend->driver, - head->console_buffer_id)) { - backend->driver_interface->destroy_buffer (backend->driver, - head->console_buffer_id); - return false; - } - - if (head->area.width != width || head->area.height != height) { - /* Force black if the fb console resolution doesn't match our resolution - */ - area.x = 0; - area.y = 0; - area.width = width; - area.height = height; - - should_set_to_black = true; - ply_trace ("Console fb is %ldx%ld and screen contents are %ldx%ld. " - "They aren't the same dimensions; forcing black", - width, height, head->area.width, head->area.height); - } else { - area = head->area; - } - - if (should_set_to_black) { - pixel_buffer = ply_pixel_buffer_new (width, height); - shadow_buffer = ply_pixel_buffer_get_argb32_data (pixel_buffer); - } else { - pixel_buffer = NULL; - shadow_buffer = ply_pixel_buffer_get_argb32_data (head->pixel_buffer); - } - - ply_trace ("Drawing %s to console fb", should_set_to_black ? "black" : "screen contents"); - map_address = - backend->driver_interface->begin_flush (backend->driver, - head->console_buffer_id); - - flush_area ((char *) shadow_buffer, area.width * 4, - map_address, row_stride, &area); - - backend->driver_interface->end_flush (backend->driver, - head->console_buffer_id); - - backend->driver_interface->unmap_buffer (backend->driver, - head->console_buffer_id); - - ply_trace ("Setting scan out hardware to console fb"); - ply_renderer_head_set_scan_out_buffer (backend, - head, head->console_buffer_id); - - backend->driver_interface->destroy_buffer (backend->driver, - head->console_buffer_id); - - if (pixel_buffer != NULL) - ply_pixel_buffer_free (pixel_buffer); - - return true; -} - static void unmap_from_device (ply_renderer_backend_t *backend) { ply_list_node_t *node; - bool should_set_to_black; - - /* We only copy what's on screen back to the fb console - * if there's one head (since in multihead set ups the fb console - * is cloned). - */ - should_set_to_black = ply_list_get_length (backend->heads) > 1; node = ply_list_get_first_node (backend->heads); while (node != NULL) { @@ -956,13 +1077,6 @@ unmap_from_device (ply_renderer_backend_t *backend) head = (ply_renderer_head_t *) ply_list_node_get_data (node); next_node = ply_list_get_next_node (backend->heads, node); - if (backend->is_active) { - ply_trace ("scanning out %s directly to console", - should_set_to_black ? "black" : "splash"); - ply_renderer_head_set_scan_out_buffer_to_console (backend, head, - should_set_to_black); - } - ply_renderer_head_unmap (backend, head); node = next_node; @@ -1019,9 +1133,7 @@ flush_head (ply_renderer_backend_t *backend, updated_region = ply_pixel_buffer_get_updated_areas (pixel_buffer); areas_to_flush = ply_region_get_sorted_rectangle_list (updated_region); - map_address = - backend->driver_interface->begin_flush (backend->driver, - head->scan_out_buffer_id); + map_address = begin_flush (backend, head->scan_out_buffer_id); node = ply_list_get_first_node (areas_to_flush); while (node != NULL) { @@ -1041,8 +1153,7 @@ flush_head (ply_renderer_backend_t *backend, node = next_node; } - backend->driver_interface->end_flush (backend->driver, - head->scan_out_buffer_id); + end_flush (backend, head->scan_out_buffer_id); ply_region_clear (updated_region); } @@ -1180,7 +1291,8 @@ ply_renderer_backend_get_interface (void) .get_input_source = get_input_source, .open_input_source = open_input_source, .set_handler_for_input_source = set_handler_for_input_source, - .close_input_source = close_input_source + .close_input_source = close_input_source, + .get_device_name = get_device_name }; return &plugin_interface; diff --git a/src/plugins/renderers/drm/ply-renderer-driver.h b/src/plugins/renderers/drm/ply-renderer-driver.h deleted file mode 100644 index f3febcf..0000000 --- a/src/plugins/renderers/drm/ply-renderer-driver.h +++ /dev/null @@ -1,66 +0,0 @@ -/* ply-renderer-driver.h - * - * Copyright (C) 2009 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written By: Ray Strode - */ -#ifndef PLY_RENDERER_DRIVER_H -#define PLY_RENDERER_DRIVER_H - -#include -#include - -#include "ply-list.h" -#include "ply-rectangle.h" -#include "ply-utils.h" - -typedef struct _ply_renderer_driver ply_renderer_driver_t; - -typedef struct -{ - ply_renderer_driver_t * (*create_driver)(int device_fd); - - void (*destroy_driver)(ply_renderer_driver_t *driver); - - uint32_t (*create_buffer)(ply_renderer_driver_t *driver, - unsigned long width, - unsigned long height, - unsigned long *row_stride); - bool (*fetch_buffer)(ply_renderer_driver_t *driver, - uint32_t buffer_id, - unsigned long *width, - unsigned long *height, - unsigned long *row_stride); - - bool (*map_buffer)(ply_renderer_driver_t *driver, - uint32_t buffer_id); - - void (*unmap_buffer)(ply_renderer_driver_t *driver, - uint32_t buffer_id); - - char * (*begin_flush)(ply_renderer_driver_t * driver, - uint32_t buffer_id); - void (*end_flush)(ply_renderer_driver_t *driver, - uint32_t buffer_id); - - void (*destroy_buffer)(ply_renderer_driver_t *driver, - uint32_t buffer_id); -} ply_renderer_driver_interface_t; - -#endif /* PLY_RENDERER_DRIVER_H */ -/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ diff --git a/src/plugins/renderers/drm/ply-renderer-generic-driver.c b/src/plugins/renderers/drm/ply-renderer-generic-driver.c deleted file mode 100644 index b1be714..0000000 --- a/src/plugins/renderers/drm/ply-renderer-generic-driver.c +++ /dev/null @@ -1,385 +0,0 @@ -/* ply-renderer-generic-driver.c - interface to generic drm kms api - * - * Copyright (C) 2012 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: Dave Airlie - * Based on other renderer drivers written by Ray Strode - */ -#include "config.h" - -#include "ply-renderer-generic-driver.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "ply-hashtable.h" -#include "ply-logger.h" -#include "ply-renderer-driver.h" - -typedef struct _ply_renderer_buffer ply_renderer_buffer_t; - -struct _ply_renderer_buffer -{ - uint32_t id; - - uint32_t handle; - uint32_t width; - uint32_t height; - uint32_t row_stride; - - void *map_address; - uint32_t map_size; - int map_count; - - uint32_t added_fb : 1; -}; - -struct _ply_renderer_driver -{ - int device_fd; - ply_hashtable_t *buffers; - - uint32_t requires_explicit_flushing : 1; -}; - -static bool -ply_renderer_buffer_map (ply_renderer_driver_t *driver, - ply_renderer_buffer_t *buffer) -{ - struct drm_mode_map_dumb map_dumb_buffer_request; - void *map_address; - - if (buffer->map_address != MAP_FAILED) { - buffer->map_count++; - return true; - } - - memset (&map_dumb_buffer_request, 0, sizeof(struct drm_mode_map_dumb)); - map_dumb_buffer_request.handle = buffer->handle; - if (drmIoctl (driver->device_fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb_buffer_request) < 0) { - ply_trace ("Could not map GEM object %u: %m", buffer->handle); - return false; - } - - map_address = mmap (0, buffer->map_size, - PROT_READ | PROT_WRITE, MAP_SHARED, - driver->device_fd, map_dumb_buffer_request.offset); - - if (map_address == MAP_FAILED) - return false; - - buffer->map_address = map_address; - buffer->map_count++; - - return true; -} - -static void -ply_renderer_buffer_unmap (ply_renderer_driver_t *driver, - ply_renderer_buffer_t *buffer) -{ - buffer->map_count--; - - assert (buffer->map_count >= 0); -} - -static ply_renderer_driver_t * -create_driver (int device_fd) -{ - ply_renderer_driver_t *driver; - - driver = calloc (1, sizeof(ply_renderer_driver_t)); - driver->device_fd = device_fd; - driver->requires_explicit_flushing = true; - driver->buffers = ply_hashtable_new (ply_hashtable_direct_hash, - ply_hashtable_direct_compare); - - return driver; -} - -static void -destroy_driver (ply_renderer_driver_t *driver) -{ - ply_hashtable_free (driver->buffers); - - free (driver); -} - -static ply_renderer_buffer_t * -ply_renderer_buffer_new (ply_renderer_driver_t *driver, - uint32_t width, - uint32_t height) -{ - ply_renderer_buffer_t *buffer; - struct drm_mode_create_dumb create_dumb_buffer_request; - - buffer = calloc (1, sizeof(ply_renderer_buffer_t)); - buffer->width = width; - buffer->height = height; - buffer->map_address = MAP_FAILED; - - memset (&create_dumb_buffer_request, 0, sizeof(struct drm_mode_create_dumb)); - - create_dumb_buffer_request.width = width; - create_dumb_buffer_request.height = height; - create_dumb_buffer_request.bpp = 32; - create_dumb_buffer_request.flags = 0; - - if (drmIoctl (driver->device_fd, - DRM_IOCTL_MODE_CREATE_DUMB, - &create_dumb_buffer_request) < 0) { - free (buffer); - ply_trace ("Could not allocate GEM object for frame buffer: %m"); - return NULL; - } - - buffer->handle = create_dumb_buffer_request.handle; - buffer->row_stride = create_dumb_buffer_request.pitch; - buffer->map_size = create_dumb_buffer_request.size; - - ply_trace ("returning %ux%u buffer with stride %u", - width, height, buffer->row_stride); - - return buffer; -} - -static void -ply_renderer_buffer_free (ply_renderer_driver_t *driver, - ply_renderer_buffer_t *buffer) -{ - struct drm_mode_destroy_dumb destroy_dumb_buffer_request; - - if (buffer->added_fb) - drmModeRmFB (driver->device_fd, buffer->id); - - if (buffer->map_address != MAP_FAILED) { - munmap (buffer->map_address, buffer->map_size); - buffer->map_address = MAP_FAILED; - } - - memset (&destroy_dumb_buffer_request, 0, sizeof(struct drm_mode_destroy_dumb)); - destroy_dumb_buffer_request.handle = buffer->handle; - - if (drmIoctl (driver->device_fd, - DRM_IOCTL_MODE_DESTROY_DUMB, - &destroy_dumb_buffer_request) < 0) - ply_trace ("Could not deallocate GEM object %u: %m", buffer->handle); - - free (buffer); -} - -static ply_renderer_buffer_t * -get_buffer_from_id (ply_renderer_driver_t *driver, - uint32_t id) -{ - static ply_renderer_buffer_t *buffer; - - buffer = ply_hashtable_lookup (driver->buffers, (void *) (uintptr_t) id); - - return buffer; -} - -static bool -fetch_buffer (ply_renderer_driver_t *driver, - uint32_t buffer_id, - unsigned long *width, - unsigned long *height, - unsigned long *row_stride) -{ - ply_renderer_buffer_t *buffer; - - buffer = get_buffer_from_id (driver, buffer_id); - - if (buffer == NULL) { - ply_trace ("could not fetch buffer %u", buffer_id); - return false; - } - - if (width != NULL) - *width = buffer->width; - - if (height != NULL) - *height = buffer->height; - - if (row_stride != NULL) - *row_stride = buffer->row_stride; - - ply_trace ("fetched %ux%u buffer with stride %u", - buffer->width, buffer->height, buffer->row_stride); - return true; -} - -static uint32_t -create_buffer (ply_renderer_driver_t *driver, - unsigned long width, - unsigned long height, - unsigned long *row_stride) -{ - ply_renderer_buffer_t *buffer; - - buffer = ply_renderer_buffer_new (driver, width, height); - - if (buffer == NULL) { - ply_trace ("Could not allocate GEM object for frame buffer: %m"); - return 0; - } - - if (drmModeAddFB (driver->device_fd, width, height, - 24, 32, buffer->row_stride, buffer->handle, - &buffer->id) != 0) { - ply_trace ("Could not set up GEM object as frame buffer: %m"); - ply_renderer_buffer_free (driver, buffer); - return 0; - } - - *row_stride = buffer->row_stride; - - buffer->added_fb = true; - ply_hashtable_insert (driver->buffers, - (void *) (uintptr_t) buffer->id, - buffer); - - return buffer->id; -} - -static bool -map_buffer (ply_renderer_driver_t *driver, - uint32_t buffer_id) -{ - ply_renderer_buffer_t *buffer; - - buffer = get_buffer_from_id (driver, buffer_id); - - assert (buffer != NULL); - - return ply_renderer_buffer_map (driver, buffer); -} - -static void -unmap_buffer (ply_renderer_driver_t *driver, - uint32_t buffer_id) -{ - ply_renderer_buffer_t *buffer; - - buffer = get_buffer_from_id (driver, buffer_id); - - assert (buffer != NULL); - - ply_renderer_buffer_unmap (driver, buffer); -} - -static char * -begin_flush (ply_renderer_driver_t *driver, - uint32_t buffer_id) -{ - ply_renderer_buffer_t *buffer; - - buffer = get_buffer_from_id (driver, buffer_id); - - assert (buffer != NULL); - - return buffer->map_address; -} - -static void -end_flush (ply_renderer_driver_t *driver, - uint32_t buffer_id) -{ - ply_renderer_buffer_t *buffer; - - buffer = get_buffer_from_id (driver, buffer_id); - - assert (buffer != NULL); - - if (driver->requires_explicit_flushing) { - struct drm_clip_rect flush_area; - int ret; - - flush_area.x1 = 0; - flush_area.y1 = 0; - flush_area.x2 = buffer->width; - flush_area.y2 = buffer->height; - - ret = drmModeDirtyFB (driver->device_fd, buffer->id, &flush_area, 1); - - if (ret == -ENOSYS) - driver->requires_explicit_flushing = false; - } -} - -static void -destroy_buffer (ply_renderer_driver_t *driver, - uint32_t buffer_id) -{ - ply_renderer_buffer_t *buffer; - - buffer = ply_hashtable_remove (driver->buffers, - (void *) (uintptr_t) buffer_id); - - assert (buffer != NULL); - - ply_renderer_buffer_free (driver, buffer); -} - -ply_renderer_driver_interface_t * -ply_renderer_generic_driver_get_interface (int device_fd) -{ - uint64_t supports_dumb_buffers; - - static ply_renderer_driver_interface_t driver_interface = - { - .create_driver = create_driver, - .destroy_driver = destroy_driver, - .create_buffer = create_buffer, - .fetch_buffer = fetch_buffer, - .map_buffer = map_buffer, - .unmap_buffer = unmap_buffer, - .begin_flush = begin_flush, - .end_flush = end_flush, - .destroy_buffer = destroy_buffer, - }; - - - if (drmGetCap (device_fd, DRM_CAP_DUMB_BUFFER, &supports_dumb_buffers) < 0) - return NULL; - - if (!supports_dumb_buffers) - return NULL; - - return &driver_interface; -} - -/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s, (0,=.5s,:.5s */ diff --git a/src/plugins/renderers/drm/ply-renderer-generic-driver.h b/src/plugins/renderers/drm/ply-renderer-generic-driver.h deleted file mode 100644 index 053587a..0000000 --- a/src/plugins/renderers/drm/ply-renderer-generic-driver.h +++ /dev/null @@ -1,33 +0,0 @@ -/* ply-renderer-generic-driver.h - * - * Copyright (C) 2012 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: Dave Airlie - * Based on other renderer drivers written by Ray Strode - */ -#ifndef PLY_RENDERER_DUMB_DRIVER_H -#define PLY_RENDERER_DUMB_DRIVER_H - -#include "ply-renderer-driver.h" - -#ifndef PLY_HIDE_FUNCTION_DECLARATIONS -ply_renderer_driver_interface_t *ply_renderer_generic_driver_get_interface (int device_fd); -#endif - -#endif /* PLY_RENDERER_GENERIC_DRIVER_H */ -/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ diff --git a/src/plugins/renderers/frame-buffer/plugin.c b/src/plugins/renderers/frame-buffer/plugin.c index 418855a..41ad6cd 100644 --- a/src/plugins/renderers/frame-buffer/plugin.c +++ b/src/plugins/renderers/frame-buffer/plugin.c @@ -365,6 +365,12 @@ open_device (ply_renderer_backend_t *backend) return true; } +static const char * +get_device_name (ply_renderer_backend_t *backend) +{ + return backend->device_name; +} + static void close_device (ply_renderer_backend_t *backend) { @@ -732,7 +738,8 @@ ply_renderer_backend_get_interface (void) .get_input_source = get_input_source, .open_input_source = open_input_source, .set_handler_for_input_source = set_handler_for_input_source, - .close_input_source = close_input_source + .close_input_source = close_input_source, + .get_device_name = get_device_name }; return &plugin_interface; diff --git a/src/plugins/renderers/x11/plugin.c b/src/plugins/renderers/x11/plugin.c index 1e1fe31..8948f69 100644 --- a/src/plugins/renderers/x11/plugin.c +++ b/src/plugins/renderers/x11/plugin.c @@ -56,6 +56,7 @@ #include "ply-logger.h" #include "ply-rectangle.h" #include "ply-region.h" +#include "ply-utils.h" #include "ply-renderer.h" #include "ply-renderer-plugin.h" @@ -64,9 +65,10 @@ struct _ply_renderer_head { ply_renderer_backend_t *backend; ply_pixel_buffer_t *pixel_buffer; - ply_rectangle_t area; + ply_rectangle_t area; /* in device pixels */ GtkWidget *window; cairo_surface_t *image; + uint32_t scale; uint32_t is_fullscreen : 1; }; @@ -148,9 +150,14 @@ open_device (ply_renderer_backend_t *backend) Display *display; int display_fd; + gdk_set_allowed_backends ("x11"); + if (!gtk_init_check (0, NULL)) return false; + /* Force gtk+ to deal in device pixels */ + gdk_x11_display_set_window_scale (gdk_display_get_default (), 1); + display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); display_fd = ConnectionNumber (display); backend->display_watch = ply_event_loop_watch_fd (backend->loop, @@ -163,6 +170,12 @@ open_device (ply_renderer_backend_t *backend) return true; } +static const char * +get_device_name (ply_renderer_backend_t *backend) +{ + return gdk_display_get_name (gdk_display_get_default ()); +} + static void close_device (ply_renderer_backend_t *backend) { @@ -183,7 +196,9 @@ create_fake_multi_head_setup (ply_renderer_backend_t *backend) head->area.y = 0; head->area.width = 800; /* FIXME hardcoded */ head->area.height = 600; + head->scale = 1; head->pixel_buffer = ply_pixel_buffer_new (head->area.width, head->area.height); + ply_pixel_buffer_set_device_scale (head->pixel_buffer, head->scale); ply_list_append_data (backend->heads, head); @@ -194,7 +209,9 @@ create_fake_multi_head_setup (ply_renderer_backend_t *backend) head->area.y = 0; head->area.width = 640; /* FIXME hardcoded */ head->area.height = 480; + head->scale = 1; head->pixel_buffer = ply_pixel_buffer_new (head->area.width, head->area.height); + ply_pixel_buffer_set_device_scale (head->pixel_buffer, head->scale); ply_list_append_data (backend->heads, head); } @@ -204,8 +221,11 @@ create_fullscreen_single_head_setup (ply_renderer_backend_t *backend) { ply_renderer_head_t *head; GdkRectangle monitor_geometry; + int width_mm, height_mm; gdk_screen_get_monitor_geometry (gdk_screen_get_default (), 0, &monitor_geometry); + width_mm = gdk_screen_get_monitor_width_mm (gdk_screen_get_default (), 0); + height_mm = gdk_screen_get_monitor_height_mm (gdk_screen_get_default (), 0); head = calloc (1, sizeof(ply_renderer_head_t)); @@ -215,7 +235,11 @@ create_fullscreen_single_head_setup (ply_renderer_backend_t *backend) head->area.width = monitor_geometry.width; head->area.height = monitor_geometry.height; head->is_fullscreen = true; + head->scale = ply_get_device_scale (monitor_geometry.width, + monitor_geometry.height, + width_mm, height_mm); head->pixel_buffer = ply_pixel_buffer_new (head->area.width, head->area.height); + ply_pixel_buffer_set_device_scale (head->pixel_buffer, head->scale); ply_list_append_data (backend->heads, head); } @@ -380,6 +404,12 @@ flush_head (ply_renderer_backend_t *backend, area_to_flush = (ply_rectangle_t *) ply_list_node_get_data (node); next_node = ply_list_get_next_node (areas_to_flush, node); + cairo_surface_mark_dirty_rectangle (head->image, + area_to_flush->x, + area_to_flush->y, + area_to_flush->width, + area_to_flush->height); + gtk_widget_queue_draw_area (head->window, area_to_flush->x, area_to_flush->y, @@ -515,7 +545,8 @@ ply_renderer_backend_get_interface (void) .get_input_source = get_input_source, .open_input_source = open_input_source, .set_handler_for_input_source = set_handler_for_input_source, - .close_input_source = close_input_source + .close_input_source = close_input_source, + .get_device_name = get_device_name }; return &plugin_interface; diff --git a/src/plugins/splash/details/plugin.c b/src/plugins/splash/details/plugin.c index 8e55d05..f534450 100644 --- a/src/plugins/splash/details/plugin.c +++ b/src/plugins/splash/details/plugin.c @@ -77,6 +77,8 @@ struct _ply_boot_splash_plugin ply_list_t *views; ply_boot_splash_display_type_t state; ply_list_t *messages; + + ply_buffer_t *boot_buffer; }; static view_t * @@ -239,6 +241,15 @@ add_text_display (ply_boot_splash_plugin_t *plugin, ply_terminal_activate_vt (terminal); ply_list_append_data (plugin->views, view); + + if (plugin->boot_buffer != NULL) { + size_t size; + const char *bytes; + + size = ply_buffer_get_size (plugin->boot_buffer); + bytes = ply_buffer_get_bytes (plugin->boot_buffer); + view_write (view, bytes, size); + } } static void @@ -282,8 +293,9 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, plugin); if (boot_buffer) { - size = ply_buffer_get_size (boot_buffer); + plugin->boot_buffer = boot_buffer; + size = ply_buffer_get_size (boot_buffer); write_on_views (plugin, ply_buffer_get_bytes (boot_buffer), size); } @@ -330,7 +342,7 @@ display_normal (ply_boot_splash_plugin_t *plugin) ply_list_node_t *node; if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_NORMAL) - write_on_views (plugin, "\r\n", strlen ("\r\n")); + write_on_views (plugin, "\n", strlen ("\n")); plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL; @@ -343,7 +355,7 @@ display_normal (ply_boot_splash_plugin_t *plugin) next_node = ply_list_get_next_node (plugin->messages, node); write_on_views (plugin, message, strlen (message)); - write_on_views (plugin, "\r\n", strlen ("\r\n")); + write_on_views (plugin, "\n", strlen ("\n")); ply_list_remove_node (plugin->messages, node); node = next_node; @@ -358,7 +370,7 @@ display_password (ply_boot_splash_plugin_t *plugin, int i; if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY) - write_on_views (plugin, "\r\n", strlen ("\r\n")); + write_on_views (plugin, "\n", strlen ("\n")); else write_on_views (plugin, CLEAR_LINE_SEQUENCE, @@ -387,7 +399,7 @@ display_question (ply_boot_splash_plugin_t *plugin, const char *entry_text) { if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY) - write_on_views (plugin, "\r\n", strlen ("\r\n")); + write_on_views (plugin, "\n", strlen ("\n")); else write_on_views (plugin, CLEAR_LINE_SEQUENCE, @@ -407,7 +419,7 @@ display_message (ply_boot_splash_plugin_t *plugin, { if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) { write_on_views (plugin, message, strlen (message)); - write_on_views (plugin, "\r\n", strlen ("\r\n")); + write_on_views (plugin, "\n", strlen ("\n")); } else { ply_list_append_data (plugin->messages, strdup (message)); } diff --git a/src/plugins/splash/fade-throbber/plugin.c b/src/plugins/splash/fade-throbber/plugin.c index 1643b87..a7ab4ef 100644 --- a/src/plugins/splash/fade-throbber/plugin.c +++ b/src/plugins/splash/fade-throbber/plugin.c @@ -104,6 +104,7 @@ struct _ply_boot_splash_plugin double now; uint32_t is_animating : 1; + uint32_t is_visible : 1; }; ply_boot_splash_plugin_interface_t *ply_boot_splash_plugin_get_interface (void); @@ -264,6 +265,8 @@ view_free (view_t *view) ply_label_free (view->message_label); free_stars (view); + ply_pixel_display_set_draw_handler (view->display, NULL, NULL); + free (view); } @@ -293,8 +296,12 @@ load_views (ply_boot_splash_plugin_t *plugin) view = ply_list_node_get_data (node); next_node = ply_list_get_next_node (plugin->views, node); - if (view_load (view)) + if (view_load (view)) { view_loaded = true; + } else { + ply_list_remove_node (plugin->views, node); + view_free (view); + } node = next_node; } @@ -745,7 +752,14 @@ add_pixel_display (ply_boot_splash_plugin_t *plugin, (ply_pixel_display_draw_handler_t) on_draw, view); - ply_list_append_data (plugin->views, view); + if (plugin->is_visible) { + if (view_load (view)) + ply_list_append_data (plugin->views, view); + else + view_free (view); + } else { + ply_list_append_data (plugin->views, view); + } } static void @@ -763,7 +777,6 @@ remove_pixel_display (ply_boot_splash_plugin_t *plugin, next_node = ply_list_get_next_node (plugin->views, node); if (view->display == display) { - ply_pixel_display_set_draw_handler (view->display, NULL, NULL); view_free (view); ply_list_remove_node (plugin->views, node); return; @@ -806,6 +819,8 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, return false; } + plugin->is_visible = true; + ply_trace ("starting boot animation"); start_animation (plugin); @@ -940,6 +955,8 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin, { assert (plugin != NULL); + plugin->is_visible = false; + if (plugin->loop != NULL) { stop_animation (plugin); diff --git a/src/plugins/splash/script/script-lib-sprite.c b/src/plugins/splash/script/script-lib-sprite.c index f292d90..c49297d 100644 --- a/src/plugins/splash/script/script-lib-sprite.c +++ b/src/plugins/splash/script/script-lib-sprite.c @@ -416,6 +416,22 @@ static script_return_t sprite_window_set_background_bottom_color (script_state_t return script_return_obj_null (); } +static void script_lib_draw_brackground (ply_pixel_buffer_t *pixel_buffer, + ply_rectangle_t *clip_area, + script_lib_sprite_data_t *data) +{ + if (data->background_color_start == data->background_color_end) { + ply_pixel_buffer_fill_with_hex_color (pixel_buffer, + clip_area, + data->background_color_start); + } else { + ply_pixel_buffer_fill_with_gradient (pixel_buffer, + clip_area, + data->background_color_start, + data->background_color_end); + } +} + static void script_lib_sprite_draw_area (script_lib_display_t *display, ply_pixel_buffer_t *pixel_buffer, int x, @@ -425,6 +441,7 @@ static void script_lib_sprite_draw_area (script_lib_display_t *display, { ply_rectangle_t clip_area; ply_list_node_t *node; + sprite_t *sprite; script_lib_sprite_data_t *data = display->data; clip_area.x = x; @@ -432,22 +449,33 @@ static void script_lib_sprite_draw_area (script_lib_display_t *display, clip_area.width = width; clip_area.height = height; - if (data->background_color_start == data->background_color_end) { - ply_pixel_buffer_fill_with_hex_color (pixel_buffer, - &clip_area, - data->background_color_start); + + node = ply_list_get_first_node (data->sprite_list); + sprite = ply_list_node_get_data (node); + + /* Check If the first sprite should be rendered opaque */ + if (sprite->image && !sprite->remove_me && + ply_pixel_buffer_is_opaque (sprite->image) && sprite->opacity == 1.0) { + int position_x = sprite->x - display->x; + int position_y = sprite->y - display->y; + + /* In that case only draw the background if the sprite doesn't + * cover the complete area */ + if (position_x > x || position_y > y || + (ply_pixel_buffer_get_width (sprite->image) + position_x) < (x + width) || + (ply_pixel_buffer_get_height (sprite->image) + position_y) < (y + height)) + script_lib_draw_brackground (pixel_buffer, &clip_area, data); } else { - ply_pixel_buffer_fill_with_gradient (pixel_buffer, - &clip_area, - data->background_color_start, - data->background_color_end); + script_lib_draw_brackground (pixel_buffer, &clip_area, data); } + for (node = ply_list_get_first_node (data->sprite_list); node; node = ply_list_get_next_node (data->sprite_list, node)) { - sprite_t *sprite = ply_list_node_get_data (node); int position_x, position_y; + sprite = ply_list_node_get_data (node); + if (!sprite->image) continue; if (sprite->remove_me) continue; if (sprite->opacity < 0.011) continue; diff --git a/src/plugins/splash/space-flares/plugin.c b/src/plugins/splash/space-flares/plugin.c index 5212c38..5af99c1 100644 --- a/src/plugins/splash/space-flares/plugin.c +++ b/src/plugins/splash/space-flares/plugin.c @@ -1387,7 +1387,14 @@ add_pixel_display (ply_boot_splash_plugin_t *plugin, (ply_pixel_display_draw_handler_t) on_draw, view); - ply_list_append_data (plugin->views, view); + if (plugin->is_visible) { + if (view_load (view)) + ply_list_append_data (plugin->views, view); + else + view_free (view); + } else { + ply_list_append_data (plugin->views, view); + } } static void diff --git a/src/plugins/splash/text/plugin.c b/src/plugins/splash/text/plugin.c index 468bb89..8260daa 100644 --- a/src/plugins/splash/text/plugin.c +++ b/src/plugins/splash/text/plugin.c @@ -472,6 +472,9 @@ add_text_display (ply_boot_splash_plugin_t *plugin, on_draw, view); ply_list_append_data (plugin->views, view); + + if (plugin->is_animating) + view_start_animation (view); } static void @@ -553,7 +556,9 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin, next_node = ply_list_get_next_node (plugin->views, node); ply_text_step_bar_set_percent_done (view->step_bar, percent_done); - ply_text_step_bar_draw (view->step_bar); + + if (plugin->is_animating) + ply_text_step_bar_draw (view->step_bar); node = next_node; } diff --git a/src/plugins/splash/throbgress/plugin.c b/src/plugins/splash/throbgress/plugin.c index c105e02..a1c8a90 100644 --- a/src/plugins/splash/throbgress/plugin.c +++ b/src/plugins/splash/throbgress/plugin.c @@ -625,7 +625,14 @@ add_pixel_display (ply_boot_splash_plugin_t *plugin, (ply_pixel_display_draw_handler_t) on_draw, view); - ply_list_append_data (plugin->views, view); + if (plugin->is_visible) { + if (view_load (view)) + ply_list_append_data (plugin->views, view); + else + view_free (view); + } else { + ply_list_append_data (plugin->views, view); + } } static void diff --git a/src/plugins/splash/tribar/plugin.c b/src/plugins/splash/tribar/plugin.c index 0dcd7f8..ecc17ea 100644 --- a/src/plugins/splash/tribar/plugin.c +++ b/src/plugins/splash/tribar/plugin.c @@ -478,6 +478,9 @@ add_text_display (ply_boot_splash_plugin_t *plugin, on_draw, view); ply_list_append_data (plugin->views, view); + + if (plugin->is_animating) + view_start_animation (view); } static void @@ -559,7 +562,9 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin, next_node = ply_list_get_next_node (plugin->views, node); ply_text_progress_bar_set_percent_done (view->progress_bar, percent_done); - ply_text_progress_bar_draw (view->progress_bar); + + if (plugin->is_animating) + ply_text_progress_bar_draw (view->progress_bar); node = next_node; } diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c index 0899ace..070741d 100644 --- a/src/plugins/splash/two-step/plugin.c +++ b/src/plugins/splash/two-step/plugin.c @@ -267,11 +267,15 @@ view_load (view_t *view) view_load_end_animation (view); - ply_trace ("loading progress animation"); - if (!ply_progress_animation_load (view->progress_animation)) { - ply_trace ("optional progress animation wouldn't load"); - ply_progress_animation_free (view->progress_animation); - view->progress_animation = NULL; + if (view->progress_animation != NULL) { + ply_trace ("loading progress animation"); + if (!ply_progress_animation_load (view->progress_animation)) { + ply_trace ("optional progress animation wouldn't load"); + ply_progress_animation_free (view->progress_animation); + view->progress_animation = NULL; + } + } else { + ply_trace ("this theme has no progress animation"); } if (view->throbber != NULL) { @@ -875,7 +879,12 @@ draw_background (view_t *view, if (view->background_image != NULL) { uint32_t *data; data = ply_image_get_data (view->background_image); - ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &area, data); + + /* We must pass NULL as fill area, because the fill area + must be sized as the image we're sourcing from, otherwise + sampling does not work + */ + ply_pixel_buffer_fill_with_argb32_data_with_clip (pixel_buffer, NULL, NULL, data); } if (plugin->watermark_image != NULL) { @@ -986,7 +995,14 @@ add_pixel_display (ply_boot_splash_plugin_t *plugin, ply_pixel_display_set_draw_handler (view->display, (ply_pixel_display_draw_handler_t) on_draw, view); - ply_list_append_data (plugin->views, view); + if (plugin->is_visible) { + if (view_load (view)) + ply_list_append_data (plugin->views, view); + else + view_free (view); + } else { + ply_list_append_data (plugin->views, view); + } } static void @@ -1329,8 +1345,8 @@ system_update (ply_boot_splash_plugin_t *plugin, view = ply_list_node_get_data (node); next_node = ply_list_get_next_node (plugin->views, node); - ply_progress_animation_set_percent_done (view->progress_animation, - (double) progress / 100.f); + if (view->progress_animation != NULL) + ply_progress_animation_set_percent_done (view->progress_animation, (double) progress / 100.f); node = next_node; } } diff --git a/src/plymouthd.defaults b/src/plymouthd.defaults index fc48b15..4d3b6d4 100644 --- a/src/plymouthd.defaults +++ b/src/plymouthd.defaults @@ -3,3 +3,4 @@ [Daemon] Theme=spinner ShowDelay=5 +DeviceTimeout=5 diff --git a/systemd-units/Makefile.am b/systemd-units/Makefile.am index 89355ac..b1d843b 100644 --- a/systemd-units/Makefile.am +++ b/systemd-units/Makefile.am @@ -50,21 +50,20 @@ install-data-hook: $(LN_S) ../plymouth-halt.service) uninstall-hook: - rm -f \ (cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/initrd-switch-root.target.wants && \ - rm -f plymouth-start.service plymouth-switch-root.service) \ + rm -f plymouth-start.service plymouth-switch-root.service) (cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/sysinit.target.wants && \ - rm -f plymouth-start.service plymouth-read-write.service) \ + rm -f plymouth-start.service plymouth-read-write.service) (cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/multi-user.target.wants && \ - rm -f plymouth-quit.service plymouth-quit-wait.service) \ + rm -f plymouth-quit.service plymouth-quit-wait.service) (cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/reboot.target.wants && \ - rm -f plymouth-reboot.service) \ + rm -f plymouth-reboot.service) (cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/kexec.target.wants && \ - rm -f plymouth-kexec.service) \ + rm -f plymouth-kexec.service) (cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/poweroff.target.wants && \ - rm -f plymouth-poweroff.service) \ + rm -f plymouth-poweroff.service) (cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/halt.target.wants && \ - rm -f plymouth-halt.service) \ + rm -f plymouth-halt.service) rmdir --ignore-fail-on-non-empty \ $(DESTDIR)$(SYSTEMD_UNIT_DIR)/sysinit.target.wants \ $(DESTDIR)$(SYSTEMD_UNIT_DIR)/multi-user.target.wants \ diff --git a/themes/script/script.script b/themes/script/script.script index 7ea9d5e..25a2f2b 100644 --- a/themes/script/script.script +++ b/themes/script/script.script @@ -152,27 +152,19 @@ Plymouth.SetQuitFunction(quit_callback); #----------------------------------------- Message -------------------------------- -message_sprites = []; -message_sprite_count = 0; -message_sprite_y = 10; +message_sprite = Sprite(); +message_sprite.SetPosition(10, 10, 10000); fun display_message_callback (text) { my_image = Image.Text(text, 1, 1, 1); - message_sprites[message_sprite_count] = Sprite(my_image); - message_sprites[message_sprite_count].SetPosition(10, message_sprite_y, 10000); - message_sprites[message_sprite_count].text = text; - message_sprite_count++; - message_sprite_y += my_image.GetHeight(); + message_sprite.SetImage(my_image); } fun hide_message_callback (text) { - for (i = 0; i < message_sprite_count; i++) - { - if (message_sprites[i].text == text) - message_sprites[i] = NULL; - } + message_sprite = Sprite(); + message_sprite.SetPosition(10, 10, 10000); } Plymouth.SetDisplayMessageFunction (display_message_callback);