diff options
author | Leo <thinkabit.ukim@gmail.com> | 2020-01-29 00:19:19 +0100 |
---|---|---|
committer | Leo <thinkabit.ukim@gmail.com> | 2020-01-29 00:19:19 +0100 |
commit | 7b666d29c84d5cad788815a1c9133a5c38c5f410 (patch) | |
tree | 7e0e9f567ea66bc0c2629499454d07545f6d674b /community/plymouth | |
parent | c10f2d9b183c51fddfcb61024d01a5bd21197694 (diff) | |
download | aports-7b666d29c84d5cad788815a1c9133a5c38c5f410.tar.bz2 aports-7b666d29c84d5cad788815a1c9133a5c38c5f410.tar.xz |
Remove stale patches in community/
Diffstat (limited to 'community/plymouth')
-rw-r--r-- | community/plymouth/plymouth-add-sysmacros.patch | 10 | ||||
-rw-r--r-- | community/plymouth/plymouth-git-master-20170123.patch | 5399 |
2 files changed, 0 insertions, 5409 deletions
diff --git a/community/plymouth/plymouth-add-sysmacros.patch b/community/plymouth/plymouth-add-sysmacros.patch deleted file mode 100644 index 90c011955f..0000000000 --- a/community/plymouth/plymouth-add-sysmacros.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/src/libply-splash-core/ply-terminal.c -+++ b/src/libply-splash-core/ply-terminal.c -@@ -32,6 +32,7 @@ - #include <sys/socket.h> - #include <sys/stat.h> - #include <sys/types.h> -+#include <sys/sysmacros.h> - #include <termios.h> - #include <unistd.h> - #include <wchar.h> diff --git a/community/plymouth/plymouth-git-master-20170123.patch b/community/plymouth/plymouth-git-master-20170123.patch deleted file mode 100644 index 6ab412fa5d..0000000000 --- a/community/plymouth/plymouth-git-master-20170123.patch +++ /dev/null @@ -1,5399 +0,0 @@ -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 <sys/stat.h> - #include <sys/types.h> - -+#ifdef HAVE_UDEV - #include <libudev.h> -+#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 <stdbool.h> --#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 <stdlib.h> - #include <unistd.h> - -+#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 <rstrode@redhat.com> -- */ --#include "config.h" --#include "ply-seat.h" -- --#include <assert.h> --#include <errno.h> --#include <stdint.h> --#include <stdio.h> --#include <stdlib.h> --#include <unistd.h> -- --#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 <rstrode@redhat.com> -- */ --#ifndef PLY_SEAT_H --#define PLY_SEAT_H -- --#include <stdarg.h> --#include <stdbool.h> --#include <stdint.h> --#include <unistd.h> -- --#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 <rstrode@redhat.com> -- */ --#ifndef PLY_RENDERER_DRIVER_H --#define PLY_RENDERER_DRIVER_H -- --#include <stdbool.h> --#include <stdint.h> -- --#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 <arpa/inet.h> --#include <assert.h> --#include <errno.h> --#include <fcntl.h> --#include <signal.h> --#include <string.h> --#include <stdbool.h> --#include <stdint.h> --#include <stdio.h> --#include <stdlib.h> --#include <sys/ioctl.h> --#include <sys/mman.h> --#include <sys/stat.h> --#include <sys/types.h> --#include <values.h> --#include <unistd.h> -- --#include <drm.h> --#include <xf86drm.h> --#include <xf86drmMode.h> -- --#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); |