From d338e6becb28edc4c4bf7aee1a7a5a38a10a3cd8 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 26 Aug 2009 23:09:46 -0400 Subject: [PATCH 01/43] [libply] Drop terminal class It was a really lame small wrapper around creating pseudoterminals. The wrapper didn't buy anything and the name ply-terminal would be better used for managing tty settings, etc. --- src/libply/Makefile.am | 2 - src/libply/ply-terminal-session.c | 71 +++++-- src/libply/ply-terminal.c | 201 ------------------ src/libply/ply-terminal.h | 43 ---- src/libply/tests/Makefile.am | 1 - src/libply/tests/ply-terminal-session-test.am | 2 - src/libply/tests/ply-terminal-test.am | 14 -- 7 files changed, 57 insertions(+), 277 deletions(-) delete mode 100644 src/libply/ply-terminal.c delete mode 100644 src/libply/ply-terminal.h delete mode 100644 src/libply/tests/ply-terminal-test.am diff --git a/src/libply/Makefile.am b/src/libply/Makefile.am index e0cb84de..5c9a8bdb 100644 --- a/src/libply/Makefile.am +++ b/src/libply/Makefile.am @@ -23,7 +23,6 @@ libply_HEADERS = \ ply-logger.h \ ply-key-file.h \ ply-progress.h \ - ply-terminal.h \ ply-terminal-session.h \ ply-trigger.h \ ply-utils.h @@ -45,7 +44,6 @@ libply_la_SOURCES = ply-event-loop.c \ ply-logger.c \ ply-key-file.c \ ply-progress.c \ - ply-terminal.c \ ply-terminal-session.c \ ply-trigger.c \ ply-utils.c diff --git a/src/libply/ply-terminal-session.c b/src/libply/ply-terminal-session.c index 2a4ca8db..68f487fd 100644 --- a/src/libply/ply-terminal-session.c +++ b/src/libply/ply-terminal-session.c @@ -39,12 +39,11 @@ #include "ply-event-loop.h" #include "ply-logger.h" -#include "ply-terminal.h" #include "ply-utils.h" struct _ply_terminal_session { - ply_terminal_t *terminal; + int pseudoterminal_master_fd; ply_logger_t *logger; ply_event_loop_t *loop; char **argv; @@ -71,7 +70,7 @@ ply_terminal_session_open_console (ply_terminal_session_t *session) int fd; const char *terminal_name; - terminal_name = ply_terminal_get_device_name (session->terminal); + terminal_name = ptsname (session->pseudoterminal_master_fd); fd = open (terminal_name, O_RDONLY); @@ -128,8 +127,8 @@ ply_terminal_session_new (const char * const *argv) assert (argv == NULL || argv[0] != NULL); session = calloc (1, sizeof (ply_terminal_session_t)); + session->pseudoterminal_master_fd = -1; session->argv = argv == NULL ? NULL : ply_copy_string_array (argv); - session->terminal = ply_terminal_new (); session->logger = ply_logger_new (); session->is_running = false; session->console_is_redirected = false; @@ -147,7 +146,8 @@ ply_terminal_session_free (ply_terminal_session_t *session) ply_logger_free (session->logger); ply_free_string_array (session->argv); - ply_terminal_free (session->terminal); + + close (session->pseudoterminal_master_fd); free (session); } @@ -181,7 +181,7 @@ ply_terminal_session_redirect_console (ply_terminal_session_t *session) assert (session != NULL); - terminal_name = ply_terminal_get_device_name (session->terminal); + terminal_name = ptsname (session->pseudoterminal_master_fd); assert (terminal_name != NULL); @@ -218,6 +218,49 @@ ply_terminal_session_unredirect_console (ply_terminal_session_t *session) session->console_is_redirected = false; } +static void +close_pseudoterminal (ply_terminal_session_t *session) +{ + close (session->pseudoterminal_master_fd); + session->pseudoterminal_master_fd = -1; +} + +static bool +open_pseudoterminal (ply_terminal_session_t *session) +{ + ply_trace ("opening device '/dev/ptmx'"); + session->pseudoterminal_master_fd = posix_openpt (O_RDWR | O_NOCTTY); + + if (session->pseudoterminal_master_fd < 0) + return false; + + ply_trace (" opened device '/dev/ptmx'"); + + ply_trace ("creating pseudoterminal"); + if (grantpt (session->pseudoterminal_master_fd) < 0) + { + ply_save_errno (); + ply_trace ("could not create psuedoterminal: %m"); + close_pseudoterminal (session); + ply_restore_errno (); + return false; + } + ply_trace ("done creating pseudoterminal"); + + ply_trace ("unlocking pseudoterminal"); + if (unlockpt (session->pseudoterminal_master_fd) < 0) + { + ply_save_errno (); + close_pseudoterminal (session); + ply_restore_errno (); + return false; + } + ply_trace ("unlocked pseudoterminal"); + + return true; +} + + bool ply_terminal_session_run (ply_terminal_session_t *session, ply_terminal_session_flags_t flags, @@ -240,7 +283,7 @@ ply_terminal_session_run (ply_terminal_session_t *session, (flags & PLY_TERMINAL_SESSION_FLAGS_REDIRECT_CONSOLE) != 0; ply_trace ("creating terminal device"); - if (!ply_terminal_create_device (session->terminal)) + if (!open_pseudoterminal (session)) return false; ply_trace ("done creating terminal device"); @@ -250,7 +293,7 @@ ply_terminal_session_run (ply_terminal_session_t *session, !ply_terminal_session_redirect_console (session)) { ply_save_errno (); - ply_terminal_destroy_device (session->terminal); + close_pseudoterminal (session); ply_restore_errno (); return false; } @@ -264,7 +307,7 @@ ply_terminal_session_run (ply_terminal_session_t *session, { ply_save_errno (); ply_terminal_session_unredirect_console (session); - ply_terminal_destroy_device (session->terminal); + close_pseudoterminal (session); ply_restore_errno (); return false; } @@ -316,12 +359,12 @@ ply_terminal_session_attach (ply_terminal_session_t *session, if (ptmx >= 0) { ply_trace ("ptmx passed in, using it"); - ply_terminal_set_fd(session->terminal, ptmx); + session->pseudoterminal_master_fd = ptmx; } else { ply_trace ("ptmx not passed in, creating one"); - if (!ply_terminal_create_device (session->terminal)) + if (!open_pseudoterminal (session)) { ply_trace ("could not create pseudo-terminal: %m"); return false; @@ -336,7 +379,7 @@ ply_terminal_session_attach (ply_terminal_session_t *session, !ply_terminal_session_redirect_console (session)) { ply_save_errno (); - ply_terminal_destroy_device (session->terminal); + close_pseudoterminal (session); ply_restore_errno (); return false; } @@ -370,7 +413,7 @@ ply_terminal_session_detach (ply_terminal_session_t *session) if (session->created_terminal_device) { ply_trace ("ptmx wasn't originally passed in, destroying created one"); - ply_terminal_destroy_device (session->terminal); + close_pseudoterminal (session); session->created_terminal_device = false; } @@ -386,7 +429,7 @@ ply_terminal_session_get_fd (ply_terminal_session_t *session) { assert (session != NULL); - return ply_terminal_get_fd (session->terminal); + return session->pseudoterminal_master_fd; } static void diff --git a/src/libply/ply-terminal.c b/src/libply/ply-terminal.c deleted file mode 100644 index 9ad293f1..00000000 --- a/src/libply/ply-terminal.c +++ /dev/null @@ -1,201 +0,0 @@ -/* ply-terminal.c - psuedoterminal abstraction - * - * Copyright (C) 2006, 2007 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: Kristian Høgsberg - * Ray Strode - */ -#include "config.h" -#include "ply-terminal.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ply-logger.h" -#include "ply-utils.h" - -struct _ply_terminal -{ - char *name; - int fd; -}; - -ply_terminal_t * -ply_terminal_new (void) -{ - ply_terminal_t *terminal; - - terminal = calloc (1, sizeof (ply_terminal_t)); - terminal->fd = -1; - - return terminal; -} - -void -ply_terminal_free (ply_terminal_t *terminal) -{ - assert (terminal != NULL); - - ply_terminal_destroy_device (terminal); - free (terminal); -} - -bool -ply_terminal_create_device (ply_terminal_t *terminal) -{ - assert (terminal != NULL); - assert (!ply_terminal_has_device (terminal)); - - ply_trace ("opening device '/dev/ptmx'"); - terminal->fd = posix_openpt (O_RDWR | O_NOCTTY); - - if (terminal->fd < 0) - return false; - - ply_trace (" opened device '/dev/ptmx'"); - - ply_trace ("creating pseudoterminal"); - if (grantpt (terminal->fd) < 0) - { - ply_save_errno (); - ply_trace ("could not create psuedoterminal: %m"); - ply_terminal_destroy_device (terminal); - ply_restore_errno (); - return false; - } - ply_trace ("done creating pseudoterminal"); - - ply_trace ("unlocking pseudoterminal"); - if (unlockpt (terminal->fd) < 0) - { - ply_save_errno (); - ply_terminal_destroy_device (terminal); - ply_restore_errno (); - return false; - } - ply_trace ("unlocked pseudoterminal"); - - terminal->name = strdup (ptsname (terminal->fd)); - ply_trace ("pseudoterminal '%s' ready for action", terminal->name); - - return true; -} - -bool -ply_terminal_has_device (ply_terminal_t *terminal) -{ - assert (terminal != NULL); - - return terminal->fd >= 0; -} - -void -ply_terminal_destroy_device (ply_terminal_t *terminal) -{ - assert (terminal != NULL); - - free (terminal->name); - terminal->name = NULL; - - close (terminal->fd); - terminal->fd = -1; -} - -int -ply_terminal_get_fd (ply_terminal_t *terminal) -{ - assert (terminal != NULL); - - return terminal->fd; -} - -void -ply_terminal_set_fd (ply_terminal_t *terminal, int fd) -{ - assert (terminal != NULL); - - terminal->fd = fd; - - if (terminal->name) - { - free(terminal->name); - terminal->name = NULL; - } - - if (terminal->fd >= 0) - terminal->name = strdup (ptsname (terminal->fd)); -} - -const char * -ply_terminal_get_device_name (ply_terminal_t *terminal) -{ - assert (terminal != NULL); - assert (ply_terminal_has_device (terminal)); - - assert (terminal->name != NULL); - return terminal->name; -} - -#ifdef PLY_TERMINAL_ENABLE_TEST - -#include - -int -main (int argc, - char **argv) -{ - ply_terminal_t *terminal; - const char *name; - uint8_t byte; - int exit_code; - - exit_code = 0; - - terminal = ply_terminal_new (); - - if (!ply_terminal_create_device (terminal)) - { - exit_code = errno; - perror ("could not open new terminal"); - return exit_code; - } - - name = ply_terminal_get_device_name (terminal); - printf ("terminal name is '%s'\n", name); - - while (read (ply_terminal_get_fd (terminal), - &byte, sizeof (byte)) == 1) - printf ("%c", byte); - - ply_terminal_free (terminal); - - return exit_code; -} - -#endif /* PLY_TERMINAL_ENABLE_TEST */ -/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/libply/ply-terminal.h b/src/libply/ply-terminal.h deleted file mode 100644 index df5af542..00000000 --- a/src/libply/ply-terminal.h +++ /dev/null @@ -1,43 +0,0 @@ -/* ply-terminal.h - psuedoterminal abstraction - * - * Copyright (C) 2007 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written By: Ray Strode - */ -#ifndef PLY_TERMINAL_H -#define PLY_TERMINAL_H - -#include -#include -#include - -typedef struct _ply_terminal ply_terminal_t; - -#ifndef PLY_HIDE_FUNCTION_DECLARATIONS -ply_terminal_t *ply_terminal_new (void); -void ply_terminal_free (ply_terminal_t *terminal); -bool ply_terminal_create_device (ply_terminal_t *terminal); -bool ply_terminal_has_device (ply_terminal_t *terminal); -void ply_terminal_destroy_device (ply_terminal_t *terminal); -int ply_terminal_get_fd (ply_terminal_t *terminal); -void ply_terminal_set_fd (ply_terminal_t *terminal, int fd); -const char *ply_terminal_get_device_name (ply_terminal_t *terminal); -#endif - -#endif /* PLY_TERMINAL_H */ -/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/libply/tests/Makefile.am b/src/libply/tests/Makefile.am index 9ef83381..49ba5760 100644 --- a/src/libply/tests/Makefile.am +++ b/src/libply/tests/Makefile.am @@ -6,7 +6,6 @@ TESTS = if ENABLE_TESTS include $(srcdir)/ply-frame-buffer-test.am -include $(srcdir)/ply-terminal-test.am include $(srcdir)/ply-terminal-session-test.am include $(srcdir)/ply-logger-test.am include $(srcdir)/ply-array-test.am diff --git a/src/libply/tests/ply-terminal-session-test.am b/src/libply/tests/ply-terminal-session-test.am index 8206f39f..decb531b 100644 --- a/src/libply/tests/ply-terminal-session-test.am +++ b/src/libply/tests/ply-terminal-session-test.am @@ -14,7 +14,5 @@ ply_terminal_session_test_SOURCES = $(srcdir)/../ply-list.c \ $(srcdir)/../ply-event-loop.h \ $(srcdir)/../ply-event-loop.c \ - $(srcdir)/../ply-terminal.h \ - $(srcdir)/../ply-terminal.c \ $(srcdir)/../ply-terminal-session.h \ $(srcdir)/../ply-terminal-session.c diff --git a/src/libply/tests/ply-terminal-test.am b/src/libply/tests/ply-terminal-test.am deleted file mode 100644 index 67a25724..00000000 --- a/src/libply/tests/ply-terminal-test.am +++ /dev/null @@ -1,14 +0,0 @@ -TESTS += ply-terminal-test - -ply_terminal_test_CFLAGS = $(PLYMOUTH_CFLAGS) -DPLY_TERMINAL_ENABLE_TEST -ply_terminal_test_LDADD = $(PLYMOUTH_LIBS) - -ply_terminal_test_SOURCES = \ - $(srcdir)/../ply-list.h \ - $(srcdir)/../ply-list.c \ - $(srcdir)/../ply-logger.h \ - $(srcdir)/../ply-logger.c \ - $(srcdir)/../ply-utils.h \ - $(srcdir)/../ply-utils.c \ - $(srcdir)/../ply-terminal.h \ - $(srcdir)/../ply-terminal.c From 376742c50f2909ae763d909e7004feb9366156ef Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Thu, 27 Aug 2009 01:26:55 -0400 Subject: [PATCH 02/43] [event-loop] Add ply_event_loop_get_default () The event loop is used all through out the code for many different things. In order to use it in all those various bits of code, it's getting passed around a lot. This adds a lot of complexity to the code. The event loop should probably be a standard resource that all parts of the code have free access to in the same vein as the logging apis. This commit adds a new function ply_event_loop_get_default () and makes main use it and pass it along. Subsequent commits may clean up all the places that take an event loop to just use this instead. --- src/libply/ply-event-loop.c | 11 +++++++++++ src/libply/ply-event-loop.h | 1 + src/main.c | 5 +---- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/libply/ply-event-loop.c b/src/libply/ply-event-loop.c index 2c03a528..33bd52c7 100644 --- a/src/libply/ply-event-loop.c +++ b/src/libply/ply-event-loop.c @@ -489,6 +489,17 @@ ply_event_loop_new (void) return loop; } +ply_event_loop_t * +ply_event_loop_get_default (void) +{ + static ply_event_loop_t *loop = NULL; + + if (loop == NULL) + loop = ply_event_loop_new (); + + return loop; +} + static void ply_event_loop_free_exit_closures (ply_event_loop_t *loop) { diff --git a/src/libply/ply-event-loop.h b/src/libply/ply-event-loop.h index 98b9cd17..ae29d285 100644 --- a/src/libply/ply-event-loop.h +++ b/src/libply/ply-event-loop.h @@ -48,6 +48,7 @@ typedef void (* ply_event_loop_timeout_handler_t) (void *user_data, #ifndef PLY_HIDE_FUNCTION_DECLARATIONS ply_event_loop_t *ply_event_loop_new (void); void ply_event_loop_free (ply_event_loop_t *loop); +ply_event_loop_t *ply_event_loop_get_default (void); ply_fd_watch_t *ply_event_loop_watch_fd (ply_event_loop_t *loop, int fd, ply_event_loop_fd_status_t status, diff --git a/src/main.c b/src/main.c index a77c45b6..3b40afab 100644 --- a/src/main.c +++ b/src/main.c @@ -1359,7 +1359,7 @@ main (int argc, state.command_parser = ply_command_parser_new ("plymouthd", "Boot splash control server"); - state.loop = ply_event_loop_new (); + state.loop = ply_event_loop_get_default (); ply_command_parser_add_options (state.command_parser, "help", "This help message", PLY_COMMAND_OPTION_TYPE_FLAG, @@ -1526,9 +1526,6 @@ main (int argc, ply_buffer_free (state.boot_buffer); ply_progress_free (state.progress); - ply_trace ("freeing event loop"); - ply_event_loop_free (state.loop); - ply_trace ("exiting with code %d", exit_code); if (debug_buffer != NULL) From 97178ba76179d30a255f4253d89958fc413f831a Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 19 Aug 2009 23:55:43 -0400 Subject: [PATCH 03/43] [libply] Add new rectangle type Previously we were using ply_frame_buffer_area_t even when not dealing with a frame buffer area. This commit adds a new general purpose rectangle type to replace ply_frame_buffer_area_t. It has some convenience functions for operating on rectangles as well. --- src/libply/Makefile.am | 2 + src/libply/ply-rectangle.c | 294 +++++++++++++++++++++++++++++++++++++ src/libply/ply-rectangle.h | 105 +++++++++++++ 3 files changed, 401 insertions(+) create mode 100644 src/libply/ply-rectangle.c create mode 100644 src/libply/ply-rectangle.h diff --git a/src/libply/Makefile.am b/src/libply/Makefile.am index 5c9a8bdb..da145755 100644 --- a/src/libply/Makefile.am +++ b/src/libply/Makefile.am @@ -23,6 +23,7 @@ libply_HEADERS = \ ply-logger.h \ ply-key-file.h \ ply-progress.h \ + ply-rectangle.h \ ply-terminal-session.h \ ply-trigger.h \ ply-utils.h @@ -44,6 +45,7 @@ libply_la_SOURCES = ply-event-loop.c \ ply-logger.c \ ply-key-file.c \ ply-progress.c \ + ply-rectangle.c \ ply-terminal-session.c \ ply-trigger.c \ ply-utils.c diff --git a/src/libply/ply-rectangle.c b/src/libply/ply-rectangle.c new file mode 100644 index 00000000..22093936 --- /dev/null +++ b/src/libply/ply-rectangle.c @@ -0,0 +1,294 @@ +/* ply-rectangle.c + * + * Copyright (C) 2009 Red Hat, Inc. + * + * Based in part on some work by: + * Copyright (C) 2009 Charlie Brej + * + * 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: Charlie Brej + * Ray Strode + */ +#include "config.h" +#include "ply-list.h" +#include "ply-rectangle.h" + +bool +ply_rectangle_contains_point (ply_rectangle_t *rectangle, + long x, + long y) +{ + long top_edge; + long left_edge; + long right_edge; + long bottom_edge; + + top_edge = rectangle->y; + left_edge = rectangle->x; + right_edge = rectangle->x + rectangle->width - 1; + bottom_edge = rectangle->y + rectangle->height - 1; + + if (x < left_edge) + return false; + + if (y < top_edge) + return false; + + if (x > right_edge) + return false; + + if (y > bottom_edge) + return false; + + return true; +} + +bool +ply_rectangle_is_empty (ply_rectangle_t *rectangle) +{ + return rectangle->width == 0 || rectangle->height == 0; +} + +ply_rectangle_overlap_t +ply_rectangle_find_overlap (ply_rectangle_t *rectangle1, + ply_rectangle_t *rectangle2) +{ + ply_rectangle_overlap_t overlap; + + long rectangle1_top_edge; + long rectangle1_left_edge; + long rectangle1_right_edge; + long rectangle1_bottom_edge; + long rectangle2_top_edge; + long rectangle2_left_edge; + long rectangle2_right_edge; + long rectangle2_bottom_edge; + + rectangle1_top_edge = rectangle1->y; + rectangle1_left_edge = rectangle1->x; + rectangle1_right_edge = rectangle1->x + rectangle1->width - 1; + rectangle1_bottom_edge = rectangle1->y + rectangle1->height - 1; + + rectangle2_top_edge = rectangle2->y; + rectangle2_left_edge = rectangle2->x; + rectangle2_right_edge = rectangle2->x + rectangle2->width - 1; + rectangle2_bottom_edge = rectangle2->y + rectangle2->height - 1; + + overlap = 0; + + /* 1111111 + * 1122211 + * 1122211 + * 1111111 + */ + if (ply_rectangle_contains_point (rectangle1, + rectangle2_left_edge, + rectangle2_top_edge) && + ply_rectangle_contains_point (rectangle1, + rectangle2_right_edge, + rectangle2_bottom_edge)) + return PLY_RECTANGLE_OVERLAP_NO_EDGES; + + /* 2222222 + * 2211122 + * 2211122 + * 2222222 + */ + if (ply_rectangle_contains_point (rectangle2, + rectangle1_left_edge, + rectangle1_top_edge) && + ply_rectangle_contains_point (rectangle2, + rectangle1_right_edge, + rectangle1_bottom_edge)) + return PLY_RECTANGLE_OVERLAP_ALL_EDGES; + + /* 1111111 + * 11112222 + * 11112222 + * 1111111 + */ + if (ply_rectangle_contains_point (rectangle2, + rectangle1_right_edge, + rectangle2_top_edge) && + ply_rectangle_contains_point (rectangle2, + rectangle1_right_edge, + rectangle2_bottom_edge)) + overlap |= PLY_RECTANGLE_OVERLAP_RIGHT_EDGE; + + /* 222222 + * 11112222 + * 11112222 + * 222222 + */ + if (ply_rectangle_contains_point (rectangle1, + rectangle2_left_edge, + rectangle1_top_edge) && + ply_rectangle_contains_point (rectangle1, + rectangle2_left_edge, + rectangle1_bottom_edge)) + overlap |= PLY_RECTANGLE_OVERLAP_RIGHT_EDGE; + + /* 1111111 + * 22221111 + * 22221111 + * 1111111 + */ + if (ply_rectangle_contains_point (rectangle2, + rectangle1_left_edge, + rectangle2_top_edge) && + ply_rectangle_contains_point (rectangle2, + rectangle1_left_edge, + rectangle2_bottom_edge)) + overlap |= PLY_RECTANGLE_OVERLAP_LEFT_EDGE; + + /* 222222 + * 22221111 + * 22221111 + * 222222 + */ + if (ply_rectangle_contains_point (rectangle1, + rectangle2_right_edge, + rectangle1_top_edge) && + ply_rectangle_contains_point (rectangle1, + rectangle2_right_edge, + rectangle1_bottom_edge)) + overlap |= PLY_RECTANGLE_OVERLAP_LEFT_EDGE; + + /* + * 2222 + * 122221 + * 111111 + * 111111 + */ + if (ply_rectangle_contains_point (rectangle2, + rectangle2_left_edge, + rectangle1_top_edge) && + ply_rectangle_contains_point (rectangle2, + rectangle2_right_edge, + rectangle1_top_edge)) + overlap |= PLY_RECTANGLE_OVERLAP_TOP_EDGE; + + /* + * 2222222 + * 2211122 + * 111 + */ + if (ply_rectangle_contains_point (rectangle1, + rectangle1_left_edge, + rectangle2_bottom_edge) && + ply_rectangle_contains_point (rectangle1, + rectangle1_right_edge, + rectangle2_bottom_edge)) + overlap |= PLY_RECTANGLE_OVERLAP_TOP_EDGE; + + /* + * 111111 + * 111111 + * 122221 + * 2222 + */ + if (ply_rectangle_contains_point (rectangle1, + rectangle1_left_edge, + rectangle2_top_edge) && + ply_rectangle_contains_point (rectangle1, + rectangle1_right_edge, + rectangle2_top_edge)) + overlap |= PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE; + + /* + * 111 + * 2211122 + * 2222222 + */ + if (ply_rectangle_contains_point (rectangle2, + rectangle2_left_edge, + rectangle1_bottom_edge) && + ply_rectangle_contains_point (rectangle2, + rectangle2_right_edge, + rectangle1_bottom_edge)) + overlap |= PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE; + + return overlap; +} + +void +ply_rectangle_intersect (ply_rectangle_t *rectangle1, + ply_rectangle_t *rectangle2, + ply_rectangle_t *result) +{ + + long rectangle1_top_edge; + long rectangle1_left_edge; + long rectangle1_right_edge; + long rectangle1_bottom_edge; + long rectangle2_top_edge; + long rectangle2_left_edge; + long rectangle2_right_edge; + long rectangle2_bottom_edge; + long result_top_edge; + long result_left_edge; + long result_right_edge; + long result_bottom_edge; + + if (ply_rectangle_is_empty (rectangle1)) + { + *result = *rectangle1; + return; + } + + if (ply_rectangle_is_empty (rectangle2)) + { + *result = *rectangle2; + return; + } + + rectangle1_top_edge = rectangle1->y; + rectangle1_left_edge = rectangle1->x; + rectangle1_right_edge = rectangle1->x + rectangle1->width - 1; + rectangle1_bottom_edge = rectangle1->y + rectangle1->height - 1; + + rectangle2_top_edge = rectangle2->y; + rectangle2_left_edge = rectangle2->x; + rectangle2_right_edge = rectangle2->x + rectangle2->width - 1; + rectangle2_bottom_edge = rectangle2->y + rectangle2->height - 1; + + result_top_edge = MAX (rectangle1_top_edge, rectangle2_top_edge); + result_left_edge = MAX (rectangle1_left_edge, rectangle2_left_edge); + result_right_edge = MIN (rectangle1_right_edge, rectangle2_right_edge); + result_bottom_edge = MIN (rectangle1_bottom_edge, rectangle2_bottom_edge); + + result->x = result_left_edge; + result->y = result_top_edge; + + if (result_right_edge >= result_left_edge) + result->width = result_right_edge - result_left_edge + 1; + else + result->width = 0; + + if (result_bottom_edge >= result_top_edge) + result->height = result_bottom_edge - result_top_edge + 1; + else + result->height = 0; + + if (ply_rectangle_is_empty (result)) + { + result->width = 0; + result->height = 0; + } +} + +/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/libply/ply-rectangle.h b/src/libply/ply-rectangle.h new file mode 100644 index 00000000..bdbb6f4c --- /dev/null +++ b/src/libply/ply-rectangle.h @@ -0,0 +1,105 @@ +/* ply-rectangle.h + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode + */ +#ifndef PLY_RECTANGLE_H +#define PLY_RECTANGLE_H + +#include +#include + +#include "ply-utils.h" + +typedef struct _ply_rectangle ply_rectangle_t; + +struct _ply_rectangle +{ + long x; + long y; + unsigned long width; + unsigned long height; +}; + +typedef enum +{ + PLY_RECTANGLE_OVERLAP_NONE = 0, + PLY_RECTANGLE_OVERLAP_TOP_EDGE = 1 << 0, + PLY_RECTANGLE_OVERLAP_LEFT_EDGE = 1 << 1, + PLY_RECTANGLE_OVERLAP_RIGHT_EDGE = 1 << 2, + PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE = 1 << 3, + PLY_RECTANGLE_OVERLAP_TOP_AND_LEFT_EDGES = + PLY_RECTANGLE_OVERLAP_TOP_EDGE | + PLY_RECTANGLE_OVERLAP_LEFT_EDGE, + PLY_RECTANGLE_OVERLAP_TOP_AND_RIGHT_EDGES = + PLY_RECTANGLE_OVERLAP_TOP_EDGE | + PLY_RECTANGLE_OVERLAP_RIGHT_EDGE, + PLY_RECTANGLE_OVERLAP_TOP_AND_SIDE_EDGES = + PLY_RECTANGLE_OVERLAP_TOP_EDGE | + PLY_RECTANGLE_OVERLAP_LEFT_EDGE | + PLY_RECTANGLE_OVERLAP_RIGHT_EDGE, + PLY_RECTANGLE_OVERLAP_BOTTOM_AND_LEFT_EDGES = + PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE | + PLY_RECTANGLE_OVERLAP_LEFT_EDGE, + PLY_RECTANGLE_OVERLAP_BOTTOM_AND_RIGHT_EDGES = + PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE | + PLY_RECTANGLE_OVERLAP_RIGHT_EDGE, + PLY_RECTANGLE_OVERLAP_BOTTOM_AND_SIDE_EDGES = + PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE | + PLY_RECTANGLE_OVERLAP_LEFT_EDGE | + PLY_RECTANGLE_OVERLAP_RIGHT_EDGE, + PLY_RECTANGLE_OVERLAP_SIDE_EDGES = + PLY_RECTANGLE_OVERLAP_LEFT_EDGE | + PLY_RECTANGLE_OVERLAP_RIGHT_EDGE, + PLY_RECTANGLE_OVERLAP_TOP_AND_BOTTOM_EDGES = + PLY_RECTANGLE_OVERLAP_TOP_EDGE | + PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE, + PLY_RECTANGLE_OVERLAP_TOP_LEFT_AND_BOTTOM_EDGES = + PLY_RECTANGLE_OVERLAP_TOP_EDGE | + PLY_RECTANGLE_OVERLAP_LEFT_EDGE | + PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE, + PLY_RECTANGLE_OVERLAP_TOP_RIGHT_AND_BOTTOM_EDGES = + PLY_RECTANGLE_OVERLAP_TOP_EDGE | + PLY_RECTANGLE_OVERLAP_RIGHT_EDGE | + PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE, + PLY_RECTANGLE_OVERLAP_ALL_EDGES = + PLY_RECTANGLE_OVERLAP_TOP_EDGE | + PLY_RECTANGLE_OVERLAP_LEFT_EDGE | + PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE | + PLY_RECTANGLE_OVERLAP_RIGHT_EDGE, + PLY_RECTANGLE_OVERLAP_NO_EDGES = 1 << 4, +} ply_rectangle_overlap_t; + +#ifndef PLY_HIDE_FUNCTION_DECLARATIONS +bool ply_rectangle_contains_point (ply_rectangle_t *rectangle, + long x, + long y); + +bool ply_rectangle_is_empty (ply_rectangle_t *rectangle); + +ply_rectangle_overlap_t ply_rectangle_find_overlap (ply_rectangle_t *rectangle1, + ply_rectangle_t *rectangle2); + +void ply_rectangle_intersect (ply_rectangle_t *rectangle1, + ply_rectangle_t *rectangle2, + ply_rectangle_t *result); +#endif + +#endif /* PLY_RECTANGLE_H */ +/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ From b032e6d4f4acf1ad371d4a810ef8362ebcf4d264 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 19 Aug 2009 23:55:43 -0400 Subject: [PATCH 04/43] [libply] Add new region class Sometimes it's necessary to deal with a disjoint set of rectangles together. One big example is when keeping track of which parts of the screen have changed. Another example would be for non-rectangular clip masks. This commit adds a new region class to simplify the handling of these types of cases. --- src/libply/Makefile.am | 2 + src/libply/ply-region.c | 390 ++++++++++++++++++++++++++++++++++++++++ src/libply/ply-region.h | 47 +++++ 3 files changed, 439 insertions(+) create mode 100644 src/libply/ply-region.c create mode 100644 src/libply/ply-region.h diff --git a/src/libply/Makefile.am b/src/libply/Makefile.am index da145755..f87bf25d 100644 --- a/src/libply/Makefile.am +++ b/src/libply/Makefile.am @@ -24,6 +24,7 @@ libply_HEADERS = \ ply-key-file.h \ ply-progress.h \ ply-rectangle.h \ + ply-region.h \ ply-terminal-session.h \ ply-trigger.h \ ply-utils.h @@ -46,6 +47,7 @@ libply_la_SOURCES = ply-event-loop.c \ ply-key-file.c \ ply-progress.c \ ply-rectangle.c \ + ply-region.c \ ply-terminal-session.c \ ply-trigger.c \ ply-utils.c diff --git a/src/libply/ply-region.c b/src/libply/ply-region.c new file mode 100644 index 00000000..ec6ca5d7 --- /dev/null +++ b/src/libply/ply-region.c @@ -0,0 +1,390 @@ +/* ply-region.c + * + * Copyright (C) 2009 Red Hat, Inc. + * + * Based in part on some work by: + * Copyright (C) 2009 Charlie Brej + * + * 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: Charlie Brej + * Ray Strode + */ +#include "config.h" +#include "ply-region.h" + +#include +#include + +#include "ply-list.h" +#include "ply-rectangle.h" + +struct _ply_region +{ + ply_list_t *rectangle_list; +}; + +ply_region_t * +ply_region_new (void) +{ + ply_region_t *region; + + region = calloc (1, sizeof (ply_region_t)); + + region->rectangle_list = ply_list_new (); + + return region; +} + +void +ply_region_clear (ply_region_t *region) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (region->rectangle_list); + while (node != NULL) + { + ply_list_node_t *next_node; + ply_rectangle_t *rectangle; + + rectangle = (ply_rectangle_t *) ply_list_node_get_data (node); + + next_node = ply_list_get_next_node (region->rectangle_list, node); + + free (rectangle); + ply_list_remove_node (region->rectangle_list, node); + + node = next_node; + } +} + +void +ply_region_free (ply_region_t *region) +{ + + ply_region_clear (region); + ply_list_free (region->rectangle_list); + free (region); +} + +static ply_rectangle_t * +copy_rectangle (ply_rectangle_t *rectangle) +{ + ply_rectangle_t *new_rectangle; + + new_rectangle = malloc (sizeof (*rectangle)); + *new_rectangle = *rectangle; + + return new_rectangle; +} + +static void +merge_rectangle_with_sub_list (ply_region_t *region, + ply_rectangle_t *new_area, + ply_list_node_t *node) +{ + + if (ply_rectangle_is_empty (new_area)) + return; + + while (node != NULL) + { + ply_list_node_t *next_node; + ply_rectangle_t *old_area; + ply_rectangle_overlap_t overlap; + + old_area = (ply_rectangle_t *) ply_list_node_get_data (node); + + next_node = ply_list_get_next_node (region->rectangle_list, node); + + overlap = ply_rectangle_find_overlap (old_area, new_area); + + switch (overlap) + { + /* NNNN The new rectangle and node rectangle don't touch, + * NNNN OOOO so let's move on to the next one. + * OOOO + */ + case PLY_RECTANGLE_OVERLAP_NONE: + break; + + /* NNNNN We need to split the new rectangle into + * NNOOOOO two rectangles: The top row of Ns and + * NNOOOOO the left side of Ns. + * OOOOO + */ + case PLY_RECTANGLE_OVERLAP_TOP_AND_LEFT_EDGES: + { + ply_rectangle_t *rectangle; + + rectangle = copy_rectangle (new_area); + rectangle->y = old_area->y; + rectangle->width = old_area->x - new_area->x; + rectangle->height = (new_area->y + new_area->height) - old_area->y; + + merge_rectangle_with_sub_list (region, rectangle, node); + + new_area->height = old_area->y - new_area->y; + } + break; + + /* NNNNN We need to split the new rectangle into + * OOOOONN two rectangles: The top row of Ns and + * OOOOONN the right side of Ns. + * OOOOO + */ + case PLY_RECTANGLE_OVERLAP_TOP_AND_RIGHT_EDGES: + { + ply_rectangle_t *rectangle; + + rectangle = copy_rectangle (new_area); + rectangle->x = new_area->x + old_area->width; + rectangle->y = old_area->y; + rectangle->width = (old_area->x + new_area->width) - (old_area->x + old_area->width); + rectangle->height = (new_area->y + new_area->height) - old_area->y; + + merge_rectangle_with_sub_list (region, rectangle, node); + + new_area->height = old_area->y - new_area->y; + } + break; + + /* NNNNNNN We need to trim out the part of + * NOOOOON old rectangle that overlaps the new + * NOOOOON rectangle by shrinking and moving it + * OOOOO and then we need to add the new rectangle. + */ + case PLY_RECTANGLE_OVERLAP_TOP_AND_SIDE_EDGES: + { + old_area->height = (old_area->y + old_area->height) + - (new_area->y + new_area->height); + old_area->y = new_area->y + new_area->height; + } + + /* NNN We only care about the top row of Ns, + * ONNNO everything below that is already handled by + * ONNNO the old rectangle. + * OOOOO + */ + case PLY_RECTANGLE_OVERLAP_TOP_EDGE: + new_area->height = old_area->y - new_area->y; + break; + + /* OOOOO We need to split the new rectangle into + * NNOOOOO two rectangles: The left side of Ns and + * NNOOOOO the bottom row of Ns. + * NNOOOOO + * NNNNN + */ + case PLY_RECTANGLE_OVERLAP_BOTTOM_AND_LEFT_EDGES: + { + ply_rectangle_t *rectangle; + + rectangle = copy_rectangle (new_area); + + rectangle->y = old_area->y; + rectangle->width = old_area->x - new_area->x; + rectangle->height = (old_area->y + old_area->height) - new_area->y; + + merge_rectangle_with_sub_list (region, rectangle, node); + + new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height); + new_area->width = new_area->width; + new_area->y = old_area->y + old_area->height; + } + break; + + /* OOOOO We need to split the new rectangle into + * OOOOONN two rectangles: The right side of Ns and + * OOOOONN the bottom row of Ns. + * OOOOONN + * NNNNN + */ + case PLY_RECTANGLE_OVERLAP_BOTTOM_AND_RIGHT_EDGES: + { + ply_rectangle_t *rectangle; + + rectangle = copy_rectangle (new_area); + + rectangle->x = old_area->x + old_area->width; + rectangle->width = (new_area->x + new_area->width) - (old_area->x + old_area->width); + rectangle->height = (old_area->y + old_area->height) - new_area->y; + + merge_rectangle_with_sub_list (region, rectangle, node); + + new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height); + new_area->y = old_area->y + old_area->height; + } + break; + + /* OOOOO We need to trim out the part of + * NOOOOON old rectangle that overlaps the new + * NOOOOON rectangle by shrinking it + * NNNNNNN and then we need to add the new rectangle. + */ + case PLY_RECTANGLE_OVERLAP_BOTTOM_AND_SIDE_EDGES: + { + old_area->height = (new_area->y + new_area->height) + - (old_area->y + old_area->height); + } + break; + + /* OOOOO We only care about the bottom row of Ns, + * ONNNO everything above that is already handled by + * ONNNO the old rectangle. + * NNN + */ + case PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE: + { + new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height); + new_area->y = old_area->y + old_area->height; + } + break; + + /* NNNN We need to trim out the part of + * NNNNO old rectangle that overlaps the new + * NNNNO rectangle by shrinking it and moving it + * NNNN and then we need to add the new rectangle. + */ + case PLY_RECTANGLE_OVERLAP_TOP_LEFT_AND_BOTTOM_EDGES: + { + old_area->width = (old_area->x + old_area->width) + - (new_area->x + new_area->width); + old_area->x = new_area->x + new_area->width; + } + break; + + /* NNNN We need to trim out the part of + * ONNNN old rectangle that overlaps the new + * ONNNN rectangle by shrinking it and then we + * NNNN need to add the new rectangle. + */ + case PLY_RECTANGLE_OVERLAP_TOP_RIGHT_AND_BOTTOM_EDGES: + old_area->width = new_area->x - old_area->x; + break; + + /* NNNNNNN The old rectangle is completely inside the new rectangle + * NOOOOON so replace the old rectangle with the new rectangle. + * NOOOOON + * NNNNNNN + */ + case PLY_RECTANGLE_OVERLAP_ALL_EDGES: + free (old_area); + ply_list_remove_node (region->rectangle_list, node); + break; + + /* NNN We need to split the new rectangle into + * ONNNO two rectangles: the top and bottom row of Ns + * ONNNO + * NNN + */ + case PLY_RECTANGLE_OVERLAP_TOP_AND_BOTTOM_EDGES: + { + ply_rectangle_t *rectangle; + + rectangle = copy_rectangle (new_area); + rectangle->y = old_area->y + old_area->height; + rectangle->width = new_area->width; + rectangle->height = (new_area->y + new_area->height) - (old_area->y + old_area->height); + merge_rectangle_with_sub_list (region, rectangle, node); + + new_area->height = old_area->y - new_area->y; + } + break; + + /* OOOOO We only care about the side row of Ns, + * NNNNOO everything rigth of that is already handled by + * NNNNOO the old rectangle. + * OOOOO + */ + case PLY_RECTANGLE_OVERLAP_LEFT_EDGE: + new_area->width = old_area->x - new_area->x; + break; + + /* OOOOO We only care about the side row of Ns, + * NNNNNN everything left of that is already handled by + * NNNNNN the old rectangle. + * OOOOO + */ + case PLY_RECTANGLE_OVERLAP_RIGHT_EDGE: + { + new_area->width = (new_area->x + new_area->width) - (old_area->x + old_area->width); + new_area->x = old_area->x + old_area->width; + } + break; + + /* OOOOO We need to split the new rectangle into + * NNNNNNN two rectangles: the side columns of Ns + * NNNNNNN + * OOOOO + */ + case PLY_RECTANGLE_OVERLAP_SIDE_EDGES: + { + ply_rectangle_t *rectangle; + + rectangle = copy_rectangle (new_area); + + rectangle->x = old_area->x + old_area->width; + rectangle->width = (new_area->x + new_area->width) - (old_area->x + old_area->width); + + merge_rectangle_with_sub_list (region, rectangle, node); + + new_area->width = old_area->x - new_area->x; + } + break; + + /* OOOOOOO The new rectangle is completely inside an old rectangle + * ONNNNNO so return early without adding the new rectangle. + * ONNNNNO + * OOOOOOO + */ + case PLY_RECTANGLE_OVERLAP_NO_EDGES: + free (new_area); + return; + + } + + node = next_node; + } + + ply_list_append_data (region->rectangle_list, new_area); +} + +void +ply_region_add_rectangle (ply_region_t *region, + ply_rectangle_t *rectangle) +{ + ply_list_node_t *first_node; + ply_rectangle_t *rectangle_copy; + + assert (region != NULL); + assert (rectangle != NULL); + + first_node = ply_list_get_first_node (region->rectangle_list); + + rectangle_copy = copy_rectangle (rectangle); + merge_rectangle_with_sub_list (region, + rectangle_copy, + first_node); +} + +ply_list_t * +ply_region_get_rectangle_list (ply_region_t *region) +{ + return region->rectangle_list; +} + +/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/libply/ply-region.h b/src/libply/ply-region.h new file mode 100644 index 00000000..ee6e992f --- /dev/null +++ b/src/libply/ply-region.h @@ -0,0 +1,47 @@ +/* ply-region.h + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode + */ +#ifndef PLY_REGION_H +#define PLY_REGION_H + +#include +#include + +#include "ply-list.h" +#include "ply-rectangle.h" +#include "ply-utils.h" + +typedef struct _ply_region ply_region_t; + +#ifndef PLY_HIDE_FUNCTION_DECLARATIONS +ply_region_t *ply_region_new (void); +void ply_region_free (ply_region_t *region); +void ply_region_add_rectangle (ply_region_t *region, + ply_rectangle_t *rectangle); +void ply_region_clear (ply_region_t *region); +ply_list_t *ply_region_get_rectangle_list (ply_region_t *region); + +bool ply_region_is_empty (ply_region_t *region); + +#endif + +#endif /* PLY_REGION_H */ +/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ From 33d5702de6a1d6b45204f704251faa27d1a2b093 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Thu, 20 Aug 2009 00:06:06 -0400 Subject: [PATCH 05/43] [libplybootsplash] Add new pixel buffer class Right now a lot of pixel manipulation functions are in the frame buffer code. This means it's hard to do these types of things without the results showing up on the display. Furthermore, we want to get away from one frame buffer anyway for multihead support. I can imagine each display in a multihead configuration with its own pixel buffer, so splash plugins can draw to the independently. This commit adds the start of a pixel buffer class, which just copies and pastes most of pixel-twiddling frame buffer code. There are some changes to deal with pixel buffers not always having a final alpha of 1.0, and some changes to provide a more flexible interface for masking fill operations. At some point it will probably gain copy-and-pastes of the resize an rotate code from the image class as well, and provide a mechansim for have subpixbufs where rowstride != width. --- src/libplybootsplash/Makefile.am | 2 + src/libplybootsplash/ply-pixel-buffer.c | 602 ++++++++++++++++++++++++ src/libplybootsplash/ply-pixel-buffer.h | 103 ++++ 3 files changed, 707 insertions(+) create mode 100644 src/libplybootsplash/ply-pixel-buffer.c create mode 100644 src/libplybootsplash/ply-pixel-buffer.h diff --git a/src/libplybootsplash/Makefile.am b/src/libplybootsplash/Makefile.am index 508a212c..7b8c5c16 100644 --- a/src/libplybootsplash/Makefile.am +++ b/src/libplybootsplash/Makefile.am @@ -14,6 +14,7 @@ libplybootsplash_HEADERS = \ ply-image.h \ ply-label.h \ ply-label-plugin.h \ + ply-pixel-buffer.h \ ply-progress-animation.h \ ply-progress-bar.h \ ply-text-progress-bar.h \ @@ -40,6 +41,7 @@ libplybootsplash_la_SOURCES = \ ply-animation.c \ ply-progress-animation.c \ ply-text-progress-bar.c \ + ply-pixel-buffer.c \ ply-window.c \ ply-boot-splash.c diff --git a/src/libplybootsplash/ply-pixel-buffer.c b/src/libplybootsplash/ply-pixel-buffer.c new file mode 100644 index 00000000..722c5324 --- /dev/null +++ b/src/libplybootsplash/ply-pixel-buffer.c @@ -0,0 +1,602 @@ +/* ply-pixel-buffer.c - pixelbuffer abstraction + * + * Copyright (C) 2006, 2007, 2008, 2009 Red Hat, Inc. + * 2008 Charlie Brej + * + * 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: Charlie Brej + * Kristian Høgsberg + * Ray Strode + */ +#include "config.h" +#include "ply-list.h" +#include "ply-pixel-buffer.h" +#include "ply-logger.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +struct _ply_pixel_buffer +{ + uint32_t *bytes; + + ply_rectangle_t area; + ply_list_t *clip_areas; + + ply_region_t *updated_areas; +}; + +static inline void ply_pixel_buffer_blend_value_at_pixel (ply_pixel_buffer_t *buffer, + int x, + int y, + uint32_t pixel_value); + +static void ply_pixel_buffer_fill_area_with_pixel_value (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + uint32_t pixel_value); + +__attribute__((__pure__)) +static inline uint32_t +blend_two_pixel_values (uint32_t pixel_value_1, + uint32_t pixel_value_2) +{ + if ((pixel_value_2 & 0xff000000) == 0xff000000) + { + uint8_t alpha_1, red_1, green_1, blue_1; + uint8_t red_2, green_2, blue_2; + uint_least16_t red, green, blue; + + alpha_1 = (uint8_t) (pixel_value_1 >> 24); + red_1 = (uint8_t) (pixel_value_1 >> 16); + green_1 = (uint8_t) (pixel_value_1 >> 8); + blue_1 = (uint8_t) pixel_value_1; + + red_2 = (uint8_t) (pixel_value_2 >> 16); + green_2 = (uint8_t) (pixel_value_2 >> 8); + blue_2 = (uint8_t) pixel_value_2; + + red = red_1 * 255 + red_2 * (255 - alpha_1); + green = green_1 * 255 + green_2 * (255 - alpha_1); + blue = blue_1 * 255 + blue_2 * (255 - alpha_1); + + red = (uint8_t) ((red + (red >> 8) + 0x80) >> 8); + green = (uint8_t) ((green + (green >> 8) + 0x80) >> 8); + blue = (uint8_t) ((blue + (blue >> 8) + 0x80) >> 8); + + return 0xff000000 | (red << 16) | (green << 8) | blue; + } + else + { + uint8_t alpha_1, red_1, green_1, blue_1; + uint8_t alpha_2, red_2, green_2, blue_2; + uint_least32_t alpha, red, green, blue; + + alpha_1 = (uint8_t) (pixel_value_1 >> 24); + red_1 = (uint8_t) (pixel_value_1 >> 16); + green_1 = (uint8_t) (pixel_value_1 >> 8); + blue_1 = (uint8_t) pixel_value_1; + + alpha_2 = (uint8_t) (pixel_value_2 >> 24); + red_2 = (uint8_t) (pixel_value_2 >> 16); + green_2 = (uint8_t) (pixel_value_2 >> 8); + blue_2 = (uint8_t) pixel_value_2; + + red = red_1 * alpha_1 + red_2 * alpha_2 * (255 - alpha_1); + green = green_1 * alpha_1 + green_2 * alpha_2 * (255 - alpha_1); + blue = blue_1 * alpha_1 + blue_2 * alpha_2 * (255 - alpha_1); + alpha = alpha_1 * 255 + alpha_2 * (255 - alpha_1); + + red = (red + (red >> 8) + 0x80) >> 8; + red = MIN (red, 0xff); + + green = (green + (green >> 8) + 0x80) >> 8; + green = MIN (green, 0xff); + + blue = (blue + (blue >> 8) + 0x80) >> 8; + blue = MIN (blue, 0xff); + + alpha = (alpha + (alpha >> 8) + 0x80) >> 8; + alpha = MIN (alpha, 0xff); + + return (alpha << 24) | (red << 16) | (green << 8) | blue; + } +} + +__attribute__((__pure__)) +static inline uint32_t +make_pixel_value_translucent (uint32_t pixel_value, + uint8_t opacity) +{ + uint_least16_t alpha, red, green, blue; + + if (opacity == 255) + return pixel_value; + + alpha = (uint8_t) (pixel_value >> 24); + red = (uint8_t) (pixel_value >> 16); + green = (uint8_t) (pixel_value >> 8); + blue = (uint8_t) pixel_value; + + red *= opacity; + green *= opacity; + blue *= opacity; + alpha *= opacity; + + red = (uint8_t) ((red + (red >> 8) + 0x80) >> 8); + green = (uint8_t) ((green + (green >> 8) + 0x80) >> 8); + blue = (uint8_t) ((blue + (blue >> 8) + 0x80) >> 8); + alpha = (uint8_t) ((alpha + (alpha >> 8) + 0x80) >> 8); + + return (alpha << 24) | (red << 16) | (green << 8) | blue; +} + +static inline void +ply_pixel_buffer_blend_value_at_pixel (ply_pixel_buffer_t *buffer, + int x, + int y, + uint32_t pixel_value) +{ + uint32_t old_pixel_value; + + if ((pixel_value >> 24) != 0xff) + { + old_pixel_value = buffer->bytes[y * buffer->area.width + x]; + + pixel_value = blend_two_pixel_values (pixel_value, old_pixel_value); + } + + buffer->bytes[y * buffer->area.width + x] = pixel_value; +} + +static void +ply_pixel_buffer_crop_area_to_clip_area (ply_pixel_buffer_t *buffer, + ply_rectangle_t *area, + ply_rectangle_t *cropped_area) +{ + ply_list_node_t *node; + + *cropped_area = *area; + + node = ply_list_get_first_node (buffer->clip_areas); + while (node != NULL) + { + ply_list_node_t *next_node; + ply_rectangle_t *clip_rectangle; + + clip_rectangle = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (buffer->clip_areas, node); + + ply_rectangle_intersect (cropped_area, clip_rectangle, cropped_area); + + node = next_node; + } +} + +static void +ply_pixel_buffer_fill_area_with_pixel_value (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + uint32_t pixel_value) +{ + unsigned long row, column; + ply_rectangle_t cropped_area; + + ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area); + + 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, + column, row, + pixel_value); + } + } +} + +void +ply_pixel_buffer_push_clip_area (ply_pixel_buffer_t *buffer, + ply_rectangle_t *clip_area) +{ + ply_rectangle_t *new_clip_area; + + new_clip_area = malloc (sizeof (*new_clip_area)); + + *new_clip_area = *clip_area; + ply_list_append_data (buffer->clip_areas, new_clip_area); +} + +void +ply_pixel_buffer_pop_clip_area (ply_pixel_buffer_t *buffer) +{ + ply_list_node_t *last_node; + + last_node = ply_list_get_last_node (buffer->clip_areas); + free (ply_list_node_get_data (last_node)); + ply_list_remove_node (buffer->clip_areas, last_node); +} + +ply_pixel_buffer_t * +ply_pixel_buffer_new (unsigned long width, + unsigned long height) +{ + ply_pixel_buffer_t *buffer; + + buffer = calloc (1, sizeof (ply_pixel_buffer_t)); + + buffer->updated_areas = ply_region_new (); + buffer->bytes = (uint32_t *) calloc (height, width * sizeof (uint32_t)); + buffer->area.width = width; + buffer->area.height = height; + + buffer->clip_areas = ply_list_new (); + ply_pixel_buffer_push_clip_area (buffer, &buffer->area); + + return buffer; +} + +static void +free_clip_areas (ply_pixel_buffer_t *buffer) +{ + while (ply_list_get_length (buffer->clip_areas) > 0) + ply_pixel_buffer_pop_clip_area (buffer); + + ply_list_free (buffer->clip_areas); + buffer->clip_areas = NULL; +} + +void +ply_pixel_buffer_free (ply_pixel_buffer_t *buffer) +{ + if (buffer == NULL) + return; + + free_clip_areas (buffer); + free (buffer->bytes); + ply_region_free (buffer->updated_areas); + free (buffer); +} + +void +ply_pixel_buffer_get_size (ply_pixel_buffer_t *buffer, + ply_rectangle_t *size) +{ + assert (buffer != NULL); + assert (size != NULL); + + *size = buffer->area; +} + +ply_region_t * +ply_pixel_buffer_get_updated_areas (ply_pixel_buffer_t *buffer) +{ + return buffer->updated_areas; +} + +void +ply_pixel_buffer_fill_with_gradient (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + uint32_t start, + uint32_t end) +{ +/* The gradient produced is a linear interpolation of the two passed + * in color stops: start and end. + * + * In order to prevent banding when the color stops are too close + * together, or are stretched over too large an area, we slightly + * perturb the intermediate colors as we generate them. + * + * Before we do this, we store the interpolated color values in a + * fixed point number with lots of fractional bits. This is so + * we don't add noise after the values have been clamped to 8-bits + * + * We add random noise to all of the fractional bits of each color + * channel and also NOISE_BITS worth of noise to the non-fractional + * part of the color. By default NOISE_BITS is 1. + * + * We incorporate the noise by filling the bottom 24 bits of an + * integer with random bits and then shifting the color channels + * to the left such that the top 8 bits of the channel overlap + * the noise by NOISE_BITS. E.g., if NOISE_BITS is 1, then the top + * 7 bits of each channel won't overlap with the noise, and the 8th + * bit + fractional bits will. When the noise and color channel + * are properly aligned, we add them together, drop the precision + * of the resulting channels back to 8 bits and stuff the results + * into a pixel in the pixel buffer. + */ +#define NOISE_BITS 1 +/* In the color stops, red is 8 bits starting at position 24 + * (since they're argb32 pixels). + * We want to move those 8 bits such that the bottom NOISE_BITS + * of them overlap the top of the 24 bits of generated noise. + * Of course, green and blue are 8 bits away from red and each + * other, respectively. + */ +#define RED_SHIFT (32 - (24 + NOISE_BITS)) +#define GREEN_SHIFT (RED_SHIFT + 8) +#define BLUE_SHIFT (GREEN_SHIFT + 8) +#define NOISE_MASK (0x00ffffff) + +/* Once, we've lined up the color channel we're interested in with + * the noise, we need to mask out the other channels. + */ +#define COLOR_MASK (0xff << (24 - NOISE_BITS)) + + uint32_t red, green, blue, red_step, green_step, blue_step, t, pixel; + uint32_t x, y; + /* we use a fixed seed so that the dithering doesn't change on repaints + * of the same area. + */ + uint32_t noise = 0x100001; + ply_rectangle_t cropped_area; + + if (fill_area == NULL) + fill_area = &buffer->area; + + ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area); + + red = (start << RED_SHIFT) & COLOR_MASK; + green = (start << GREEN_SHIFT) & COLOR_MASK; + blue = (start << BLUE_SHIFT) & COLOR_MASK; + + t = (end << RED_SHIFT) & COLOR_MASK; + red_step = (int32_t) (t - red) / (int32_t) buffer->area.height; + t = (end << GREEN_SHIFT) & COLOR_MASK; + green_step = (int32_t) (t - green) / (int32_t) buffer->area.height; + t = (end << BLUE_SHIFT) & COLOR_MASK; + blue_step = (int32_t) (t - blue) / (int32_t) buffer->area.height; + + +#define RANDOMIZE(num) (num = (num + (num << 1)) & NOISE_MASK) +#define UNROLLED_PIXEL_COUNT 8 + + for (y = buffer->area.y; y < buffer->area.y + buffer->area.height; y++) + { + if (cropped_area.y <= y && y < cropped_area.y + cropped_area.height) + { + if (cropped_area.width < UNROLLED_PIXEL_COUNT) + { + for (x = cropped_area.x; x < cropped_area.x + cropped_area.width; x++) + { + pixel = 0xff000000; + RANDOMIZE(noise); + pixel |= (((red + noise) & COLOR_MASK) >> RED_SHIFT); + RANDOMIZE(noise); + pixel |= (((green + noise) & COLOR_MASK) >> GREEN_SHIFT); + RANDOMIZE(noise); + pixel |= (((blue + noise) & COLOR_MASK) >> BLUE_SHIFT); + + buffer->bytes[y * buffer->area.width + x] = pixel; + } + } + else + { + uint32_t shaded_set[UNROLLED_PIXEL_COUNT]; + uint32_t *ptr = &buffer->bytes[y * buffer->area.width + cropped_area.x]; + for (x = 0; x < UNROLLED_PIXEL_COUNT; x++) + { + shaded_set[x] = 0xff000000; + RANDOMIZE(noise); + shaded_set[x] |= (((red + noise) & COLOR_MASK) >> RED_SHIFT); + RANDOMIZE(noise); + shaded_set[x] |= (((green + noise) & COLOR_MASK) >> GREEN_SHIFT); + RANDOMIZE(noise); + shaded_set[x] |= (((blue + noise) & COLOR_MASK) >> BLUE_SHIFT); + } + for (x = cropped_area.width; x >=UNROLLED_PIXEL_COUNT; x-= UNROLLED_PIXEL_COUNT) + { + memcpy (ptr, (void *) shaded_set, UNROLLED_PIXEL_COUNT * sizeof (uint32_t)); + ptr += UNROLLED_PIXEL_COUNT; + } + + memcpy (ptr, (void *) shaded_set, x * sizeof (uint32_t)); + } + } + + red += red_step; + green += green_step; + blue += blue_step; + } + + ply_region_add_rectangle (buffer->updated_areas, &cropped_area); +} + +void +ply_pixel_buffer_fill_with_color (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + double red, + double green, + double blue, + 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); +} + +void +ply_pixel_buffer_fill_with_hex_color_at_opacity (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + uint32_t hex_color, + double opacity) +{ + ply_rectangle_t cropped_area; + uint32_t pixel_value; + double red; + double green; + double blue; + double alpha; + + 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) + hex_color = (hex_color << 8) | 0xff; + + red = ((double) (hex_color & 0xff000000) / 0xff000000); + green = ((double) (hex_color & 0x00ff0000) / 0x00ff0000); + blue = ((double) (hex_color & 0x0000ff00) / 0x0000ff00); + alpha = ((double) (hex_color & 0x000000ff) / 0x000000ff); + + alpha *= opacity; + + 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); +} + +void +ply_pixel_buffer_fill_with_hex_color (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + uint32_t hex_color) +{ + return ply_pixel_buffer_fill_with_hex_color_at_opacity (buffer, fill_area, + hex_color, 1.0); +} + +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, + unsigned long x, + unsigned long y, + uint32_t *data, + double opacity) +{ + unsigned long row, column; + uint8_t opacity_as_byte; + 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); + + if (clip_area) + ply_rectangle_intersect (&cropped_area, 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); + + 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 ((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), + pixel_value); + + } + } + + ply_region_add_rectangle (buffer->updated_areas, &cropped_area); +} + +void +ply_pixel_buffer_fill_with_argb32_data_at_opacity (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + unsigned long x, + unsigned long y, + uint32_t *data, + double opacity) +{ + ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer, + fill_area, + NULL, x, y, + data, opacity); +} + +void +ply_pixel_buffer_fill_with_argb32_data (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + unsigned long x, + unsigned long y, + uint32_t *data) +{ + ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer, + fill_area, + NULL, x, y, + data, 1.0); +} + +void +ply_pixel_buffer_fill_with_argb32_data_with_clip (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + ply_rectangle_t *clip_area, + unsigned long x, + unsigned long y, + uint32_t *data) +{ + ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer, + fill_area, + clip_area, x, y, + data, 1.0); +} + +uint32_t * +ply_pixel_buffer_get_argb32_data (ply_pixel_buffer_t *buffer) +{ + return buffer->bytes; +} +/* 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/libplybootsplash/ply-pixel-buffer.h b/src/libplybootsplash/ply-pixel-buffer.h new file mode 100644 index 00000000..52a93b55 --- /dev/null +++ b/src/libplybootsplash/ply-pixel-buffer.h @@ -0,0 +1,103 @@ +/* ply-pixel-buffer.h - pixel buffer abstraction + * + * Copyright (C) 2007, 2009 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode + */ +#ifndef PLY_PIXEL_BUFFER_H +#define PLY_PIXEL_BUFFER_H + +#include +#include + +#include "ply-rectangle.h" +#include "ply-region.h" +#include "ply-utils.h" + +typedef struct _ply_pixel_buffer ply_pixel_buffer_t; + +#define PLY_PIXEL_BUFFER_COLOR_TO_PIXEL_VALUE(r,g,b,a) \ + (((uint8_t) (CLAMP (a * 255.0, 0.0, 255.0)) << 24) \ + | ((uint8_t) (CLAMP (r * 255.0, 0.0, 255.0)) << 16) \ + | ((uint8_t) (CLAMP (g * 255.0, 0.0, 255.0)) << 8) \ + | ((uint8_t) (CLAMP (b * 255.0, 0.0, 255.0)))) + +#ifndef PLY_HIDE_FUNCTION_DECLARATIONS +ply_pixel_buffer_t *ply_pixel_buffer_new (unsigned long width, + unsigned long height); +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); +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, + ply_rectangle_t *fill_area, + double red, + double green, + double blue, + double alpha); +void ply_pixel_buffer_fill_with_hex_color (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + uint32_t hex_color); + +void ply_pixel_buffer_fill_with_hex_color_at_opacity (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + uint32_t hex_color, + double opacity); + +void ply_pixel_buffer_fill_with_gradient (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + uint32_t start, + uint32_t end); + +void ply_pixel_buffer_fill_with_argb32_data (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + unsigned long x, + unsigned long y, + uint32_t *data); +void ply_pixel_buffer_fill_with_argb32_data_at_opacity (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + unsigned long x, + unsigned long y, + uint32_t *data, + double opacity); + +void ply_pixel_buffer_fill_with_argb32_data_with_clip (ply_pixel_buffer_t *buffer, + ply_rectangle_t *fill_area, + ply_rectangle_t *clip_area, + unsigned long x, + unsigned long y, + uint32_t *data); +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, + unsigned long x, + unsigned long y, + uint32_t *data, + double opacity); + +void ply_pixel_buffer_push_clip_area (ply_pixel_buffer_t *buffer, + ply_rectangle_t *clip_area); +void ply_pixel_buffer_pop_clip_area (ply_pixel_buffer_t *buffer); + +uint32_t *ply_pixel_buffer_get_argb32_data (ply_pixel_buffer_t *buffer); + +#endif + +#endif /* PLY_PIXEL_BUFFER_H */ +/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ From a018e96d5fc46d82cd05f22f1d96d3d6c410a275 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 21 Aug 2009 19:21:53 -0400 Subject: [PATCH 06/43] [libplybootsplash] Add keyboard class This is the input portion of the window class. With this commit and subsequent commits to split out the output portions, we should be able to drop the window class. This will give us the flexibility we need for multi-head rendering. --- src/libplybootsplash/Makefile.am | 2 + src/libplybootsplash/ply-keyboard.c | 583 ++++++++++++++++++++++++++++ src/libplybootsplash/ply-keyboard.h | 78 ++++ 3 files changed, 663 insertions(+) create mode 100644 src/libplybootsplash/ply-keyboard.c create mode 100644 src/libplybootsplash/ply-keyboard.h diff --git a/src/libplybootsplash/Makefile.am b/src/libplybootsplash/Makefile.am index 7b8c5c16..51b9b842 100644 --- a/src/libplybootsplash/Makefile.am +++ b/src/libplybootsplash/Makefile.am @@ -12,6 +12,7 @@ libplybootsplash_HEADERS = \ ply-boot-splash-plugin.h \ ply-entry.h \ ply-image.h \ + ply-keyboard.h \ ply-label.h \ ply-label-plugin.h \ ply-pixel-buffer.h \ @@ -35,6 +36,7 @@ libplybootsplash_la_SOURCES = \ $(libplybootsplash_HEADERS) \ ply-entry.c \ ply-image.c \ + ply-keyboard.c \ ply-label.c \ ply-progress-bar.c \ ply-throbber.c \ diff --git a/src/libplybootsplash/ply-keyboard.c b/src/libplybootsplash/ply-keyboard.c new file mode 100644 index 00000000..375ddd54 --- /dev/null +++ b/src/libplybootsplash/ply-keyboard.c @@ -0,0 +1,583 @@ +/* ply-keyboard.h - APIs for putting up a keyboard screen + * + * 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 + */ +#include "config.h" +#include "ply-keyboard.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ply-buffer.h" +#include "ply-event-loop.h" +#include "ply-list.h" +#include "ply-logger.h" +#include "ply-renderer.h" +#include "ply-terminal.h" +#include "ply-utils.h" + +#define KEY_CTRL_U ('\100' ^'U') +#define KEY_CTRL_W ('\100' ^'W') +#define KEY_CTRL_V ('\100' ^'V') +#define KEY_ESCAPE ('\100' ^'[') +#define KEY_RETURN '\r' +#define KEY_BACKSPACE '\177' + +typedef void (* ply_keyboard_handler_t) (void *); + +typedef struct +{ + ply_keyboard_handler_t function; + void *user_data; +} ply_keyboard_closure_t; + +typedef enum +{ + PLY_KEYBOARD_PROVIDER_TYPE_TERMINAL, + PLY_KEYBOARD_PROVIDER_TYPE_RENDERER +} ply_keyboard_provider_type_t; + +typedef struct +{ + ply_terminal_t *terminal; + ply_fd_watch_t *input_watch; + ply_buffer_t *key_buffer; +} ply_keyboard_terminal_provider_t; + +typedef struct +{ + ply_renderer_t *renderer; + ply_renderer_input_source_t *input_source; +} ply_keyboard_renderer_provider_t; + +typedef union { + ply_keyboard_renderer_provider_t *if_renderer; + ply_keyboard_terminal_provider_t *if_terminal; +} ply_keyboard_provider_t; + +struct _ply_keyboard +{ + ply_event_loop_t *loop; + + ply_keyboard_provider_type_t provider_type; + ply_keyboard_provider_t provider; + + ply_buffer_t *line_buffer; + + ply_list_t *keyboard_input_handler_list; + ply_list_t *backspace_handler_list; + ply_list_t *escape_handler_list; + ply_list_t *enter_handler_list; +}; + +ply_keyboard_t * +ply_keyboard_new_for_terminal (ply_terminal_t *terminal) +{ + ply_keyboard_t *keyboard; + + keyboard = calloc (1, sizeof (ply_keyboard_t)); + keyboard->line_buffer = ply_buffer_new (); + keyboard->keyboard_input_handler_list = ply_list_new (); + keyboard->backspace_handler_list = ply_list_new (); + keyboard->escape_handler_list = ply_list_new (); + keyboard->enter_handler_list = ply_list_new (); + keyboard->provider_type = PLY_KEYBOARD_PROVIDER_TYPE_TERMINAL; + keyboard->provider.if_terminal = calloc (1, sizeof (ply_keyboard_terminal_provider_t)); + keyboard->provider.if_terminal->terminal = terminal; + keyboard->provider.if_terminal->key_buffer = ply_buffer_new (); + + keyboard->loop = ply_event_loop_get_default (); + + return keyboard; +} + +ply_keyboard_t * +ply_keyboard_new_for_renderer (ply_renderer_t *renderer) +{ + ply_keyboard_t *keyboard; + ply_renderer_input_source_t *input_source; + + keyboard = calloc (1, sizeof (ply_keyboard_t)); + keyboard->line_buffer = ply_buffer_new (); + keyboard->keyboard_input_handler_list = ply_list_new (); + keyboard->backspace_handler_list = ply_list_new (); + keyboard->escape_handler_list = ply_list_new (); + keyboard->enter_handler_list = ply_list_new (); + keyboard->provider_type = PLY_KEYBOARD_PROVIDER_TYPE_RENDERER; + keyboard->provider.if_renderer = calloc (1, sizeof (ply_keyboard_renderer_provider_t)); + keyboard->provider.if_renderer->renderer = renderer; + + input_source = ply_renderer_get_input_source (renderer); + + keyboard->provider.if_renderer->input_source = input_source; + + keyboard->loop = ply_event_loop_get_default (); + + return keyboard; +} + +static void +process_backspace (ply_keyboard_t *keyboard) +{ + size_t bytes_to_remove; + ssize_t previous_character_size; + const char *bytes; + size_t size; + ply_list_node_t *node; + + bytes = ply_buffer_get_bytes (keyboard->line_buffer); + size = ply_buffer_get_size (keyboard->line_buffer); + + bytes_to_remove = MIN (size, PLY_UTF8_CHARACTER_SIZE_MAX); + while ((previous_character_size = ply_utf8_character_get_size (bytes + size - bytes_to_remove, bytes_to_remove)) < (ssize_t) bytes_to_remove) + { + if (previous_character_size > 0) + bytes_to_remove -= previous_character_size; + else + bytes_to_remove--; + } + + if (bytes_to_remove <= size) + ply_buffer_remove_bytes_at_end (keyboard->line_buffer, bytes_to_remove); + + for (node = ply_list_get_first_node(keyboard->backspace_handler_list); + node; node = ply_list_get_next_node(keyboard->backspace_handler_list, node)) + { + ply_keyboard_closure_t *closure = ply_list_node_get_data (node); + ply_keyboard_backspace_handler_t backspace_handler = + (ply_keyboard_backspace_handler_t) closure->function; + backspace_handler (closure->user_data); + } +} + +static void +process_line_erase (ply_keyboard_t *keyboard) +{ + size_t size; + + while ((size = ply_buffer_get_size (keyboard->line_buffer)) > 0) + process_backspace (keyboard); +} + +static void +process_keyboard_input (ply_keyboard_t *keyboard, + const char *keyboard_input, + size_t character_size) +{ + wchar_t key; + ply_list_node_t *node; + + if ((ssize_t) mbrtowc (&key, keyboard_input, character_size, NULL) > 0) + { + switch (key) + { + case KEY_CTRL_U: + case KEY_CTRL_W: + ply_trace ("erase line!"); + process_line_erase (keyboard); + return; + + case KEY_CTRL_V: + ply_trace ("toggle verbose mode!"); + ply_toggle_tracing (); + ply_trace ("verbose mode toggled!"); + return; + + case KEY_ESCAPE: + ply_trace ("escape key!"); + for (node = ply_list_get_first_node(keyboard->escape_handler_list); + node; node = ply_list_get_next_node(keyboard->escape_handler_list, node)) + { + ply_keyboard_closure_t *closure = ply_list_node_get_data (node); + ply_keyboard_escape_handler_t escape_handler = (ply_keyboard_escape_handler_t) closure->function; + escape_handler (closure->user_data); + } + + ply_trace ("end escape key handler"); + return; + + case KEY_BACKSPACE: + ply_trace ("backspace key!"); + process_backspace (keyboard); + return; + + case KEY_RETURN: + ply_trace ("return key!"); + + for (node = ply_list_get_first_node(keyboard->enter_handler_list); + node; node = ply_list_get_next_node(keyboard->enter_handler_list, node)) + { + ply_keyboard_closure_t *closure = ply_list_node_get_data (node); + ply_keyboard_enter_handler_t enter_handler = (ply_keyboard_enter_handler_t) closure->function; + enter_handler (closure->user_data, ply_buffer_get_bytes (keyboard->line_buffer)); + } + ply_buffer_clear (keyboard->line_buffer); + return; + + default: + ply_buffer_append_bytes (keyboard->line_buffer, + keyboard_input, character_size); + break; + } + } + + for (node = ply_list_get_first_node(keyboard->keyboard_input_handler_list); + node; node = ply_list_get_next_node(keyboard->keyboard_input_handler_list, node)) + { + ply_keyboard_closure_t *closure = ply_list_node_get_data (node); + ply_keyboard_input_handler_t keyboard_input_handler = + (ply_keyboard_input_handler_t) closure->function; + + keyboard_input_handler (closure->user_data, + keyboard_input, character_size); + } +} + +static void +on_key_event (ply_keyboard_t *keyboard, + ply_buffer_t *buffer) +{ + const char *bytes; + size_t size, i; + + bytes = ply_buffer_get_bytes (buffer); + size = ply_buffer_get_size (buffer); + + i = 0; + while (i < size) + { + ssize_t character_size; + char *keyboard_input; + + character_size = (ssize_t) ply_utf8_character_get_size (bytes + i, size - i); + + if (character_size < 0) + break; + + /* If we're at a NUL character walk through it + */ + if (character_size == 0) + { + i++; + continue; + } + + keyboard_input = strndup (bytes + i, character_size); + + process_keyboard_input (keyboard, keyboard_input, character_size); + + i += character_size; + + free (keyboard_input); + } + + if (i > 0) + ply_buffer_remove_bytes (buffer, i); +} + +static bool +ply_keyboard_watch_for_renderer_input (ply_keyboard_t *keyboard) +{ + assert (keyboard != NULL); + + if (!ply_renderer_open_input_source (keyboard->provider.if_renderer->renderer, + keyboard->provider.if_renderer->input_source)) + return false; + + ply_renderer_set_handler_for_input_source (keyboard->provider.if_renderer->renderer, + keyboard->provider.if_renderer->input_source, + (ply_renderer_input_source_handler_t) + on_key_event, + keyboard); + return true; +} + +static void +ply_keyboard_stop_watching_for_renderer_input (ply_keyboard_t *keyboard) +{ + ply_renderer_set_handler_for_input_source (keyboard->provider.if_renderer->renderer, + keyboard->provider.if_renderer->input_source, + (ply_renderer_input_source_handler_t) + NULL, NULL); + + ply_renderer_close_input_source (keyboard->provider.if_renderer->renderer, + keyboard->provider.if_renderer->input_source); +} + +static void +on_terminal_data (ply_keyboard_t *keyboard) +{ + int terminal_fd; + + terminal_fd = ply_terminal_get_fd (keyboard->provider.if_terminal->terminal); + ply_buffer_append_from_fd (keyboard->provider.if_terminal->key_buffer, + terminal_fd); + on_key_event (keyboard, keyboard->provider.if_terminal->key_buffer); +} + +static bool +ply_keyboard_watch_for_terminal_input (ply_keyboard_t *keyboard) +{ + int terminal_fd; + + assert (keyboard != NULL); + + terminal_fd = ply_terminal_get_fd (keyboard->provider.if_terminal->terminal); + keyboard->provider.if_terminal->input_watch = ply_event_loop_watch_fd (keyboard->loop, terminal_fd, PLY_EVENT_LOOP_FD_STATUS_HAS_DATA, + (ply_event_handler_t) on_terminal_data, NULL, keyboard); + + return true; +} + +static void +ply_keyboard_stop_watching_for_terminal_input (ply_keyboard_t *keyboard) +{ + ply_event_loop_stop_watching_fd (keyboard->loop, + keyboard->provider.if_terminal->input_watch); + keyboard->provider.if_terminal->input_watch = NULL; +} + +bool +ply_keyboard_watch_for_input (ply_keyboard_t *keyboard) +{ + assert (keyboard != NULL); + + switch (keyboard->provider_type) + { + case PLY_KEYBOARD_PROVIDER_TYPE_RENDERER: + return ply_keyboard_watch_for_renderer_input (keyboard); + + case PLY_KEYBOARD_PROVIDER_TYPE_TERMINAL: + return ply_keyboard_watch_for_terminal_input (keyboard); + } + + return false; +} + +void +ply_keyboard_stop_watching_for_input (ply_keyboard_t *keyboard) +{ + assert (keyboard != NULL); + + switch (keyboard->provider_type) + { + case PLY_KEYBOARD_PROVIDER_TYPE_RENDERER: + ply_keyboard_stop_watching_for_renderer_input (keyboard); + break; + + case PLY_KEYBOARD_PROVIDER_TYPE_TERMINAL: + ply_keyboard_stop_watching_for_terminal_input (keyboard); + break; + } + +} + +void +ply_keyboard_free (ply_keyboard_t *keyboard) +{ + if (keyboard == NULL) + return; + + ply_keyboard_stop_watching_for_input (keyboard); + + ply_buffer_free (keyboard->line_buffer); + + if (keyboard->provider_type == PLY_KEYBOARD_PROVIDER_TYPE_RENDERER) + { + free (keyboard->provider.if_renderer); + } + else + { + ply_buffer_free (keyboard->provider.if_terminal->key_buffer); + free (keyboard->provider.if_terminal); + } + + free (keyboard); +} + +static ply_keyboard_closure_t * +ply_keyboard_closure_new (ply_keyboard_handler_t function, + void *user_data) +{ + ply_keyboard_closure_t *closure = calloc (1, sizeof (ply_keyboard_closure_t)); + closure->function = function; + closure->user_data = user_data; + return closure; +} + + +static void +ply_keyboard_closure_free (ply_keyboard_closure_t *closure) +{ + free (closure); +} + +void +ply_keyboard_add_input_handler (ply_keyboard_t *keyboard, + ply_keyboard_input_handler_t input_handler, + void *user_data) +{ + ply_keyboard_closure_t *closure; + + assert (keyboard != NULL); + + closure = ply_keyboard_closure_new ((ply_keyboard_handler_t) input_handler, + user_data); + ply_list_append_data (keyboard->keyboard_input_handler_list, closure); +} + +void +ply_keyboard_remove_input_handler (ply_keyboard_t *keyboard, + ply_keyboard_input_handler_t input_handler) +{ + ply_list_node_t *node; + + assert (keyboard != NULL); + + for (node = ply_list_get_first_node(keyboard->keyboard_input_handler_list); + node; node = ply_list_get_next_node(keyboard->keyboard_input_handler_list, node)) + { + ply_keyboard_closure_t *closure = ply_list_node_get_data (node); + if ((ply_keyboard_input_handler_t) closure->function == input_handler) + { + ply_keyboard_closure_free (closure); + ply_list_remove_node (keyboard->keyboard_input_handler_list, node); + return; + } + } +} + +void +ply_keyboard_add_backspace_handler (ply_keyboard_t *keyboard, + ply_keyboard_backspace_handler_t backspace_handler, + void *user_data) +{ + ply_keyboard_closure_t *closure; + + assert (keyboard != NULL); + + closure = ply_keyboard_closure_new ((ply_keyboard_handler_t) backspace_handler, + user_data); + ply_list_append_data (keyboard->backspace_handler_list, closure); +} + + +void +ply_keyboard_remove_backspace_handler (ply_keyboard_t *keyboard, + ply_keyboard_backspace_handler_t backspace_handler) +{ + ply_list_node_t *node; + + assert (keyboard != NULL); + + for (node = ply_list_get_first_node(keyboard->backspace_handler_list); + node; node = ply_list_get_next_node(keyboard->backspace_handler_list, node)) + { + ply_keyboard_closure_t *closure = ply_list_node_get_data (node); + if ((ply_keyboard_backspace_handler_t) closure->function == backspace_handler) + { + ply_keyboard_closure_free (closure); + ply_list_remove_node (keyboard->backspace_handler_list, node); + return; + } + } +} + +void +ply_keyboard_add_escape_handler (ply_keyboard_t *keyboard, + ply_keyboard_escape_handler_t escape_handler, + void *user_data) +{ + ply_keyboard_closure_t *closure; + + assert (keyboard != NULL); + + closure = ply_keyboard_closure_new ((ply_keyboard_handler_t) escape_handler, + user_data); + ply_list_append_data (keyboard->escape_handler_list, closure); +} + + +void +ply_keyboard_remove_escape_handler (ply_keyboard_t *keyboard, + ply_keyboard_escape_handler_t escape_handler) +{ + ply_list_node_t *node; + + assert (keyboard != NULL); + + for (node = ply_list_get_first_node(keyboard->escape_handler_list); + node; node = ply_list_get_next_node(keyboard->escape_handler_list, node)) + { + ply_keyboard_closure_t *closure = ply_list_node_get_data (node); + if ((ply_keyboard_escape_handler_t) closure->function == escape_handler) + { + ply_keyboard_closure_free (closure); + ply_list_remove_node (keyboard->escape_handler_list, node); + return; + } + } +} + +void +ply_keyboard_add_enter_handler (ply_keyboard_t *keyboard, + ply_keyboard_enter_handler_t enter_handler, + void *user_data) +{ + ply_keyboard_closure_t *closure; + + assert (keyboard != NULL); + + closure = ply_keyboard_closure_new ((ply_keyboard_handler_t) enter_handler, + user_data); + + ply_list_append_data (keyboard->enter_handler_list, closure); +} + +void +ply_keyboard_remove_enter_handler (ply_keyboard_t *keyboard, + ply_keyboard_enter_handler_t enter_handler) +{ + ply_list_node_t *node; + + assert (keyboard != NULL); + + for (node = ply_list_get_first_node(keyboard->enter_handler_list); + node; node = ply_list_get_next_node(keyboard->enter_handler_list, node)) + { + ply_keyboard_closure_t *closure = ply_list_node_get_data (node); + if ((ply_keyboard_enter_handler_t) closure->function == enter_handler) + { + ply_keyboard_closure_free (closure); + ply_list_remove_node (keyboard->enter_handler_list, node); + return; + } + } +} + +/* 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/libplybootsplash/ply-keyboard.h b/src/libplybootsplash/ply-keyboard.h new file mode 100644 index 00000000..74683cf1 --- /dev/null +++ b/src/libplybootsplash/ply-keyboard.h @@ -0,0 +1,78 @@ +/* ply-keyboard.h - APIs for putting up a splash screen + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode + */ +#ifndef PLY_KEYBOARD_H +#define PLY_KEYBOARD_H + +#include +#include +#include + +#include "ply-buffer.h" +#include "ply-event-loop.h" +#include "ply-renderer.h" + +typedef struct _ply_keyboard ply_keyboard_t; + +typedef void (* ply_keyboard_input_handler_t) (void *user_data, + const char *keyboard_input, + size_t character_size); + +typedef void (* ply_keyboard_backspace_handler_t) (void *user_data); + +typedef void (* ply_keyboard_escape_handler_t) (void *user_data); + +typedef void (* ply_keyboard_enter_handler_t) (void *user_data, + const char *line); + +#ifndef PLY_HIDE_FUNCTION_DECLARATIONS +ply_keyboard_t *ply_keyboard_new_for_terminal (ply_terminal_t *terminal); +ply_keyboard_t *ply_keyboard_new_for_renderer (ply_renderer_t *renderer); +void ply_keyboard_free (ply_keyboard_t *keyboard); + +void ply_keyboard_add_input_handler (ply_keyboard_t *keyboard, + ply_keyboard_input_handler_t input_handler, + void *user_data); +void ply_keyboard_remove_input_handler (ply_keyboard_t *keyboard, + ply_keyboard_input_handler_t input_handler); +void ply_keyboard_add_backspace_handler (ply_keyboard_t *keyboard, + ply_keyboard_backspace_handler_t backspace_handler, + void *user_data); +void ply_keyboard_remove_backspace_handler (ply_keyboard_t *keyboard, + ply_keyboard_backspace_handler_t backspace_handler); +void ply_keyboard_add_escape_handler (ply_keyboard_t *keyboard, + ply_keyboard_escape_handler_t escape_handler, + void *user_data); +void ply_keyboard_remove_escape_handler (ply_keyboard_t *keyboard, + ply_keyboard_escape_handler_t escape_handler); +void ply_keyboard_add_enter_handler (ply_keyboard_t *keyboard, + ply_keyboard_enter_handler_t enter_handler, + void *user_data); +void ply_keyboard_remove_enter_handler (ply_keyboard_t *keyboard, + ply_keyboard_enter_handler_t enter_handler); + +bool ply_keyboard_watch_for_input (ply_keyboard_t *keyboard); +void ply_keyboard_stop_watching_for_input (ply_keyboard_t *keyboard); + +#endif + +#endif /* PLY_KEYBOARD_H */ +/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ From f183218c7361e5fec7e910e9edefac932386cfb7 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 23 Sep 2009 02:53:21 -0400 Subject: [PATCH 07/43] [libplybootsplash] Add console class This serves a few purposes: 1) To watch for VT changes 2) To make VT changes 3) To put the console in KD_GRAPHICS mode The latter is handled by the window class right now, but I want to drop the window class. --- src/libplybootsplash/ply-console.c | 406 +++++++++++++++++++++++++++++ src/libplybootsplash/ply-console.h | 70 +++++ 2 files changed, 476 insertions(+) create mode 100644 src/libplybootsplash/ply-console.c create mode 100644 src/libplybootsplash/ply-console.h diff --git a/src/libplybootsplash/ply-console.c b/src/libplybootsplash/ply-console.c new file mode 100644 index 00000000..7fb92980 --- /dev/null +++ b/src/libplybootsplash/ply-console.c @@ -0,0 +1,406 @@ +/* ply-console.c - console APIs + * + * 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 + */ +#include "config.h" +#include "ply-console.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ply-event-loop.h" +#include "ply-list.h" +#include "ply-logger.h" +#include "ply-utils.h" + +#ifndef TEXT_PALETTE_SIZE +#define TEXT_PALETTE_SIZE 48 +#endif + +typedef struct +{ + ply_console_active_vt_changed_handler_t handler; + void *user_data; +} ply_console_active_vt_changed_closure_t; + +struct _ply_console +{ + ply_event_loop_t *loop; + + int fd; + int active_vt; + int next_active_vt; + + ply_list_t *vt_change_closures; + ply_fd_watch_t *fd_watch; + + uint32_t is_open : 1; + uint32_t is_watching_for_vt_changes : 1; + uint32_t should_force_text_mode : 1; +}; + +static bool ply_console_open_device (ply_console_t *console); + +ply_console_t * +ply_console_new (void) +{ + ply_console_t *console; + + console = calloc (1, sizeof (ply_console_t)); + + console->loop = ply_event_loop_get_default (); + console->vt_change_closures = ply_list_new (); + console->fd = -1; + + return console; +} + +static void +ply_console_look_up_active_vt (ply_console_t *console) +{ + struct vt_stat console_state = { 0 }; + + if (ioctl (console->fd, VT_GETSTATE, &console_state) < 0) + return; + + console->active_vt = console_state.v_active; +} + +void +ply_console_set_mode (ply_console_t *console, + ply_console_mode_t mode) +{ + + assert (console != NULL); + assert (mode == PLY_CONSOLE_MODE_TEXT || mode == PLY_CONSOLE_MODE_GRAPHICS); + + if (console->should_force_text_mode) + mode = PLY_CONSOLE_MODE_TEXT; + + switch (mode) + { + case PLY_CONSOLE_MODE_TEXT: + if (ioctl (console->fd, KDSETMODE, KD_TEXT) < 0) + return; + break; + + case PLY_CONSOLE_MODE_GRAPHICS: + if (ioctl (console->fd, KDSETMODE, KD_GRAPHICS) < 0) + return; + break; + } +} + +void +ply_console_force_text_mode (ply_console_t *console, + bool should_force) +{ + console->should_force_text_mode = should_force; +} + +static void +on_tty_disconnected (ply_console_t *console) +{ + ply_trace ("console tty disconnected (fd %d)", console->fd); + console->fd_watch = NULL; + console->fd = -1; + + ply_trace ("trying to reopen console"); + ply_console_open_device (console); +} + +static void +do_active_vt_changed (ply_console_t *console) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (console->vt_change_closures); + while (node != NULL) + { + ply_console_active_vt_changed_closure_t *closure; + ply_list_node_t *next_node; + + closure = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (console->vt_change_closures, node); + + if (closure->handler != NULL) + closure->handler (closure->user_data, console); + + node = next_node; + } +} + +static void +on_leave_vt (ply_console_t *console) +{ + ioctl (console->fd, VT_RELDISP, 1); + + if (console->next_active_vt > 0) + { + ioctl (console->fd, VT_WAITACTIVE, console->next_active_vt); + console->next_active_vt = 0; + } + + ply_console_look_up_active_vt (console); + do_active_vt_changed (console); +} + +static void +on_enter_vt (ply_console_t *console) +{ + ioctl (console->fd, VT_RELDISP, VT_ACKACQ); + + ply_console_look_up_active_vt (console); + do_active_vt_changed (console); +} + +static void +ply_console_watch_for_vt_changes (ply_console_t *console) +{ + assert (console != NULL); + assert (console->fd >= 0); + + struct vt_mode mode = { 0 }; + + if (console->is_watching_for_vt_changes) + return; + + mode.mode = VT_PROCESS; + mode.relsig = SIGUSR1; + mode.acqsig = SIGUSR2; + + if (!ioctl (console->fd, VT_SETMODE, &mode) < 0) + return; + + ply_event_loop_watch_signal (console->loop, + SIGUSR1, + (ply_event_handler_t) + on_leave_vt, console); + + ply_event_loop_watch_signal (console->loop, + SIGUSR2, + (ply_event_handler_t) + on_enter_vt, console); + + console->is_watching_for_vt_changes = true; +} + +static void +ply_console_stop_watching_for_vt_changes (ply_console_t *console) +{ + struct vt_mode mode = { 0 }; + + if (!console->is_watching_for_vt_changes) + return; + + console->is_watching_for_vt_changes = false; + + ply_event_loop_stop_watching_signal (console->loop, SIGUSR1); + ply_event_loop_stop_watching_signal (console->loop, SIGUSR2); + + mode.mode = VT_AUTO; + ioctl (console->fd, VT_SETMODE, &mode); +} + +static bool +ply_console_open_device (ply_console_t *console) +{ + assert (console != NULL); + assert (console->fd < 0); + assert (console->fd_watch == NULL); + + console->fd = open ("/dev/tty0", O_RDWR | O_NOCTTY); + + if (console->fd < 0) + return false; + + console->fd_watch = ply_event_loop_watch_fd (console->loop, console->fd, + PLY_EVENT_LOOP_FD_STATUS_NONE, + (ply_event_handler_t) NULL, + (ply_event_handler_t) on_tty_disconnected, + console); + + ply_console_look_up_active_vt (console); + + return true; +} + +bool +ply_console_open (ply_console_t *console) +{ + assert (console != NULL); + + if (!ply_console_open_device (console)) + { + ply_trace ("could not open console: %m"); + return false; + } + + ply_console_watch_for_vt_changes (console); + + console->is_open = true; + + return true; +} + + +int +ply_console_get_fd (ply_console_t *console) +{ + return console->fd; +} + +bool +ply_console_is_open (ply_console_t *console) +{ + return console->is_open; +} + +void +ply_console_close (ply_console_t *console) +{ + console->is_open = false; + + ply_console_stop_watching_for_vt_changes (console); + + if (console->fd_watch != NULL) + { + ply_trace ("stop watching tty fd"); + ply_event_loop_stop_watching_fd (console->loop, console->fd_watch); + console->fd_watch = NULL; + } + + close (console->fd); + console->fd = -1; +} + +static void +free_vt_change_closures (ply_console_t *console) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (console->vt_change_closures); + while (node != NULL) + { + ply_console_active_vt_changed_closure_t *closure; + ply_list_node_t *next_node; + + closure = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (console->vt_change_closures, node); + + free (closure); + node = next_node; + } + ply_list_free (console->vt_change_closures); +} + +void +ply_console_free (ply_console_t *console) +{ + if (console == NULL) + return; + + ply_console_close (console); + + free_vt_change_closures (console); + free (console); +} + +int +ply_console_get_active_vt (ply_console_t *console) +{ + return console->active_vt; +} + +bool +ply_console_set_active_vt (ply_console_t *console, + int vt_number) +{ + assert (console != NULL); + assert (vt_number > 0); + + if (vt_number == console->active_vt) + return true; + + if (ioctl (console->fd, VT_ACTIVATE, vt_number) < 0) + return false; + + console->next_active_vt = vt_number; + + return true; +} + +void +ply_console_watch_for_active_vt_change (ply_console_t *console, + ply_console_active_vt_changed_handler_t active_vt_changed_handler, + void *user_data) +{ + ply_console_active_vt_changed_closure_t *closure; + + closure = calloc (1, sizeof (*closure)); + closure->handler = active_vt_changed_handler; + closure->user_data = user_data; + + ply_list_append_data (console->vt_change_closures, closure); +} + +void +ply_console_stop_watching_for_active_vt_change (ply_console_t *console, + ply_console_active_vt_changed_handler_t active_vt_changed_handler, + void *user_data) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (console->vt_change_closures); + while (node != NULL) + { + ply_console_active_vt_changed_closure_t *closure; + ply_list_node_t *next_node; + + closure = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (console->vt_change_closures, node); + + if (closure->handler == active_vt_changed_handler && + closure->user_data == user_data) + { + free (closure); + ply_list_remove_node (console->vt_change_closures, node); + } + + node = next_node; + } +} + +/* 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/libplybootsplash/ply-console.h b/src/libplybootsplash/ply-console.h new file mode 100644 index 00000000..36263bbc --- /dev/null +++ b/src/libplybootsplash/ply-console.h @@ -0,0 +1,70 @@ +/* ply-console.h - APIs for consoleing text + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode + */ +#ifndef PLY_CONSOLE_H +#define PLY_CONSOLE_H + +#include +#include +#include +#include + +typedef struct _ply_console ply_console_t; +typedef void (* ply_console_active_vt_changed_handler_t) (void *user_data, + ply_console_t *console); + +typedef enum +{ + PLY_CONSOLE_MODE_TEXT, + PLY_CONSOLE_MODE_GRAPHICS +} ply_console_mode_t; + +#ifndef PLY_HIDE_FUNCTION_DECLARATIONS +ply_console_t *ply_console_new (void); + +void ply_console_free (ply_console_t *console); + +bool ply_console_open (ply_console_t *console); +bool ply_console_is_open (ply_console_t *console); +void ply_console_close (ply_console_t *console); + +void ply_console_set_mode (ply_console_t *console, + ply_console_mode_t mode); + +void ply_console_force_text_mode (ply_console_t *console, + bool should_force); + +int ply_console_get_fd (ply_console_t *console); +int ply_console_get_active_vt (ply_console_t *console); +bool ply_console_set_active_vt (ply_console_t *console, + int vt_number); + +void ply_console_watch_for_active_vt_change (ply_console_t *console, + ply_console_active_vt_changed_handler_t active_vt_changed_handler, + void *user_data); +void ply_console_stop_watching_for_active_vt_change (ply_console_t *console, + ply_console_active_vt_changed_handler_t active_vt_changed_handler, + void *user_data); + +#endif + +#endif /* PLY_CONSOLE_H */ +/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ From 48d4f00052c119b3324d68eb169a2ddbdf080594 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 16:57:13 -0400 Subject: [PATCH 08/43] [libplybootsplash] Add terminal class This is the terminal settings portion of the window class. With this commit and subsequent commits to split out the higher level text output, and graphical output portions, we should be able to drop window in favor of the new display classes. --- src/libplybootsplash/Makefile.am | 2 + src/libplybootsplash/ply-terminal.c | 513 ++++++++++++++++++++++++++++ src/libplybootsplash/ply-terminal.h | 82 +++++ 3 files changed, 597 insertions(+) create mode 100644 src/libplybootsplash/ply-terminal.c create mode 100644 src/libplybootsplash/ply-terminal.h diff --git a/src/libplybootsplash/Makefile.am b/src/libplybootsplash/Makefile.am index 51b9b842..adf75f1c 100644 --- a/src/libplybootsplash/Makefile.am +++ b/src/libplybootsplash/Makefile.am @@ -18,6 +18,7 @@ libplybootsplash_HEADERS = \ ply-pixel-buffer.h \ ply-progress-animation.h \ ply-progress-bar.h \ + ply-terminal.h \ ply-text-progress-bar.h \ ply-throbber.h \ ply-window.h @@ -43,6 +44,7 @@ libplybootsplash_la_SOURCES = \ ply-animation.c \ ply-progress-animation.c \ ply-text-progress-bar.c \ + ply-terminal.c \ ply-pixel-buffer.c \ ply-window.c \ ply-boot-splash.c diff --git a/src/libplybootsplash/ply-terminal.c b/src/libplybootsplash/ply-terminal.c new file mode 100644 index 00000000..41eab543 --- /dev/null +++ b/src/libplybootsplash/ply-terminal.c @@ -0,0 +1,513 @@ +/* ply-terminal.c - APIs for terminaling text + * + * 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 + */ +#include "config.h" +#include "ply-terminal.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ply-buffer.h" +#include "ply-event-loop.h" +#include "ply-list.h" +#include "ply-logger.h" +#include "ply-utils.h" + +#ifndef TEXT_PALETTE_SIZE +#define TEXT_PALETTE_SIZE 48 +#endif + +struct _ply_terminal +{ + ply_event_loop_t *loop; + + struct termios original_term_attributes; + + char *name; + int fd; + int vt_number; + + ply_fd_watch_t *fd_watch; + ply_terminal_color_t foreground_color; + ply_terminal_color_t background_color; + + uint8_t original_color_palette[TEXT_PALETTE_SIZE]; + uint8_t color_palette[TEXT_PALETTE_SIZE]; + + int number_of_rows; + int number_of_columns; + + uint32_t original_term_attributes_saved : 1; + uint32_t supports_text_color : 1; + uint32_t is_open : 1; +}; + +static bool ply_terminal_open_device (ply_terminal_t *terminal); + +ply_terminal_t * +ply_terminal_new (const char *device_name) +{ + ply_terminal_t *terminal; + + terminal = calloc (1, sizeof (ply_terminal_t)); + + terminal->loop = ply_event_loop_get_default (); + if (device_name != NULL) + { + if (strncmp (device_name, "/dev/", strlen ("/dev/")) == 0) + terminal->name = strdup (device_name); + else + asprintf (&terminal->name, "/dev/%s", device_name); + } + terminal->fd = -1; + terminal->vt_number = -1; + + return terminal; +} + +static void +ply_terminal_look_up_color_palette (ply_terminal_t *terminal) +{ + if (ioctl (terminal->fd, GIO_CMAP, terminal->color_palette) < 0) + terminal->supports_text_color = false; + else + terminal->supports_text_color = true; +} + +static bool +ply_terminal_change_color_palette (ply_terminal_t *terminal) +{ + if (!terminal->supports_text_color) + return true; + + if (ioctl (terminal->fd, PIO_CMAP, terminal->color_palette) < 0) + return false; + + return true; +} + +static void +ply_terminal_save_color_palette (ply_terminal_t *terminal) +{ + if (!terminal->supports_text_color) + return; + + memcpy (terminal->original_color_palette, terminal->color_palette, + TEXT_PALETTE_SIZE); +} + +static void +ply_terminal_restore_color_palette (ply_terminal_t *terminal) +{ + if (!terminal->supports_text_color) + return; + + memcpy (terminal->color_palette, terminal->original_color_palette, + TEXT_PALETTE_SIZE); + + ply_terminal_change_color_palette (terminal); +} + +void +ply_terminal_reset_colors (ply_terminal_t *terminal) +{ + assert (terminal != NULL); + + ply_terminal_restore_color_palette (terminal); +} + +bool +ply_terminal_set_unbuffered_input (ply_terminal_t *terminal) +{ + struct termios term_attributes; + + tcgetattr (terminal->fd, &term_attributes); + + if (!terminal->original_term_attributes_saved) + { + terminal->original_term_attributes = term_attributes; + terminal->original_term_attributes_saved = true; + } + + cfmakeraw (&term_attributes); + + /* Make \n return go to the beginning of the next line */ + term_attributes.c_oflag |= ONLCR; + + if (tcsetattr (terminal->fd, TCSAFLUSH, &term_attributes) != 0) + return false; + + return true; +} + +bool +ply_terminal_set_buffered_input (ply_terminal_t *terminal) +{ + struct termios term_attributes; + + tcgetattr (terminal->fd, &term_attributes); + + /* If someone already messed with the terminal settings, + * and they seem good enough, bail + */ + if (term_attributes.c_lflag & ICANON) + return true; + + /* If we don't know the original term attributes, or they were originally sucky, + * then invent some that are probably good enough. + */ + if (!terminal->original_term_attributes_saved || !(terminal->original_term_attributes.c_lflag & ICANON)) + { + term_attributes.c_iflag |= IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON; + term_attributes.c_oflag |= OPOST; + term_attributes.c_lflag |= ECHO | ECHONL | ICANON | ISIG | IEXTEN; + + if (tcsetattr (terminal->fd, TCSAFLUSH, &term_attributes) != 0) + return false; + + return true; + } + + if (tcsetattr (terminal->fd, TCSAFLUSH, &terminal->original_term_attributes) != 0) + return false; + + return true; +} + +void +ply_terminal_write (ply_terminal_t *terminal, + const char *format, + ...) +{ + va_list args; + char *string; + + assert (terminal != NULL); + assert (format != NULL); + + string = NULL; + va_start (args, format); + vasprintf (&string, format, args); + va_end (args); + + write (terminal->fd, string, strlen (string)); + free (string); +} + +static void +on_tty_disconnected (ply_terminal_t *terminal) +{ + ply_trace ("tty disconnected (fd %d)", terminal->fd); + terminal->fd_watch = NULL; + terminal->fd = -1; + + if (terminal->name != NULL) + { + ply_trace ("trying to reopen terminal '%s'", terminal->name); + ply_terminal_open_device (terminal); + } +} + +static int +get_active_vt (void) +{ + int console_fd; + struct vt_stat console_state = { 0 }; + + console_fd = open ("/dev/tty0", O_RDONLY | O_NOCTTY); + + if (console_fd < 0) + goto out; + + if (ioctl (console_fd, VT_GETSTATE, &console_state) < 0) + goto out; + +out: + if (console_fd >= 0) + close (console_fd); + + return console_state.v_active; +} + +static bool +ply_terminal_look_up_geometry (ply_terminal_t *terminal) +{ + struct winsize terminal_size; + + ply_trace ("looking up terminal text geometry"); + + if (ioctl (terminal->fd, TIOCGWINSZ, &terminal_size) < 0) + { + ply_trace ("could not read terminal text geometry: %m"); + terminal->number_of_columns = 80; + terminal->number_of_rows = 24; + return false; + } + + terminal->number_of_rows = terminal_size.ws_row; + terminal->number_of_columns = terminal_size.ws_col; + + ply_trace ("terminal is now %dx%d text cells", + terminal->number_of_columns, + terminal->number_of_rows); + + return true; +} + +static void +ply_terminal_check_for_vt (ply_terminal_t *terminal) +{ + int major_number, minor_number; + struct stat file_attributes; + + assert (terminal != NULL); + assert (terminal->fd >= 0); + + if (fstat (terminal->fd, &file_attributes) != 0) + return; + + major_number = major (file_attributes.st_rdev); + minor_number = minor (file_attributes.st_rdev); + + if (major_number == TTY_MAJOR) + terminal->vt_number = minor_number; + else + terminal->vt_number = -1; +} + +static bool +ply_terminal_open_device (ply_terminal_t *terminal) +{ + assert (terminal != NULL); + assert (terminal->name != NULL); + assert (terminal->fd < 0); + assert (terminal->fd_watch == NULL); + + terminal->fd = open (terminal->name, O_RDWR | O_NOCTTY); + + if (terminal->fd < 0) + return false; + + terminal->fd_watch = ply_event_loop_watch_fd (terminal->loop, terminal->fd, + PLY_EVENT_LOOP_FD_STATUS_NONE, + (ply_event_handler_t) NULL, + (ply_event_handler_t) on_tty_disconnected, + terminal); + + ply_terminal_check_for_vt (terminal); + + return true; +} + +bool +ply_terminal_open (ply_terminal_t *terminal) +{ + assert (terminal != NULL); + + if (terminal->name == NULL) + { + char tty_name[512] = ""; + + terminal->vt_number = get_active_vt (); + + if (readlink ("/proc/self/fd/0", tty_name, sizeof (tty_name) - 1) < 0) + { + ply_trace ("could not read tty name of fd 0"); + return false; + } + + terminal->name = strdup (tty_name); + } + + ply_trace ("trying to open terminal '%s'", terminal->name); + + if (!ply_terminal_open_device (terminal)) + { + ply_trace ("could not open %s : %m", terminal->name); + return false; + } + + if (!ply_terminal_set_unbuffered_input (terminal)) + ply_trace ("terminal '%s' will be line buffered", terminal->name); + + ply_terminal_look_up_geometry (terminal); + + ply_terminal_look_up_color_palette (terminal); + ply_terminal_save_color_palette (terminal); + + ply_event_loop_watch_signal (terminal->loop, + SIGWINCH, + (ply_event_handler_t) + ply_terminal_look_up_geometry, + terminal); + + terminal->is_open = true; + + return true; +} + +int +ply_terminal_get_fd (ply_terminal_t *terminal) +{ + return terminal->fd; +} + +bool +ply_terminal_is_open (ply_terminal_t *terminal) +{ + return terminal->is_open; +} + +void +ply_terminal_close (ply_terminal_t *terminal) +{ + terminal->is_open = false; + + ply_trace ("restoring color palette"); + ply_terminal_restore_color_palette (terminal); + + if (terminal->fd_watch != NULL) + { + ply_trace ("stop watching tty fd"); + ply_event_loop_stop_watching_fd (terminal->loop, terminal->fd_watch); + terminal->fd_watch = NULL; + } + + if (terminal->loop != NULL) + { + ply_trace ("stop watching SIGWINCH signal"); + ply_event_loop_stop_watching_signal (terminal->loop, SIGWINCH); + } + + ply_trace ("setting buffered input"); + ply_terminal_set_buffered_input (terminal); + + close (terminal->fd); + terminal->fd = -1; +} + +int +ply_terminal_get_number_of_columns (ply_terminal_t *terminal) +{ + return terminal->number_of_columns; +} + +int +ply_terminal_get_number_of_rows (ply_terminal_t *terminal) +{ + return terminal->number_of_rows; +} + +uint32_t +ply_terminal_get_color_hex_value (ply_terminal_t *terminal, + ply_terminal_color_t color) +{ + uint8_t red, green, blue; + uint32_t hex_value; + + assert (terminal != NULL); + assert (color <= PLY_TERMINAL_COLOR_WHITE); + + red = (uint8_t) *(terminal->color_palette + 3 * color); + green = (uint8_t) *(terminal->color_palette + 3 * color + 1); + blue = (uint8_t) *(terminal->color_palette + 3 * color + 2); + + hex_value = red << 16 | green << 8 | blue; + + return hex_value; +} + +void +ply_terminal_set_color_hex_value (ply_terminal_t *terminal, + ply_terminal_color_t color, + uint32_t hex_value) +{ + uint8_t red, green, blue; + + assert (terminal != NULL); + assert (color <= PLY_TERMINAL_COLOR_WHITE); + + red = (uint8_t) ((hex_value >> 16) & 0xff); + green = (uint8_t) ((hex_value >> 8) & 0xff); + blue = (uint8_t) (hex_value & 0xff); + + *(terminal->color_palette + 3 * color) = red; + *(terminal->color_palette + 3 * color + 1) = green; + *(terminal->color_palette + 3 * color + 2) = blue; + + ply_terminal_change_color_palette (terminal); +} + +bool +ply_terminal_supports_color (ply_terminal_t *terminal) +{ + return terminal->supports_text_color; +} + +static void +ply_terminal_detach_from_event_loop (ply_terminal_t *terminal) +{ + assert (terminal != NULL); + terminal->loop = NULL; + terminal->fd_watch = NULL; +} + +void +ply_terminal_free (ply_terminal_t *terminal) +{ + if (terminal == NULL) + return; + + free (terminal->name); + + if (terminal->loop != NULL) + ply_event_loop_stop_watching_for_exit (terminal->loop, + (ply_event_loop_exit_handler_t) + ply_terminal_detach_from_event_loop, + terminal); + + ply_terminal_close (terminal); + + free (terminal); +} + +int +ply_terminal_get_vt_number (ply_terminal_t *terminal) +{ + return terminal->vt_number; +} + +/* 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/libplybootsplash/ply-terminal.h b/src/libplybootsplash/ply-terminal.h new file mode 100644 index 00000000..21689d19 --- /dev/null +++ b/src/libplybootsplash/ply-terminal.h @@ -0,0 +1,82 @@ +/* ply-terminal.h - APIs for terminaling text + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode + */ +#ifndef PLY_TERMINAL_H +#define PLY_TERMINAL_H + +#include +#include +#include +#include + +#include "ply-buffer.h" +#include "ply-event-loop.h" + +typedef struct _ply_terminal ply_terminal_t; + +typedef enum +{ + PLY_TERMINAL_COLOR_BLACK = 0, + PLY_TERMINAL_COLOR_RED, + PLY_TERMINAL_COLOR_GREEN, + PLY_TERMINAL_COLOR_BROWN, + PLY_TERMINAL_COLOR_BLUE, + PLY_TERMINAL_COLOR_MAGENTA, + PLY_TERMINAL_COLOR_CYAN, + PLY_TERMINAL_COLOR_WHITE, + PLY_TERMINAL_COLOR_DEFAULT = PLY_TERMINAL_COLOR_WHITE + 2 +} ply_terminal_color_t; + +#ifndef PLY_HIDE_FUNCTION_DECLARATIONS +ply_terminal_t *ply_terminal_new (const char *device_name); + +void ply_terminal_free (ply_terminal_t *terminal); + +bool ply_terminal_open (ply_terminal_t *terminal); +int ply_terminal_get_fd (ply_terminal_t *terminal); +bool ply_terminal_is_open (ply_terminal_t *terminal); +void ply_terminal_close (ply_terminal_t *terminal); +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); + +__attribute__((__format__ (__printf__, 2, 3))) +void ply_terminal_write (ply_terminal_t *terminal, + const char *format, + ...); +int ply_terminal_get_number_of_columns (ply_terminal_t *terminal); +int ply_terminal_get_number_of_rows (ply_terminal_t *terminal); + +bool ply_terminal_supports_color (ply_terminal_t *terminal); +uint32_t ply_terminal_get_color_hex_value (ply_terminal_t *terminal, + ply_terminal_color_t color); + +void ply_terminal_set_color_hex_value (ply_terminal_t *terminal, + ply_terminal_color_t color, + uint32_t hex_value); + +int ply_terminal_get_vt_number (ply_terminal_t *terminal); + +#endif + +#endif /* PLY_TERMINAL_H */ +/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ From 846d609e5fb68bb7d576ae71c1662246783abc06 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 21 Aug 2009 09:53:33 -0400 Subject: [PATCH 09/43] [libplybootsplash] Add renderer class In order to support multiple rendering backends, and multi-head monitor layouts, I'm moving the actually rendering to render plugins. Examples of plugins could be frame-buffer, drm fb, and x11 (for debugging). The renderer class is responsible for loading the appropriate rendering backend, and providing an interface for the rendering backend to advertise multiple displays. Right now we only check for a frame-buffer plugin, although, it isn't implemented yet. --- src/libplybootsplash/Makefile.am | 5 + src/libplybootsplash/ply-renderer-plugin.h | 71 +++++ src/libplybootsplash/ply-renderer.c | 353 +++++++++++++++++++++ src/libplybootsplash/ply-renderer.h | 70 ++++ src/plugins/Makefile.am | 2 +- 5 files changed, 500 insertions(+), 1 deletion(-) create mode 100644 src/libplybootsplash/ply-renderer-plugin.h create mode 100644 src/libplybootsplash/ply-renderer.c create mode 100644 src/libplybootsplash/ply-renderer.h diff --git a/src/libplybootsplash/Makefile.am b/src/libplybootsplash/Makefile.am index adf75f1c..1172cf1d 100644 --- a/src/libplybootsplash/Makefile.am +++ b/src/libplybootsplash/Makefile.am @@ -10,6 +10,7 @@ libplybootsplash_HEADERS = \ ply-animation.h \ ply-boot-splash.h \ ply-boot-splash-plugin.h \ + ply-console.h \ ply-entry.h \ ply-image.h \ ply-keyboard.h \ @@ -18,6 +19,8 @@ libplybootsplash_HEADERS = \ ply-pixel-buffer.h \ ply-progress-animation.h \ ply-progress-bar.h \ + ply-renderer.h \ + ply-renderer-plugin.h \ ply-terminal.h \ ply-text-progress-bar.h \ ply-throbber.h \ @@ -35,6 +38,7 @@ libplybootsplash_la_LDFLAGS = -export-symbols-regex '^[^_].*' \ -no-undefined libplybootsplash_la_SOURCES = \ $(libplybootsplash_HEADERS) \ + ply-console.c \ ply-entry.c \ ply-image.c \ ply-keyboard.c \ @@ -46,6 +50,7 @@ libplybootsplash_la_SOURCES = \ ply-text-progress-bar.c \ ply-terminal.c \ ply-pixel-buffer.c \ + ply-renderer.c \ ply-window.c \ ply-boot-splash.c diff --git a/src/libplybootsplash/ply-renderer-plugin.h b/src/libplybootsplash/ply-renderer-plugin.h new file mode 100644 index 00000000..6acb8928 --- /dev/null +++ b/src/libplybootsplash/ply-renderer-plugin.h @@ -0,0 +1,71 @@ +/* ply-renderer-plugin.h - plugin interface for ply_renderer_t + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode + */ +#ifndef PLY_RENDERER_PLUGIN_H +#define PLY_RENDERER_PLUGIN_H + +#include +#include +#include + +#include "ply-console.h" +#include "ply-event-loop.h" +#include "ply-list.h" +#include "ply-region.h" +#include "ply-renderer.h" + +typedef struct _ply_renderer_plugin ply_renderer_plugin_t; +typedef struct _ply_renderer_backend ply_renderer_backend_t; + +typedef struct +{ + ply_renderer_backend_t * (* create_backend) (const char *device_name, + ply_terminal_t *terminal, + ply_console_t *console); + void (* destroy_backend) (ply_renderer_backend_t *backend); + bool (* open_device) (ply_renderer_backend_t *backend); + void (* close_device) (ply_renderer_backend_t *backend); + bool (* query_device) (ply_renderer_backend_t *backend); + bool (* map_to_device) (ply_renderer_backend_t *backend); + void (* unmap_from_device) (ply_renderer_backend_t *backend); + void (* flush_head) (ply_renderer_backend_t *backend, + ply_renderer_head_t *head); + + ply_list_t * (* get_heads) (ply_renderer_backend_t *backend); + + ply_pixel_buffer_t * (* get_buffer_for_head) (ply_renderer_backend_t *backend, + ply_renderer_head_t *head); + + ply_renderer_input_source_t * (* get_input_source) (ply_renderer_backend_t *backend); + bool (* open_input_source) (ply_renderer_backend_t *backend, + ply_renderer_input_source_t *input_source); + + void (* set_handler_for_input_source) (ply_renderer_backend_t *backend, + ply_renderer_input_source_t *input_source, + ply_renderer_input_source_handler_t handler, + void *user_data); + + void (* close_input_source) (ply_renderer_backend_t *backend, + ply_renderer_input_source_t *input_source); +} ply_renderer_plugin_interface_t; + +#endif /* PLY_RENDERER_PLUGIN_H */ +/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/libplybootsplash/ply-renderer.c b/src/libplybootsplash/ply-renderer.c new file mode 100644 index 00000000..510479d8 --- /dev/null +++ b/src/libplybootsplash/ply-renderer.c @@ -0,0 +1,353 @@ +/* ply-renderer.c - renderer abstraction + * + * Copyright (C) 2006, 2007, 2008, 2009 Red Hat, Inc. + * 2008 Charlie Brej + * + * 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: Charlie Brej + * Kristian Høgsberg + * Ray Strode + */ +#include "config.h" +#include "ply-renderer.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ply-renderer-plugin.h" +#include "ply-buffer.h" +#include "ply-console.h" +#include "ply-event-loop.h" +#include "ply-list.h" +#include "ply-logger.h" +#include "ply-utils.h" + +struct _ply_renderer +{ + ply_event_loop_t *loop; + ply_module_handle_t *module_handle; + const ply_renderer_plugin_interface_t *plugin_interface; + ply_renderer_backend_t *backend; + + char *device_name; + ply_console_t *console; +}; + +typedef const ply_renderer_plugin_interface_t * + (* get_backend_interface_function_t) (void); + +static void ply_renderer_unload_plugin (ply_renderer_t *renderer); + +ply_renderer_t * +ply_renderer_new (const char *device_name, + ply_terminal_t *terminal, + ply_console_t *console) +{ + ply_renderer_t *renderer; + + renderer = calloc (1, sizeof (struct _ply_renderer)); + + if (device_name != NULL) + renderer->device_name = strdup (device_name); + + renderer->terminal = terminal; + renderer->console = console; + + return renderer; +} + +void +ply_renderer_free (ply_renderer_t *renderer) +{ + if (renderer == NULL) + return; + + if (renderer->plugin_interface != NULL) + { + ply_trace ("Unloading renderer backend plugin"); + ply_renderer_unload_plugin (renderer); + } + + free (renderer->device_name); + free (renderer); +} + +static bool +ply_renderer_load_plugin (ply_renderer_t *renderer, + const char *module_path) +{ + assert (renderer != NULL); + + get_backend_interface_function_t get_renderer_backend_interface; + + renderer->module_handle = ply_open_module (module_path); + + if (renderer->module_handle == NULL) + return false; + + get_renderer_backend_interface = (get_backend_interface_function_t) + ply_module_look_up_function (renderer->module_handle, + "ply_renderer_backend_get_interface"); + + if (get_renderer_backend_interface == NULL) + { + ply_save_errno (); + ply_trace ("module '%s' is not a renderer plugin", + module_path); + ply_close_module (renderer->module_handle); + renderer->module_handle = NULL; + ply_restore_errno (); + return false; + } + + renderer->plugin_interface = get_renderer_backend_interface (); + + if (renderer->plugin_interface == NULL) + { + ply_trace ("module '%s' is not a valid renderer plugin", + module_path); + ply_save_errno (); + ply_close_module (renderer->module_handle); + renderer->module_handle = NULL; + ply_restore_errno (); + return false; + } + + renderer->backend = renderer->plugin_interface->create_backend (renderer->device_name, + renderer->terminal, + renderer->console); + + if (renderer->backend == NULL) + { + ply_save_errno (); + ply_trace ("module '%s' renderer backend could not be created", + module_path); + ply_close_module (renderer->module_handle); + renderer->module_handle = NULL; + ply_restore_errno (); + return false; + } + + return true; +} + +static void +ply_renderer_unload_plugin (ply_renderer_t *renderer) +{ + assert (renderer != NULL); + assert (renderer->plugin_interface != NULL); + assert (renderer->module_handle != NULL); + + ply_close_module (renderer->module_handle); + renderer->plugin_interface = NULL; + renderer->module_handle = NULL; +} + +static bool +ply_renderer_open_device (ply_renderer_t *renderer) +{ + assert (renderer != NULL); + assert (renderer->plugin_interface != NULL); + + return renderer->plugin_interface->open_device (renderer->backend); +} + +static void +ply_renderer_close_device (ply_renderer_t *renderer) +{ + assert (renderer != NULL); + assert (renderer->plugin_interface != NULL); + + renderer->plugin_interface->close_device (renderer->backend); +} + +static bool +ply_renderer_query_device (ply_renderer_t *renderer) +{ + assert (renderer != NULL); + assert (renderer->plugin_interface != NULL); + + return renderer->plugin_interface->query_device (renderer->backend); +} + +static bool +ply_renderer_map_to_device (ply_renderer_t *renderer) +{ + assert (renderer != NULL); + assert (renderer->plugin_interface != NULL); + + return renderer->plugin_interface->map_to_device (renderer->backend); +} + +static void +ply_renderer_unmap_from_device (ply_renderer_t *renderer) +{ + assert (renderer != NULL); + assert (renderer->plugin_interface != NULL); + + renderer->plugin_interface->unmap_from_device (renderer->backend); +} + +bool +ply_renderer_open (ply_renderer_t *renderer) +{ + int i; + + /* FIXME: at some point we may want to make this + * part more dynamic (so you don't have to edit this + * list to add a new renderer) + */ + const char *known_plugins[] = + { + PLYMOUTH_PLUGIN_PATH "renderers/frame-buffer.so", + NULL + }; + + for (i = 0; known_plugins[i] != NULL; i++) + { + const char *plugin_path; + + plugin_path = known_plugins[i]; + + if (!ply_renderer_load_plugin (renderer, plugin_path)) + continue; + + if (!ply_renderer_open_device (renderer)) + { + ply_trace ("could not open rendering device for plugin %s", + plugin_path); + ply_renderer_unload_plugin (renderer); + continue; + } + + if (!ply_renderer_query_device (renderer)) + { + ply_trace ("could not query rendering device for plugin %s", + plugin_path); + ply_renderer_unload_plugin (renderer); + continue; + } + + if (!ply_renderer_map_to_device (renderer)) + { + ply_trace ("could not map renderer to device for plugin %s", + plugin_path); + ply_renderer_unload_plugin (renderer); + continue; + } + return true; + } + + ply_trace ("could not find suitable rendering plugin"); + return false; +} + +void +ply_renderer_close (ply_renderer_t *renderer) +{ + ply_renderer_unmap_from_device (renderer); + ply_renderer_close_device (renderer); +} + +ply_list_t * +ply_renderer_get_heads (ply_renderer_t *renderer) +{ + assert (renderer->plugin_interface != NULL); + + return renderer->plugin_interface->get_heads (renderer->backend); +} + +ply_pixel_buffer_t * +ply_renderer_get_buffer_for_head (ply_renderer_t *renderer, + ply_renderer_head_t *head) +{ + assert (renderer != NULL); + assert (renderer->plugin_interface != NULL); + assert (head != NULL); + + return renderer->plugin_interface->get_buffer_for_head (renderer->backend, + head); +} + +void +ply_renderer_flush_head (ply_renderer_t *renderer, + ply_renderer_head_t *head) +{ + assert (renderer != NULL); + assert (renderer->plugin_interface != NULL); + assert (head != NULL); + + if (ply_console_get_active_vt (renderer->console) != + ply_terminal_get_vt_number (renderer->terminal)) + return; + + renderer->plugin_interface->flush_head (renderer->backend, head); +} + +ply_renderer_input_source_t * +ply_renderer_get_input_source (ply_renderer_t *renderer) +{ + assert (renderer != NULL); + assert (renderer->plugin_interface != NULL); + + return renderer->plugin_interface->get_input_source (renderer->backend); +} + +bool +ply_renderer_open_input_source (ply_renderer_t *renderer, + ply_renderer_input_source_t *input_source) +{ + assert (renderer != NULL); + assert (input_source != NULL); + + return renderer->plugin_interface->open_input_source (renderer->backend, + input_source); +} + +void +ply_renderer_set_handler_for_input_source (ply_renderer_t *renderer, + ply_renderer_input_source_t *input_source, + ply_renderer_input_source_handler_t handler, + void *user_data) +{ + assert (renderer != NULL); + assert (input_source != NULL); + + renderer->plugin_interface->set_handler_for_input_source (renderer->backend, + input_source, + handler, + user_data); +} + +void +ply_renderer_close_input_source (ply_renderer_t *renderer, + ply_renderer_input_source_t *input_source) +{ + assert (renderer != NULL); + assert (input_source != NULL); + + renderer->plugin_interface->close_input_source (renderer->backend, + input_source); +} + +/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/libplybootsplash/ply-renderer.h b/src/libplybootsplash/ply-renderer.h new file mode 100644 index 00000000..da03e8d8 --- /dev/null +++ b/src/libplybootsplash/ply-renderer.h @@ -0,0 +1,70 @@ +/* ply-renderer.h - rendering abstraction + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode + */ +#ifndef PLY_RENDERER_H +#define PLY_RENDERER_H + +#include +#include + +#include "ply-buffer.h" +#include "ply-console.h" +#include "ply-list.h" +#include "ply-pixel-buffer.h" +#include "ply-terminal.h" +#include "ply-utils.h" + +typedef struct _ply_renderer ply_renderer_t; +typedef struct _ply_renderer_head ply_renderer_head_t; +typedef struct _ply_renderer_input_source ply_renderer_input_source_t; + +typedef void (* ply_renderer_input_source_handler_t) (void *user_data, + ply_buffer_t *key_buffer, + ply_renderer_input_source_t *input_source); + +#ifndef PLY_HIDE_FUNCTION_DECLARATIONS +ply_renderer_t *ply_renderer_new (const char *device_name, + ply_terminal_t *terminal, + ply_console_t *console); +void ply_renderer_free (ply_renderer_t *renderer); +bool ply_renderer_open (ply_renderer_t *renderer); +void ply_renderer_close (ply_renderer_t *renderer); +ply_list_t *ply_renderer_get_heads (ply_renderer_t *renderer); +ply_pixel_buffer_t *ply_renderer_get_buffer_for_head (ply_renderer_t *renderer, + ply_renderer_head_t *head); + +void ply_renderer_flush_head (ply_renderer_t *renderer, + ply_renderer_head_t *head); + +ply_renderer_input_source_t *ply_renderer_get_input_source (ply_renderer_t *renderer); +bool ply_renderer_open_input_source (ply_renderer_t *renderer, + ply_renderer_input_source_t *input_source); +void ply_renderer_set_handler_for_input_source (ply_renderer_t *renderer, + ply_renderer_input_source_t *input_source, + ply_renderer_input_source_handler_t handler, + void *user_data); + +void ply_renderer_close_input_source (ply_renderer_t *renderer, + ply_renderer_input_source_t *input_source); +#endif + +#endif /* PLY_RENDERER_H */ +/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index b4fd30b9..12531fbd 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS = controls splash +SUBDIRS = controls splash renderers MAINTAINERCLEANFILES = Makefile.in From 6479cc162c7ff0fe82c182497cd0cc5e8cd23890 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 21 Aug 2009 19:21:53 -0400 Subject: [PATCH 10/43] [libplybootsplash] Add text-display class This is the text output portion of the window class. With this commit and a subsequent commit to split out the graphical output portion, we should be able to drop the window class. As mentioned earlier, this will give us the flexibility we need for multi-head rendering. --- src/libplybootsplash/Makefile.am | 2 + src/libplybootsplash/ply-text-display.c | 343 ++++++++++++++++++++++++ src/libplybootsplash/ply-text-display.h | 91 +++++++ 3 files changed, 436 insertions(+) create mode 100644 src/libplybootsplash/ply-text-display.c create mode 100644 src/libplybootsplash/ply-text-display.h diff --git a/src/libplybootsplash/Makefile.am b/src/libplybootsplash/Makefile.am index 1172cf1d..25c48539 100644 --- a/src/libplybootsplash/Makefile.am +++ b/src/libplybootsplash/Makefile.am @@ -22,6 +22,7 @@ libplybootsplash_HEADERS = \ ply-renderer.h \ ply-renderer-plugin.h \ ply-terminal.h \ + ply-text-display.h \ ply-text-progress-bar.h \ ply-throbber.h \ ply-window.h @@ -47,6 +48,7 @@ libplybootsplash_la_SOURCES = \ ply-throbber.c \ ply-animation.c \ ply-progress-animation.c \ + ply-text-display.c \ ply-text-progress-bar.c \ ply-terminal.c \ ply-pixel-buffer.c \ diff --git a/src/libplybootsplash/ply-text-display.c b/src/libplybootsplash/ply-text-display.c new file mode 100644 index 00000000..5639f241 --- /dev/null +++ b/src/libplybootsplash/ply-text-display.c @@ -0,0 +1,343 @@ +/* ply-text-display.c - APIs for displaying text + * + * 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 + */ +#include "config.h" +#include "ply-text-display.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ply-buffer.h" +#include "ply-console.h" +#include "ply-event-loop.h" +#include "ply-list.h" +#include "ply-logger.h" +#include "ply-terminal.h" +#include "ply-utils.h" + +#ifndef CLEAR_SCREEN_SEQUENCE +#define CLEAR_SCREEN_SEQUENCE "\033[2J" +#endif + +#ifndef CLEAR_LINE_SEQUENCE +#define CLEAR_LINE_SEQUENCE "\033[2K\r\n" +#endif + +#ifndef BACKSPACE +#define BACKSPACE "\b\033[0K" +#endif + +#ifndef MOVE_CURSOR_SEQUENCE +#define MOVE_CURSOR_SEQUENCE "\033[%d;%df" +#endif + +#ifndef HIDE_CURSOR_SEQUENCE +#define HIDE_CURSOR_SEQUENCE "\033[?25l" +#endif + +#ifndef SHOW_CURSOR_SEQUENCE +#define SHOW_CURSOR_SEQUENCE "\033[?25h" +#endif + +#ifndef COLOR_SEQUENCE_FORMAT +#define COLOR_SEQUENCE_FORMAT "\033[%dm" +#endif + +#ifndef PAUSE_SEQUENCE +#define PAUSE_SEQUENCE "\023" +#endif + +#ifndef UNPAUSE_SEQUENCE +#define UNPAUSE_SEQUENCE "\021" +#endif + +#ifndef FOREGROUND_COLOR_BASE +#define FOREGROUND_COLOR_BASE 30 +#endif + +#ifndef BACKGROUND_COLOR_BASE +#define BACKGROUND_COLOR_BASE 40 +#endif + +#ifndef TEXT_PALETTE_SIZE +#define TEXT_PALETTE_SIZE 48 +#endif + +struct _ply_text_display +{ + ply_event_loop_t *loop; + + ply_terminal_t *terminal; + ply_console_t *console; + + ply_terminal_color_t foreground_color; + ply_terminal_color_t background_color; + + ply_text_display_draw_handler_t draw_handler; + void *draw_handler_user_data; +}; + +ply_text_display_t * +ply_text_display_new (ply_terminal_t *terminal, + ply_console_t *console) +{ + ply_text_display_t *display; + + display = calloc (1, sizeof (ply_text_display_t)); + + display->loop = NULL; + display->terminal = terminal; + display->console = console; + + return display; +} + +int +ply_text_display_get_number_of_columns (ply_text_display_t *display) +{ + return ply_terminal_get_number_of_columns (display->terminal); +} + +int +ply_text_display_get_number_of_rows (ply_text_display_t *display) +{ + return ply_terminal_get_number_of_rows (display->terminal); +} + +void +ply_text_display_set_cursor_position (ply_text_display_t *display, + int column, + int row) +{ + int number_of_columns; + int number_of_rows; + + number_of_columns = ply_text_display_get_number_of_columns (display); + number_of_rows = ply_text_display_get_number_of_rows (display); + + column = CLAMP (column, 0, number_of_columns - 1); + row = CLAMP (row, 0, number_of_rows - 1); + + ply_terminal_write (display->terminal, + MOVE_CURSOR_SEQUENCE, + row, column); +} + +void +ply_text_display_clear_screen (ply_text_display_t *display) +{ + if (ply_is_tracing ()) + return; + + ply_terminal_write (display->terminal, + CLEAR_SCREEN_SEQUENCE); + + ply_text_display_set_cursor_position (display, 0, 0); +} + +void +ply_text_display_clear_line (ply_text_display_t *display) +{ + + ply_terminal_write (display->terminal, + CLEAR_LINE_SEQUENCE); +} + +void +ply_text_display_remove_character (ply_text_display_t *display) +{ + ply_terminal_write (display->terminal, + BACKSPACE); +} + +void +ply_text_display_set_background_color (ply_text_display_t *display, + ply_terminal_color_t color) +{ + + ply_terminal_write (display->terminal, + COLOR_SEQUENCE_FORMAT, + BACKGROUND_COLOR_BASE + color); + + display->background_color = color; +} + +void +ply_text_display_set_foreground_color (ply_text_display_t *display, + ply_terminal_color_t color) +{ + ply_terminal_write (display->terminal, + COLOR_SEQUENCE_FORMAT, + FOREGROUND_COLOR_BASE + color); + + display->foreground_color = color; +} + +ply_terminal_color_t +ply_text_display_get_background_color (ply_text_display_t *display) +{ + return display->background_color; +} + +ply_terminal_color_t +ply_text_display_get_foreground_color (ply_text_display_t *display) +{ + return display->foreground_color; +} + +void +ply_text_display_draw_area (ply_text_display_t *display, + int x, + int y, + int width, + int height) +{ + if (display->draw_handler != NULL) + display->draw_handler (display->draw_handler_user_data, + display->terminal, + x, y, width, height); +} + +void +ply_text_display_hide_cursor (ply_text_display_t *display) +{ + ply_terminal_write (display->terminal, + HIDE_CURSOR_SEQUENCE); +} + +void +ply_text_display_write (ply_text_display_t *display, + const char *format, + ...) +{ + int fd; + + va_list args; + char *string; + + assert (display != NULL); + assert (format != NULL); + + fd = ply_terminal_get_fd (display->terminal); + + string = NULL; + va_start (args, format); + vasprintf (&string, format, args); + va_end (args); + + if (ply_terminal_get_vt_number (display->terminal) > 0) + ply_console_set_mode (display->console, PLY_CONSOLE_MODE_TEXT); + write (fd, string, strlen (string)); + free (string); +} + +void +ply_text_display_show_cursor (ply_text_display_t *display) +{ + ply_terminal_write (display->terminal, + SHOW_CURSOR_SEQUENCE); +} + +bool +ply_text_display_supports_color (ply_text_display_t *display) +{ + return ply_terminal_supports_color (display->terminal); +} + +static void +ply_text_display_detach_from_event_loop (ply_text_display_t *display) +{ + assert (display != NULL); + display->loop = NULL; +} + +void +ply_text_display_free (ply_text_display_t *display) +{ + if (display == NULL) + return; + + if (display->loop != NULL) + ply_event_loop_stop_watching_for_exit (display->loop, + (ply_event_loop_exit_handler_t) + ply_text_display_detach_from_event_loop, + display); + + free (display); +} + +void +ply_text_display_set_draw_handler (ply_text_display_t *display, + ply_text_display_draw_handler_t draw_handler, + void *user_data) +{ + assert (display != NULL); + + display->draw_handler = draw_handler; + display->draw_handler_user_data = user_data; +} + +void +ply_text_display_pause_updates (ply_text_display_t *display) +{ + ply_terminal_write (display->terminal, + PAUSE_SEQUENCE); +} + +void +ply_text_display_unpause_updates (ply_text_display_t *display) +{ + ply_terminal_write (display->terminal, + UNPAUSE_SEQUENCE); +} + +void +ply_text_display_attach_to_event_loop (ply_text_display_t *display, + ply_event_loop_t *loop) +{ + assert (display != NULL); + assert (loop != NULL); + assert (display->loop == NULL); + + display->loop = loop; + + ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) + ply_text_display_detach_from_event_loop, + display); +} + +ply_terminal_t * +ply_text_display_get_terminal (ply_text_display_t *display) +{ + return display->terminal; +} + +/* 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/libplybootsplash/ply-text-display.h b/src/libplybootsplash/ply-text-display.h new file mode 100644 index 00000000..8c6870ad --- /dev/null +++ b/src/libplybootsplash/ply-text-display.h @@ -0,0 +1,91 @@ +/* ply-text-display.h - APIs for displaying text + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode + */ +#ifndef PLY_TEXT_DISPLAY_H +#define PLY_TEXT_DISPLAY_H + +#include +#include +#include + +#include "ply-buffer.h" +#include "ply-console.h" +#include "ply-event-loop.h" +#include "ply-terminal.h" + +typedef struct _ply_text_display ply_text_display_t; + +typedef void (* ply_text_display_draw_handler_t) (void *user_data, + ply_terminal_t *terminal, + int column, + int row, + int number_of_columns, + int number_of_rows); + +#ifndef PLY_HIDE_FUNCTION_DECLARATIONS +ply_text_display_t *ply_text_display_new (ply_terminal_t *terminal, + ply_console_t *console); + +void ply_text_display_free (ply_text_display_t *display); + +void ply_text_display_attach_to_event_loop (ply_text_display_t *display, + ply_event_loop_t *loop); + +ply_terminal_t *ply_text_display_get_terminal (ply_text_display_t *display); + +int ply_text_display_get_number_of_rows (ply_text_display_t *display); +int ply_text_display_get_number_of_columns (ply_text_display_t *display); +void ply_text_display_set_cursor_position (ply_text_display_t *display, + int column, + int row); +__attribute__((__format__ (__printf__, 2, 3))) +void ply_text_display_write (ply_text_display_t *display, + const char *format, + ...); +void ply_text_display_hide_cursor (ply_text_display_t *display); +void ply_text_display_show_cursor (ply_text_display_t *display); +void ply_text_display_clear_screen (ply_text_display_t *display); +void ply_text_display_clear_line (ply_text_display_t *display); +void ply_text_display_remove_character (ply_text_display_t *display); +bool ply_text_display_supports_color (ply_text_display_t *display); +void ply_text_display_set_background_color (ply_text_display_t *display, + ply_terminal_color_t color); +void ply_text_display_set_foreground_color (ply_text_display_t *display, + ply_terminal_color_t color); +ply_terminal_color_t ply_text_display_get_background_color (ply_text_display_t *display); +ply_terminal_color_t ply_text_display_get_foreground_color (ply_text_display_t *display); + +void ply_text_display_draw_area (ply_text_display_t *display, + int column, + int row, + int number_of_columns, + int number_of_rows); + +void ply_text_display_set_draw_handler (ply_text_display_t *display, + ply_text_display_draw_handler_t draw_handler, + void *user_data); +void ply_text_display_pause_updates (ply_text_display_t *display); +void ply_text_display_unpause_updates (ply_text_display_t *display); + +#endif + +#endif /* PLY_TEXT_DISPLAY_H */ +/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ From 91abc08d3b8253ca882e485db106910d56bf9b1a Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 21 Aug 2009 19:21:53 -0400 Subject: [PATCH 11/43] [libplybootsplash] Add pixel-display class This is the graphical output portion of the window class. This commit and the previous few commits lay the foundation needed for dropping the window class and getting multi-head rendering support. --- src/libplybootsplash/Makefile.am | 2 + src/libplybootsplash/ply-pixel-display.c | 175 +++++++++++++++++++++++ src/libplybootsplash/ply-pixel-display.h | 68 +++++++++ 3 files changed, 245 insertions(+) create mode 100644 src/libplybootsplash/ply-pixel-display.c create mode 100644 src/libplybootsplash/ply-pixel-display.h diff --git a/src/libplybootsplash/Makefile.am b/src/libplybootsplash/Makefile.am index 25c48539..19479e21 100644 --- a/src/libplybootsplash/Makefile.am +++ b/src/libplybootsplash/Makefile.am @@ -17,6 +17,7 @@ libplybootsplash_HEADERS = \ ply-label.h \ ply-label-plugin.h \ ply-pixel-buffer.h \ + ply-pixel-display.h \ ply-progress-animation.h \ ply-progress-bar.h \ ply-renderer.h \ @@ -47,6 +48,7 @@ libplybootsplash_la_SOURCES = \ ply-progress-bar.c \ ply-throbber.c \ ply-animation.c \ + ply-pixel-display.c \ ply-progress-animation.c \ ply-text-display.c \ ply-text-progress-bar.c \ diff --git a/src/libplybootsplash/ply-pixel-display.c b/src/libplybootsplash/ply-pixel-display.c new file mode 100644 index 00000000..37151203 --- /dev/null +++ b/src/libplybootsplash/ply-pixel-display.c @@ -0,0 +1,175 @@ +/* ply-pixel-display.c - APIs for putting up a pixel + * + * 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 + */ +#include "config.h" +#include "ply-pixel-display.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ply-event-loop.h" +#include "ply-list.h" +#include "ply-logger.h" +#include "ply-pixel-buffer.h" +#include "ply-renderer.h" +#include "ply-utils.h" + +struct _ply_pixel_display +{ + ply_event_loop_t *loop; + + ply_renderer_t *renderer; + ply_renderer_head_t *head; + + unsigned long width; + unsigned long height; + + ply_pixel_display_draw_handler_t draw_handler; + void *draw_handler_user_data; + + int pause_count; + +}; + +ply_pixel_display_t * +ply_pixel_display_new (ply_renderer_t *renderer, + ply_renderer_head_t *head) +{ + ply_pixel_display_t *display; + ply_pixel_buffer_t *pixel_buffer; + ply_rectangle_t size; + + display = calloc (1, sizeof (ply_pixel_display_t)); + + display->loop = ply_event_loop_get_default (); + display->renderer = renderer; + display->head = head; + + pixel_buffer = ply_renderer_get_buffer_for_head (renderer, head); + ply_pixel_buffer_get_size (pixel_buffer, &size); + + display->width = size.width; + display->height = size.height; + + return display; +} + +unsigned long +ply_pixel_display_get_width (ply_pixel_display_t *display) +{ + return display->width; +} + +unsigned long +ply_pixel_display_get_height (ply_pixel_display_t *display) +{ + return display->height; +} + +static void +ply_pixel_display_flush (ply_pixel_display_t *display) +{ + if (display->pause_count > 0) + return; + + ply_renderer_flush_head (display->renderer, display->head); +} + +void +ply_pixel_display_pause_updates (ply_pixel_display_t *display) +{ + assert (display != NULL); + + display->pause_count++; +} + +void +ply_pixel_display_unpause_updates (ply_pixel_display_t *display) +{ + assert (display != NULL); + + display->pause_count--; + + ply_pixel_display_flush (display); +} + +void +ply_pixel_display_draw_area (ply_pixel_display_t *display, + int x, + int y, + int width, + int height) +{ + + ply_pixel_buffer_t *pixel_buffer; + + pixel_buffer = ply_renderer_get_buffer_for_head (display->renderer, + display->head); + + if (display->draw_handler != NULL) + { + ply_rectangle_t clip_area; + + clip_area.x = x; + clip_area.y = y; + clip_area.width = width; + clip_area.height = height; + ply_pixel_buffer_push_clip_area (pixel_buffer, &clip_area); + display->draw_handler (display->draw_handler_user_data, + pixel_buffer, + x, y, width, height, display); + ply_pixel_buffer_pop_clip_area (pixel_buffer); + } + + ply_pixel_display_flush (display); +} + +void +ply_pixel_display_free (ply_pixel_display_t *display) +{ + if (display == NULL) + return; + + free (display); +} + +void +ply_pixel_display_set_draw_handler (ply_pixel_display_t *display, + ply_pixel_display_draw_handler_t draw_handler, + void *user_data) +{ + assert (display != NULL); + + display->draw_handler = draw_handler; + display->draw_handler_user_data = user_data; +} + +/* 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/libplybootsplash/ply-pixel-display.h b/src/libplybootsplash/ply-pixel-display.h new file mode 100644 index 00000000..98a6b3c8 --- /dev/null +++ b/src/libplybootsplash/ply-pixel-display.h @@ -0,0 +1,68 @@ +/* ply-pixel-display.h - APIs for displaying pixels + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode + */ +#ifndef PLY_PIXEL_DISPLAY_H +#define PLY_PIXEL_DISPLAY_H + +#include +#include +#include + +#include "ply-event-loop.h" +#include "ply-pixel-buffer.h" +#include "ply-renderer.h" + +typedef struct _ply_pixel_display ply_pixel_display_t; + +typedef void (* ply_pixel_display_draw_handler_t) (void *user_data, + ply_pixel_buffer_t *pixel_buffer, + int x, + int y, + int width, + int height, + ply_pixel_display_t *pixel_display); + +#ifndef PLY_HIDE_FUNCTION_DECLARATIONS +ply_pixel_display_t *ply_pixel_display_new (ply_renderer_t *renderer, + ply_renderer_head_t *head); + +void ply_pixel_display_free (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); + +void ply_pixel_display_set_draw_handler (ply_pixel_display_t *display, + ply_pixel_display_draw_handler_t draw_handler, + void *user_data); + +void ply_pixel_display_draw_area (ply_pixel_display_t *display, + int x, + int y, + int width, + int height); + +void ply_pixel_display_pause_updates (ply_pixel_display_t *display); +void ply_pixel_display_unpause_updates (ply_pixel_display_t *display); + +#endif + +#endif /* PLY_PIXEL_DISPLAY_H */ +/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ From d47959e042f31b9f362b198399c7a7ed5e4a1dab Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 21 Aug 2009 10:13:22 -0400 Subject: [PATCH 12/43] [renderer] Add start of frame-buffer plugin Much of this code comes directly from ply-frame-buffer in libply, but shoehorned to fit into the renderer plugin interface. One improvement over the old code is it tracks VT changes, and stops drawing when the wrong VT is active. --- configure.ac | 2 + scripts/plymouth-populate-initrd.in | 2 + src/plugins/renderers/Makefile.am | 2 + .../renderers/frame-buffer/Makefile.am | 20 + src/plugins/renderers/frame-buffer/plugin.c | 667 ++++++++++++++++++ 5 files changed, 693 insertions(+) create mode 100644 src/plugins/renderers/Makefile.am create mode 100644 src/plugins/renderers/frame-buffer/Makefile.am create mode 100644 src/plugins/renderers/frame-buffer/plugin.c diff --git a/configure.ac b/configure.ac index af507ffd..df076e2c 100644 --- a/configure.ac +++ b/configure.ac @@ -209,6 +209,8 @@ AC_OUTPUT([Makefile src/libplybootsplash/Makefile src/plymouth-1.pc src/plugins/Makefile + src/plugins/renderers/Makefile + src/plugins/renderers/frame-buffer/Makefile src/plugins/splash/Makefile src/plugins/splash/throbgress/Makefile src/plugins/splash/fade-throbber/Makefile diff --git a/scripts/plymouth-populate-initrd.in b/scripts/plymouth-populate-initrd.in index dcf2b427..42b119c3 100755 --- a/scripts/plymouth-populate-initrd.in +++ b/scripts/plymouth-populate-initrd.in @@ -93,6 +93,8 @@ fi inst ${PLYMOUTH_PLUGIN_PATH}/${PLYMOUTH_MODULE_NAME}.so $INITRDDIR +inst ${PLYMOUTH_PLUGIN_PATH}/renderers/frame-buffer.so $INITRDDIR + if [ -d ${DATADIR}/plymouth/themes/${PLYMOUTH_THEME_NAME} ]; then for x in ${DATADIR}/plymouth/themes/${PLYMOUTH_THEME_NAME}/* ; do [ ! -f "$x" ] && break diff --git a/src/plugins/renderers/Makefile.am b/src/plugins/renderers/Makefile.am new file mode 100644 index 00000000..2a9e8a0c --- /dev/null +++ b/src/plugins/renderers/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = frame-buffer +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/plugins/renderers/frame-buffer/Makefile.am b/src/plugins/renderers/frame-buffer/Makefile.am new file mode 100644 index 00000000..6811e01d --- /dev/null +++ b/src/plugins/renderers/frame-buffer/Makefile.am @@ -0,0 +1,20 @@ +INCLUDES = -I$(top_srcdir) \ + -I$(srcdir)/../../../libply \ + -I$(srcdir)/../../../libplybootsplash \ + -I$(srcdir)/../../.. \ + -I$(srcdir)/../.. \ + -I$(srcdir)/.. \ + -I$(srcdir) + +plugindir = $(libdir)/plymouth/renderers +plugin_LTLIBRARIES = frame-buffer.la + +frame_buffer_la_CFLAGS = $(PLYMOUTH_CFLAGS) + +frame_buffer_la_LDFLAGS = -module -avoid-version -export-dynamic +frame_buffer_la_LIBADD = $(PLYMOUTH_LIBS) \ + ../../../libply/libply.la \ + ../../../libplybootsplash/libplybootsplash.la +frame_buffer_la_SOURCES = $(srcdir)/plugin.c + +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/plugins/renderers/frame-buffer/plugin.c b/src/plugins/renderers/frame-buffer/plugin.c new file mode 100644 index 00000000..85d9e7dd --- /dev/null +++ b/src/plugins/renderers/frame-buffer/plugin.c @@ -0,0 +1,667 @@ +/* plugin.c - frame-backend renderer plugin + * + * Copyright (C) 2006-2009 Red Hat, Inc. + * 2008 Charlie Brej + * + * 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: Charlie Brej + * Kristian Høgsberg + * Peter Jones + * Ray Strode + */ +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ply-buffer.h" +#include "ply-event-loop.h" +#include "ply-list.h" +#include "ply-logger.h" +#include "ply-rectangle.h" +#include "ply-region.h" +#include "ply-terminal.h" + +#include "ply-renderer.h" +#include "ply-renderer-plugin.h" + +#ifndef PLY_FRAME_BUFFER_DEFAULT_FB_DEVICE_NAME +#define PLY_FRAME_BUFFER_DEFAULT_FB_DEVICE_NAME "/dev/fb" +#endif + +struct _ply_renderer_head +{ + ply_pixel_buffer_t *pixel_buffer; + ply_rectangle_t area; + char *map_address; + size_t size; + +}; + +struct _ply_renderer_input_source +{ + ply_fd_watch_t *terminal_input_watch; + + ply_buffer_t *key_buffer; + + ply_renderer_input_source_handler_t handler; + void *user_data; +}; + +struct _ply_renderer_backend +{ + ply_event_loop_t *loop; + ply_console_t *console; + ply_terminal_t *terminal; + + char *device_name; + int device_fd; + + ply_renderer_input_source_t input_source; + ply_renderer_head_t head; + ply_list_t *heads; + + uint32_t red_bit_position; + uint32_t green_bit_position; + uint32_t blue_bit_position; + uint32_t alpha_bit_position; + + uint32_t bits_for_red; + uint32_t bits_for_green; + uint32_t bits_for_blue; + uint32_t bits_for_alpha; + + int32_t dither_red; + int32_t dither_green; + int32_t dither_blue; + + unsigned int bytes_per_pixel; + unsigned int row_stride; + + void (* flush_area) (ply_renderer_backend_t *backend, + ply_renderer_head_t *head, + ply_rectangle_t *area_to_flush); +}; + +ply_renderer_plugin_interface_t *ply_renderer_backend_get_interface (void); +static void ply_renderer_head_redraw (ply_renderer_backend_t *backend, + ply_renderer_head_t *head); + +static inline uint_fast32_t +argb32_pixel_value_to_device_pixel_value (ply_renderer_backend_t *backend, + uint32_t pixel_value) +{ + uint8_t r, g, b, a; + int orig_r, orig_g, orig_b, orig_a; + uint8_t new_r, new_g, new_b; + int i; + + orig_a = pixel_value >> 24; + a = orig_a >> (8 - backend->bits_for_alpha); + + orig_r = ((pixel_value >> 16) & 0xff) - backend->dither_red; + r = CLAMP (orig_r, 0, 255) >> (8 - backend->bits_for_red); + + orig_g = ((pixel_value >> 8) & 0xff) - backend->dither_green; + g = CLAMP (orig_g, 0, 255) >> (8 - backend->bits_for_green); + + orig_b = (pixel_value & 0xff) - backend->dither_blue; + b = CLAMP (orig_b, 0, 255) >> (8 - backend->bits_for_blue); + + new_r = r << (8 - backend->bits_for_red); + new_g = g << (8 - backend->bits_for_green); + new_b = b << (8 - backend->bits_for_blue); + + for (i = backend->bits_for_red; i < 8; i <<= 1) + new_r |= new_r >> i; + + for (i = backend->bits_for_green; i < 8; i <<= 1) + new_g |= new_g >> i; + + for (i = backend->bits_for_blue; i < 8; i <<= 1) + new_b |= new_b >> i; + + backend->dither_red = new_r - orig_r; + backend->dither_green = new_g - orig_g; + backend->dither_blue = new_b - orig_b; + + return ((a << backend->alpha_bit_position) + | (r << backend->red_bit_position) + | (g << backend->green_bit_position) + | (b << backend->blue_bit_position)); +} + +static void +flush_area_to_any_device (ply_renderer_backend_t *backend, + ply_renderer_head_t *head, + ply_rectangle_t *area_to_flush) +{ + unsigned long row, column; + uint32_t *shadow_buffer; + char *row_backend; + size_t bytes_per_row; + unsigned long x1, y1, x2, y2; + + x1 = area_to_flush->x; + y1 = area_to_flush->y; + x2 = x1 + area_to_flush->width; + y2 = y1 + area_to_flush->height; + + bytes_per_row = area_to_flush->width * backend->bytes_per_pixel; + row_backend = malloc (backend->row_stride); + shadow_buffer = ply_pixel_buffer_get_argb32_data (backend->head.pixel_buffer); + for (row = y1; row < y2; row++) + { + unsigned long offset; + + for (column = x1; column < x2; column++) + { + uint32_t pixel_value; + uint_fast32_t device_pixel_value; + + pixel_value = shadow_buffer[row * head->area.width + column]; + + device_pixel_value = argb32_pixel_value_to_device_pixel_value (backend, + pixel_value); + + memcpy (row_backend + column * backend->bytes_per_pixel, + &device_pixel_value, backend->bytes_per_pixel); + } + + offset = row * backend->row_stride + x1 * backend->bytes_per_pixel; + memcpy (head->map_address + offset, row_backend + x1 * backend->bytes_per_pixel, + area_to_flush->width * backend->bytes_per_pixel); + } + free (row_backend); +} + +static void +flush_area_to_xrgb32_device (ply_renderer_backend_t *backend, + ply_renderer_head_t *head, + ply_rectangle_t *area_to_flush) +{ + unsigned long x1, y1, x2, y2, y; + uint32_t *shadow_buffer; + char *dst, *src; + + x1 = area_to_flush->x; + y1 = area_to_flush->y; + x2 = x1 + area_to_flush->width; + y2 = y1 + area_to_flush->height; + + shadow_buffer = ply_pixel_buffer_get_argb32_data (backend->head.pixel_buffer); + + dst = &head->map_address[y1 * backend->row_stride + x1 * backend->bytes_per_pixel]; + src = (char *) &shadow_buffer[y1 * head->area.width + x1]; + + if (area_to_flush->width == backend->row_stride) + { + memcpy (dst, src, area_to_flush->width * area_to_flush->height * 4); + return; + } + + for (y = y1; y < y2; y++) + { + memcpy (dst, src, area_to_flush->width * 4); + dst += backend->row_stride; + src += head->area.width * 4; + } +} + +static ply_renderer_backend_t * +create_backend (const char *device_name, + ply_terminal_t *terminal, + ply_console_t *console) +{ + ply_renderer_backend_t *backend; + + backend = calloc (1, sizeof (ply_renderer_backend_t)); + + if (device_name != NULL) + backend->device_name = strdup (device_name); + else if (getenv ("FRAMEBUFFER") != NULL) + backend->device_name = strdup (getenv ("FRAMEBUFFER")); + else + backend->device_name = + strdup (PLY_FRAME_BUFFER_DEFAULT_FB_DEVICE_NAME); + + backend->loop = ply_event_loop_get_default (); + backend->heads = ply_list_new (); + backend->input_source.key_buffer = ply_buffer_new (); + backend->console = console; + backend->terminal = terminal; + + return backend; +} + +static void +initialize_head (ply_renderer_backend_t *backend, + ply_renderer_head_t *head) +{ + head->pixel_buffer = ply_pixel_buffer_new (head->area.width, + head->area.height); + ply_pixel_buffer_fill_with_color (backend->head.pixel_buffer, NULL, + 0.0, 0.0, 0.0, 1.0); + ply_list_append_data (backend->heads, head); +} + +static void +uninitialize_head (ply_renderer_backend_t *backend, + ply_renderer_head_t *head) +{ + if (head->pixel_buffer != NULL) + { + ply_pixel_buffer_free (head->pixel_buffer); + head->pixel_buffer = NULL; + + ply_list_remove_data (backend->heads, head); + } +} + +static void +destroy_backend (ply_renderer_backend_t *backend) +{ + + free (backend->device_name); + uninitialize_head (backend, &backend->head); + + ply_list_free (backend->heads); + + free (backend); +} + +static void +on_active_vt_changed (ply_renderer_backend_t *backend) +{ + if (ply_console_get_active_vt (backend->console) != + ply_terminal_get_vt_number (backend->terminal)) + return; + + if (backend->head.map_address != MAP_FAILED) + ply_renderer_head_redraw (backend, &backend->head); +} + +static bool +open_device (ply_renderer_backend_t *backend) +{ + backend->device_fd = open (backend->device_name, O_RDWR); + + if (backend->device_fd < 0) + { + ply_trace ("could not open '%s': %m", backend->device_name); + return false; + } + + ply_console_watch_for_active_vt_change (backend->console, + (ply_console_active_vt_changed_handler_t) + on_active_vt_changed, + backend); + + return true; +} + +static void +close_device (ply_renderer_backend_t *backend) +{ + + ply_console_stop_watching_for_active_vt_change (backend->console, + (ply_console_active_vt_changed_handler_t) + on_active_vt_changed, + backend); + close (backend->device_fd); + backend->device_fd = -1; + + backend->bytes_per_pixel = 0; + backend->head.area.x = 0; + backend->head.area.y = 0; + backend->head.area.width = 0; + backend->head.area.height = 0; +} + +static const char const *get_visual_name (int visual) +{ + static const char const *visuals[] = + { + [FB_VISUAL_MONO01] = "FB_VISUAL_MONO01", + [FB_VISUAL_MONO10] = "FB_VISUAL_MONO10", + [FB_VISUAL_TRUECOLOR] = "FB_VISUAL_TRUECOLOR", + [FB_VISUAL_PSEUDOCOLOR] = "FB_VISUAL_PSEUDOCOLOR", + [FB_VISUAL_DIRECTCOLOR] = "FB_VISUAL_DIRECTCOLOR", + [FB_VISUAL_STATIC_PSEUDOCOLOR] = "FB_VISUAL_STATIC_PSEUDOCOLOR", + NULL + }; + static char unknown[] = "invalid visual: -4294967295"; + + if (visual < FB_VISUAL_MONO01 || visual > FB_VISUAL_STATIC_PSEUDOCOLOR) + { + sprintf (unknown, "invalid visual: %d", visual); + return unknown; + } + + return visuals[visual]; +} + +static bool +query_device (ply_renderer_backend_t *backend) +{ + struct fb_var_screeninfo variable_screen_info; + struct fb_fix_screeninfo fixed_screen_info; + + assert (backend != NULL); + assert (backend->device_fd >= 0); + + if (ioctl (backend->device_fd, FBIOGET_VSCREENINFO, &variable_screen_info) < 0) + return false; + + if (ioctl (backend->device_fd, FBIOGET_FSCREENINFO, &fixed_screen_info) < 0) + return false; + + /* Normally the pixel is divided into channels between the color components. + * Each channel directly maps to a color channel on the hardware. + * + * There are some odd ball modes that use an indexed palette instead. In + * those cases (pseudocolor, direct color, etc), the pixel value is just an + * index into a lookup table of the real color values. + * + * We don't support that. + */ + if (fixed_screen_info.visual != FB_VISUAL_TRUECOLOR) + { + int rc = -1; + int i; + static const int depths[] = {32, 24, 16, 0}; + + ply_trace ("Visual was %s, trying to find usable mode.\n", + get_visual_name (fixed_screen_info.visual)); + + for (i = 0; depths[i] != 0; i++) + { + variable_screen_info.bits_per_pixel = depths[i]; + variable_screen_info.activate |= FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; + + rc = ioctl (backend->device_fd, FBIOPUT_VSCREENINFO, &variable_screen_info); + if (rc >= 0) + { + if (ioctl (backend->device_fd, FBIOGET_FSCREENINFO, &fixed_screen_info) < 0) + return false; + + if (fixed_screen_info.visual == FB_VISUAL_TRUECOLOR) + break; + } + } + + if (ioctl (backend->device_fd, FBIOGET_VSCREENINFO, &variable_screen_info) < 0) + return false; + + if (ioctl (backend->device_fd, FBIOGET_FSCREENINFO, &fixed_screen_info) < 0) + return false; + } + + if (fixed_screen_info.visual != FB_VISUAL_TRUECOLOR || + variable_screen_info.bits_per_pixel < 16) + { + ply_trace ("Visual is %s; not using graphics\n", + get_visual_name (fixed_screen_info.visual)); + return false; + } + + backend->head.area.x = variable_screen_info.xoffset; + backend->head.area.y = variable_screen_info.yoffset; + backend->head.area.width = variable_screen_info.xres; + backend->head.area.height = variable_screen_info.yres; + + backend->red_bit_position = variable_screen_info.red.offset; + backend->bits_for_red = variable_screen_info.red.length; + + backend->green_bit_position = variable_screen_info.green.offset; + backend->bits_for_green = variable_screen_info.green.length; + + backend->blue_bit_position = variable_screen_info.blue.offset; + backend->bits_for_blue = variable_screen_info.blue.length; + + backend->alpha_bit_position = variable_screen_info.transp.offset; + backend->bits_for_alpha = variable_screen_info.transp.length; + + backend->bytes_per_pixel = variable_screen_info.bits_per_pixel >> 3; + backend->row_stride = fixed_screen_info.line_length; + backend->dither_red = 0; + backend->dither_green = 0; + backend->dither_blue = 0; + + backend->head.size = backend->head.area.height * backend->row_stride; + + if (backend->bytes_per_pixel == 4 && + backend->red_bit_position == 16 && backend->bits_for_red == 8 && + backend->green_bit_position == 8 && backend->bits_for_green == 8 && + backend->blue_bit_position == 0 && backend->bits_for_blue == 8) + backend->flush_area = flush_area_to_xrgb32_device; + else + backend->flush_area = flush_area_to_any_device; + + return true; + +} + +static bool +map_to_device (ply_renderer_backend_t *backend) +{ + ply_renderer_head_t *head; + + assert (backend != NULL); + assert (backend->device_fd >= 0); + + head = &backend->head; + assert (head->size > 0); + + head->map_address = mmap (NULL, head->size, PROT_WRITE, + MAP_SHARED, backend->device_fd, 0); + + if (head->map_address == MAP_FAILED) + return false; + + initialize_head (backend, head); + + return true; +} + +static void +unmap_from_device (ply_renderer_backend_t *backend) +{ + ply_renderer_head_t *head; + + head = &backend->head; + + uninitialize_head (backend, head); + + if (head->map_address != MAP_FAILED) + { + munmap (head->map_address, head->size); + head->map_address = MAP_FAILED; + } +} + +static void +flush_head (ply_renderer_backend_t *backend, + ply_renderer_head_t *head) +{ + ply_region_t *updated_region; + ply_list_t *areas_to_flush; + ply_list_node_t *node; + ply_pixel_buffer_t *pixel_buffer; + + assert (backend != NULL); + assert (&backend->head == head); + + ply_console_set_mode (backend->console, PLY_CONSOLE_MODE_GRAPHICS); + pixel_buffer = head->pixel_buffer; + updated_region = ply_pixel_buffer_get_updated_areas (pixel_buffer); + areas_to_flush = ply_region_get_rectangle_list (updated_region); + + node = ply_list_get_first_node (areas_to_flush); + while (node != NULL) + { + ply_list_node_t *next_node; + ply_rectangle_t *area_to_flush; + + area_to_flush = (ply_rectangle_t *) ply_list_node_get_data (node); + + next_node = ply_list_get_next_node (areas_to_flush, node); + + backend->flush_area (backend, head, area_to_flush); + + node = next_node; + } + + ply_region_clear (updated_region); +} + +static void +ply_renderer_head_redraw (ply_renderer_backend_t *backend, + ply_renderer_head_t *head) +{ + ply_region_t *region; + + region = ply_pixel_buffer_get_updated_areas (head->pixel_buffer); + + ply_region_add_rectangle (region, &head->area); + + flush_head (backend, head); +} + +static ply_list_t * +get_heads (ply_renderer_backend_t *backend) +{ + return backend->heads; +} + +static ply_pixel_buffer_t * +get_buffer_for_head (ply_renderer_backend_t *backend, + ply_renderer_head_t *head) +{ + + if (head != &backend->head) + return NULL; + + return backend->head.pixel_buffer; +} + +static bool +has_input_source (ply_renderer_backend_t *backend, + ply_renderer_input_source_t *input_source) +{ + return input_source == &backend->input_source; +} + +static ply_renderer_input_source_t * +get_input_source (ply_renderer_backend_t *backend) +{ + return &backend->input_source; +} + +static void +on_key_event (ply_renderer_input_source_t *input_source, + int terminal_fd) +{ + ply_buffer_append_from_fd (input_source->key_buffer, + terminal_fd); + + if (input_source->handler != NULL) + input_source->handler (input_source->user_data, input_source->key_buffer, input_source); + +} + +static bool +open_input_source (ply_renderer_backend_t *backend, + ply_renderer_input_source_t *input_source) +{ + int terminal_fd; + + assert (backend != NULL); + assert (has_input_source (backend, input_source)); + + terminal_fd = ply_terminal_get_fd (backend->terminal); + + input_source->terminal_input_watch = ply_event_loop_watch_fd (backend->loop, terminal_fd, PLY_EVENT_LOOP_FD_STATUS_HAS_DATA, + (ply_event_handler_t) on_key_event, + NULL, input_source); + return true; +} + +static void +set_handler_for_input_source (ply_renderer_backend_t *backend, + ply_renderer_input_source_t *input_source, + ply_renderer_input_source_handler_t handler, + void *user_data) +{ + assert (backend != NULL); + assert (has_input_source (backend, input_source)); + + input_source->handler = handler; + input_source->user_data = user_data; +} + +static void +close_input_source (ply_renderer_backend_t *backend, + ply_renderer_input_source_t *input_source) +{ + assert (backend != NULL); + assert (has_input_source (backend, input_source)); + + ply_event_loop_stop_watching_fd (backend->loop, input_source->terminal_input_watch); + input_source->terminal_input_watch = NULL; +} + +ply_renderer_plugin_interface_t * +ply_renderer_backend_get_interface (void) +{ + static ply_renderer_plugin_interface_t plugin_interface = + { + .create_backend = create_backend, + .destroy_backend = destroy_backend, + .open_device = open_device, + .close_device = close_device, + .query_device = query_device, + .map_to_device = map_to_device, + .unmap_from_device = unmap_from_device, + .flush_head = flush_head, + .get_heads = get_heads, + .get_buffer_for_head = get_buffer_for_head, + .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 + }; + + return &plugin_interface; +} +/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ From 6c6ecf5e2d72370b71d2c59abe65ff3bb9a2a40a Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 16:23:39 -0400 Subject: [PATCH 13/43] [boot-splash] Update to use new multihead interface The boot splash plugin now takes in a keyboard, text displays, pixel displays, and the console. I passes those along to the plugins, and listens for key strokes to handle CTRL-L refresh and other keybindings. So now it's assuming some of the role of ply-window. --- src/libplybootsplash/ply-boot-splash-plugin.h | 21 +- src/libplybootsplash/ply-boot-splash.c | 247 ++++++++++++++++-- src/libplybootsplash/ply-boot-splash.h | 24 +- src/tests/ply-boot-splash-test.am | 16 +- 4 files changed, 274 insertions(+), 34 deletions(-) diff --git a/src/libplybootsplash/ply-boot-splash-plugin.h b/src/libplybootsplash/ply-boot-splash-plugin.h index 4671d0c2..d22eb437 100644 --- a/src/libplybootsplash/ply-boot-splash-plugin.h +++ b/src/libplybootsplash/ply-boot-splash-plugin.h @@ -28,9 +28,11 @@ #include "ply-buffer.h" #include "ply-event-loop.h" +#include "ply-keyboard.h" +#include "ply-pixel-display.h" +#include "ply-text-display.h" #include "ply-trigger.h" #include "ply-key-file.h" -#include "ply-window.h" typedef enum { @@ -47,11 +49,18 @@ typedef struct ply_boot_splash_plugin_t * (* create_plugin) (ply_key_file_t *key_file); void (* destroy_plugin) (ply_boot_splash_plugin_t *plugin); - void (* add_window) (ply_boot_splash_plugin_t *plugin, - ply_window_t *window); - - void (* remove_window) (ply_boot_splash_plugin_t *plugin, - ply_window_t *window); + void (* set_keyboard) (ply_boot_splash_plugin_t *plugin, + ply_keyboard_t *keyboard); + void (* unset_keyboard) (ply_boot_splash_plugin_t *plugin, + ply_keyboard_t *keyboard); + void (* add_pixel_display) (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display); + void (* remove_pixel_display) (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display); + void (* add_text_display) (ply_boot_splash_plugin_t *plugin, + ply_text_display_t *display); + void (* remove_text_display) (ply_boot_splash_plugin_t *plugin, + ply_text_display_t *display); bool (* show_splash_screen) (ply_boot_splash_plugin_t *plugin, ply_event_loop_t *loop, ply_buffer_t *boot_buffer, diff --git a/src/libplybootsplash/ply-boot-splash.c b/src/libplybootsplash/ply-boot-splash.c index 68bbaddc..72ee7f02 100644 --- a/src/libplybootsplash/ply-boot-splash.c +++ b/src/libplybootsplash/ply-boot-splash.c @@ -34,18 +34,23 @@ #include #include "ply-boot-splash-plugin.h" +#include "ply-console.h" #include "ply-event-loop.h" #include "ply-list.h" #include "ply-logger.h" #include "ply-trigger.h" #include "ply-utils.h" #include "ply-progress.h" +#include "ply-keyboard.h" #include "ply-key-file.h" #ifndef UPDATES_PER_SECOND #define UPDATES_PER_SECOND 30 #endif +#define KEY_CTRL_L ('\100' ^'L') +#define KEY_CTRL_T ('\100' ^'T') +#define KEY_CTRL_V ('\100' ^'V') struct _ply_boot_splash { @@ -53,8 +58,12 @@ struct _ply_boot_splash ply_module_handle_t *module_handle; const ply_boot_splash_plugin_interface_t *plugin_interface; ply_boot_splash_plugin_t *plugin; + ply_console_t *console; + ply_keyboard_t *keyboard; ply_buffer_t *boot_buffer; ply_trigger_t *idle_trigger; + ply_list_t *pixel_displays; + ply_list_t *text_displays; char *theme_path; char *plugin_dir; @@ -66,6 +75,7 @@ struct _ply_boot_splash uint32_t is_loaded : 1; uint32_t is_shown : 1; + uint32_t should_force_text_mode : 1; }; typedef const ply_boot_splash_plugin_interface_t * @@ -77,7 +87,8 @@ static void ply_boot_splash_detach_from_event_loop (ply_boot_splash_t *splash); ply_boot_splash_t * ply_boot_splash_new (const char *theme_path, const char *plugin_dir, - ply_buffer_t *boot_buffer) + ply_buffer_t *boot_buffer, + ply_console_t *console) { ply_boot_splash_t *splash; @@ -91,22 +102,162 @@ ply_boot_splash_new (const char *theme_path, splash->is_shown = false; splash->boot_buffer = boot_buffer; + splash->console = console; + splash->pixel_displays = ply_list_new (); + splash->text_displays = ply_list_new (); return splash; } -void -ply_boot_splash_add_window (ply_boot_splash_t *splash, - ply_window_t *window) +static void +refresh_displays (ply_boot_splash_t *splash) { - splash->plugin_interface->add_window (splash->plugin, window); + ply_list_node_t *node; + + 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_pixel_display_draw_area (display, 0, 0, width, height); + node = next_node; + } + + node = ply_list_get_first_node (splash->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 (splash->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; + } +} + +static void +on_keyboard_input (ply_boot_splash_t *splash, + const char *keyboard_input, + size_t character_size) +{ + wchar_t key; + + if ((ssize_t) mbrtowc (&key, keyboard_input, character_size, NULL) > 0) + { + switch (key) + { + case KEY_CTRL_L: + refresh_displays (splash); + return; + + case KEY_CTRL_T: + ply_trace ("toggle text mode!"); + splash->should_force_text_mode = !splash->should_force_text_mode; + ply_console_force_text_mode (splash->console, + splash->should_force_text_mode); + ply_trace ("text mode toggled!"); + return; + + case KEY_CTRL_V: + ply_trace ("toggle verbose mode!"); + ply_toggle_tracing (); + ply_trace ("verbose mode toggled!"); + return; + } + } } void -ply_boot_splash_remove_window (ply_boot_splash_t *splash, - ply_window_t *window) +ply_boot_splash_set_keyboard (ply_boot_splash_t *splash, + ply_keyboard_t *keyboard) { - splash->plugin_interface->remove_window (splash->plugin, window); + splash->keyboard = keyboard; + + ply_keyboard_add_input_handler (keyboard, + (ply_keyboard_input_handler_t) + on_keyboard_input, splash); + + if (splash->plugin_interface->set_keyboard == NULL) + return; + + splash->plugin_interface->set_keyboard (splash->plugin, keyboard); +} + +void +ply_boot_splash_unset_keyboard (ply_boot_splash_t *splash) +{ + ply_keyboard_remove_input_handler (splash->keyboard, + (ply_keyboard_input_handler_t) + on_keyboard_input); + + if (splash->plugin_interface->set_keyboard == NULL) + return; + + splash->plugin_interface->unset_keyboard (splash->plugin, splash->keyboard); +} + +void +ply_boot_splash_add_pixel_display (ply_boot_splash_t *splash, + ply_pixel_display_t *display) +{ + ply_list_append_data (splash->pixel_displays, display); + + if (splash->plugin_interface->add_pixel_display == NULL) + return; + + splash->plugin_interface->add_pixel_display (splash->plugin, display); +} + +void +ply_boot_splash_remove_pixel_display (ply_boot_splash_t *splash, + ply_pixel_display_t *display) +{ + ply_list_remove_data (splash->pixel_displays, display); + + if (splash->plugin_interface->remove_pixel_display == NULL) + return; + + splash->plugin_interface->remove_pixel_display (splash->plugin, display); +} + +void +ply_boot_splash_add_text_display (ply_boot_splash_t *splash, + ply_text_display_t *display) +{ + ply_list_append_data (splash->text_displays, display); + + if (splash->plugin_interface->add_text_display == NULL) + return; + + splash->plugin_interface->add_text_display (splash->plugin, display); +} + +void +ply_boot_splash_remove_text_display (ply_boot_splash_t *splash, + ply_text_display_t *display) +{ + ply_list_remove_data (splash->text_displays, display); + + if (splash->plugin_interface->remove_pixel_display == NULL) + return; + + splash->plugin_interface->remove_text_display (splash->plugin, display); } bool @@ -223,6 +374,8 @@ ply_boot_splash_free (ply_boot_splash_t *splash) if (splash->idle_trigger != NULL) ply_trigger_free (splash->idle_trigger); + ply_list_free (splash->pixel_displays); + ply_list_free (splash->text_displays); free (splash->theme_path); free (splash->plugin_dir); free (splash); @@ -354,6 +507,8 @@ ply_boot_splash_hide (ply_boot_splash_t *splash) splash->plugin_interface->hide_splash_screen (splash->plugin, splash->loop); + ply_console_set_mode (splash->console, PLY_CONSOLE_MODE_TEXT); + splash->is_shown = false; if (splash->loop != NULL) @@ -479,7 +634,6 @@ typedef struct test_state test_state_t; struct test_state { ply_event_loop_t *loop; ply_boot_splash_t *splash; - ply_window_t *window; ply_buffer_t *buffer; }; @@ -501,6 +655,33 @@ on_quit (test_state_t *state) ply_event_loop_exit (state->loop, 0); } +static void +add_displays_to_splash_from_renderer (test_state_t *state, + ply_renderer_t *renderer) +{ + ply_list_t *heads; + ply_list_node_t *node; + + heads = ply_renderer_get_heads (renderer); + + 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_boot_splash_add_pixel_display (state->splash, display); + + node = next_node; + } +} + int main (int argc, char **argv) @@ -509,6 +690,11 @@ main (int argc, test_state_t state; char *tty_name; const char *theme_path; + ply_text_display_t *text_display; + ply_renderer_t *renderer; + ply_console_t *console; + ply_terminal_t *terminal; + ply_keyboard_t *keyboard; exit_code = 0; @@ -524,29 +710,51 @@ main (int argc, else tty_name = strdup("tty0"); - state.window = ply_window_new (tty_name); - free(tty_name); - ply_window_attach_to_event_loop (state.window, state.loop); + console = ply_console_new (); - if (!ply_window_open (state.window)) + if (!ply_console_open (console)) { - perror ("could not open terminal"); + perror ("could not open console"); return errno; } - ply_window_attach_to_event_loop (state.window, state.loop); - ply_window_add_escape_handler (state.window, - (ply_window_escape_handler_t) on_quit, &state); + terminal = ply_terminal_new (tty_name); + + if (!ply_terminal_open (terminal)) + { + perror ("could not open tty"); + return errno; + } + + renderer = ply_renderer_new (NULL, terminal, console); + free(tty_name); + + if (!ply_renderer_open (renderer)) + { + perror ("could not open renderer /dev/fb"); + ply_renderer_free (renderer); + return errno; + } + + keyboard = ply_keyboard_new_for_renderer (renderer); + ply_keyboard_add_escape_handler (keyboard, + (ply_keyboard_escape_handler_t) on_quit, &state); state.buffer = ply_buffer_new (); - state.splash = ply_boot_splash_new (theme_path, PLYMOUTH_PLUGIN_PATH, state.buffer); + state.splash = ply_boot_splash_new (theme_path, PLYMOUTH_PLUGIN_PATH, state.buffer, console); + if (!ply_boot_splash_load (state.splash)) { perror ("could not load splash screen"); return errno; } - ply_boot_splash_add_window (state.splash, state.window); + ply_boot_splash_set_keyboard (state.splash, keyboard); + add_displays_to_splash_from_renderer (&state, renderer); + + text_display = ply_text_display_new (terminal, console); + ply_boot_splash_add_text_display (state.splash, text_display); + ply_boot_splash_attach_to_event_loop (state.splash, state.loop); if (!ply_boot_splash_show (state.splash, PLY_BOOT_SPLASH_MODE_BOOT_UP)) @@ -561,7 +769,6 @@ main (int argc, on_timeout, state.splash); exit_code = ply_event_loop_run (state.loop); - ply_window_free (state.window); ply_boot_splash_free (state.splash); ply_buffer_free (state.buffer); diff --git a/src/libplybootsplash/ply-boot-splash.h b/src/libplybootsplash/ply-boot-splash.h index 90cd5853..4cb61b75 100644 --- a/src/libplybootsplash/ply-boot-splash.h +++ b/src/libplybootsplash/ply-boot-splash.h @@ -27,9 +27,13 @@ #include #include "ply-event-loop.h" -#include "ply-window.h" #include "ply-buffer.h" +#include "ply-console.h" +#include "ply-keyboard.h" +#include "ply-pixel-display.h" +#include "ply-text-display.h" #include "ply-progress.h" + #include "ply-boot-splash-plugin.h" typedef struct _ply_boot_splash ply_boot_splash_t; @@ -39,13 +43,21 @@ typedef void (* ply_boot_splash_on_idle_handler_t) (void *user_data); #ifndef PLY_HIDE_FUNCTION_DECLARATIONS ply_boot_splash_t *ply_boot_splash_new (const char *theme_path, const char *plugin_dir, - ply_buffer_t *boot_buffer); + ply_buffer_t *boot_buffer, + ply_console_t *console); bool ply_boot_splash_load (ply_boot_splash_t *splash); void ply_boot_splash_unload (ply_boot_splash_t *splash); -void ply_boot_splash_add_window (ply_boot_splash_t *splash, - ply_window_t *window); -void ply_boot_splash_remove_window (ply_boot_splash_t *splash, - ply_window_t *window); +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 *display); +void ply_boot_splash_remove_pixel_display (ply_boot_splash_t *splash, + ply_pixel_display_t *display); +void ply_boot_splash_add_text_display (ply_boot_splash_t *splash, + ply_text_display_t *display); +void ply_boot_splash_remove_text_display (ply_boot_splash_t *splash, + ply_text_display_t *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/tests/ply-boot-splash-test.am b/src/tests/ply-boot-splash-test.am index ef79719c..3af7bd54 100644 --- a/src/tests/ply-boot-splash-test.am +++ b/src/tests/ply-boot-splash-test.am @@ -9,7 +9,19 @@ ply_boot_splash_test_LDADD = $(PLYMOUTH_LIBS) ../libply/libply.la ply_boot_splash_test_SOURCES = \ $(srcdir)/../libplybootsplash/ply-boot-splash-plugin.h \ - $(srcdir)/../libplybootsplash/ply-window.h \ - $(srcdir)/../libplybootsplash/ply-window.c \ + $(srcdir)/../libplybootsplash/ply-console.h \ + $(srcdir)/../libplybootsplash/ply-console.c \ + $(srcdir)/../libplybootsplash/ply-keyboard.h \ + $(srcdir)/../libplybootsplash/ply-keyboard.c \ + $(srcdir)/../libplybootsplash/ply-pixel-buffer.h \ + $(srcdir)/../libplybootsplash/ply-pixel-buffer.c \ + $(srcdir)/../libplybootsplash/ply-pixel-display.h \ + $(srcdir)/../libplybootsplash/ply-pixel-display.c \ + $(srcdir)/../libplybootsplash/ply-renderer.h \ + $(srcdir)/../libplybootsplash/ply-renderer.c \ + $(srcdir)/../libplybootsplash/ply-terminal.h \ + $(srcdir)/../libplybootsplash/ply-terminal.c \ + $(srcdir)/../libplybootsplash/ply-text-display.h \ + $(srcdir)/../libplybootsplash/ply-text-display.c \ $(srcdir)/../libplybootsplash/ply-boot-splash.h \ $(srcdir)/../libplybootsplash/ply-boot-splash.c From d60e817609a9d19befb025e1a38a09a8f9182887 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 15:08:59 -0400 Subject: [PATCH 14/43] [label] Use pixel display instead of window --- src/libplybootsplash/ply-label-plugin.h | 16 +- src/libplybootsplash/ply-label.c | 26 ++- src/libplybootsplash/ply-label.h | 17 +- src/plugins/controls/label/plugin.c | 211 +++++++++++++----------- 4 files changed, 160 insertions(+), 110 deletions(-) diff --git a/src/libplybootsplash/ply-label-plugin.h b/src/libplybootsplash/ply-label-plugin.h index fbb65f6f..8db46263 100644 --- a/src/libplybootsplash/ply-label-plugin.h +++ b/src/libplybootsplash/ply-label-plugin.h @@ -27,7 +27,8 @@ #include #include "ply-event-loop.h" -#include "ply-window.h" +#include "ply-pixel-buffer.h" +#include "ply-pixel-display.h" typedef struct _ply_label_plugin ply_label_plugin_t; typedef struct _ply_label_plugin_control ply_label_plugin_control_t; @@ -37,11 +38,16 @@ typedef struct ply_label_plugin_control_t * (* create_control) (void); void (* destroy_control) (ply_label_plugin_control_t *label); bool (* show_control) (ply_label_plugin_control_t *label, - ply_window_t *window, - long x, - long y); + ply_pixel_display_t *display, + long x, + long y); void (* hide_control) (ply_label_plugin_control_t *label); - void (* draw_control) (ply_label_plugin_control_t *label); + void (* draw_control) (ply_label_plugin_control_t *label, + ply_pixel_buffer_t *pixel_buffer, + long x, + long y, + unsigned long width, + unsigned long height); bool (* is_control_hidden) (ply_label_plugin_control_t *label); void (* set_text_for_control) (ply_label_plugin_control_t *label, diff --git a/src/libplybootsplash/ply-label.c b/src/libplybootsplash/ply-label.c index 16a8b1fc..ef68081f 100644 --- a/src/libplybootsplash/ply-label.c +++ b/src/libplybootsplash/ply-label.c @@ -136,10 +136,10 @@ ply_label_unload_plugin (ply_label_t *label) } bool -ply_label_show (ply_label_t *label, - ply_window_t *window, - long x, - long y) +ply_label_show (ply_label_t *label, + ply_pixel_display_t *display, + long x, + long y) { if (label->plugin_interface == NULL) { @@ -148,7 +148,7 @@ ply_label_show (ply_label_t *label, } return label->plugin_interface->show_control (label->control, - window, x, y); + display, x, y); } void @@ -156,8 +156,22 @@ ply_label_draw (ply_label_t *label) { if (label->plugin_interface == NULL) return; +} - label->plugin_interface->draw_control (label->control); +void +ply_label_draw_area (ply_label_t *label, + ply_pixel_buffer_t *buffer, + long x, + long y, + unsigned long width, + unsigned long height) +{ + if (label->plugin_interface == NULL) + return; + + label->plugin_interface->draw_control (label->control, + buffer, + x, y, width, height); } void diff --git a/src/libplybootsplash/ply-label.h b/src/libplybootsplash/ply-label.h index c4673a2d..b342e17e 100644 --- a/src/libplybootsplash/ply-label.h +++ b/src/libplybootsplash/ply-label.h @@ -27,7 +27,8 @@ #include #include "ply-event-loop.h" -#include "ply-window.h" +#include "ply-pixel-buffer.h" +#include "ply-pixel-display.h" typedef struct _ply_label ply_label_t; @@ -35,13 +36,19 @@ typedef struct _ply_label ply_label_t; ply_label_t *ply_label_new (void); void ply_label_free (ply_label_t *label); -bool ply_label_show (ply_label_t *label, - ply_window_t *window, - long x, - long y); +bool ply_label_show (ply_label_t *label, + ply_pixel_display_t *display, + long x, + long y); void ply_label_hide (ply_label_t *label); void ply_label_draw (ply_label_t *label); +void ply_label_draw_area (ply_label_t *label, + ply_pixel_buffer_t *buffer, + long x, + long y, + unsigned long width, + unsigned long height); bool ply_label_is_hidden (ply_label_t *label); void ply_label_set_text (ply_label_t *label, diff --git a/src/plugins/controls/label/plugin.c b/src/plugins/controls/label/plugin.c index 24bdf945..54917b18 100644 --- a/src/plugins/controls/label/plugin.c +++ b/src/plugins/controls/label/plugin.c @@ -43,22 +43,18 @@ #include #include -#include "ply-frame-buffer.h" +#include "ply-pixel-buffer.h" +#include "ply-pixel-display.h" #include "ply-utils.h" -#include "ply-window.h" #include "ply-label-plugin.h" struct _ply_label_plugin_control { ply_event_loop_t *loop; - ply_window_t *window; - ply_frame_buffer_t *frame_buffer; - ply_frame_buffer_area_t area; + ply_pixel_display_t *display; + ply_rectangle_t area; - PangoLayout *pango_layout; - cairo_t *cairo_context; - cairo_surface_t *cairo_surface; char *text; uint32_t is_hidden : 1; @@ -82,64 +78,135 @@ destroy_control (ply_label_plugin_control_t *label) if (label == NULL) return; - cairo_destroy (label->cairo_context); - cairo_surface_destroy (label->cairo_surface); - g_object_unref (label->pango_layout); - free (label); } long get_width_of_control (ply_label_plugin_control_t *label) { - int width; - - pango_layout_get_size (label->pango_layout, &width, NULL); - - return (long) ((double) width / PANGO_SCALE)+1; + return label->area.width; } long get_height_of_control (ply_label_plugin_control_t *label) { - int height; + return label->area.height; +} - pango_layout_get_size (label->pango_layout, NULL, &height); +static cairo_t * +get_cairo_context_for_pixel_buffer (ply_label_plugin_control_t *label, + ply_pixel_buffer_t *pixel_buffer) +{ + cairo_surface_t *cairo_surface; + cairo_t *cairo_context; + unsigned char *data; + ply_rectangle_t size; - return (long) ((double) height / PANGO_SCALE)+1; + data = (unsigned char *) ply_pixel_buffer_get_argb32_data (pixel_buffer); + ply_pixel_buffer_get_size (pixel_buffer, &size); + + cairo_surface = cairo_image_surface_create_for_data (data, + CAIRO_FORMAT_ARGB32, + size.width, + size.height, + size.width * 4); + cairo_context = cairo_create (cairo_surface); + cairo_surface_destroy (cairo_surface); + + return cairo_context; +} + +static cairo_t * +get_cairo_context_for_sizing (ply_label_plugin_control_t *label) +{ + cairo_surface_t *cairo_surface; + cairo_t *cairo_context; + + cairo_surface = cairo_image_surface_create_for_data (NULL, CAIRO_FORMAT_ARGB32, 0, 0, 0); + cairo_context = cairo_create (cairo_surface); + cairo_surface_destroy (cairo_surface); + + return cairo_context; } static void -erase_label_area (ply_label_plugin_control_t *label) -{ - ply_window_erase_area (label->window, - label->area.x, label->area.y, - label->area.width, label->area.height); -} - -void -draw_control (ply_label_plugin_control_t *label) +size_control (ply_label_plugin_control_t *label) { + cairo_t *cairo_context; + PangoLayout *pango_layout; + PangoFontDescription *description; + int text_width; + int text_height; if (label->is_hidden) return; - ply_frame_buffer_pause_updates (label->frame_buffer); - erase_label_area (label); - cairo_move_to (label->cairo_context, + cairo_context = get_cairo_context_for_sizing (label); + + pango_layout = pango_cairo_create_layout (cairo_context); + + description = pango_font_description_from_string ("Sans 12"); + pango_layout_set_font_description (pango_layout, description); + pango_font_description_free (description); + + pango_layout_set_text (pango_layout, label->text, -1); + pango_cairo_update_layout (cairo_context, pango_layout); + pango_layout_get_size (pango_layout, &text_width, &text_height); + label->area.width = (long) ((double) text_width / PANGO_SCALE) + 1; + label->area.height = (long) ((double) text_height / PANGO_SCALE) + 1; + + g_object_unref (pango_layout); + cairo_destroy (cairo_context); +} + +void +draw_control (ply_label_plugin_control_t *label, + ply_pixel_buffer_t *pixel_buffer, + long x, + long y, + unsigned long width, + unsigned long height) +{ + cairo_t *cairo_context; + PangoLayout *pango_layout; + PangoFontDescription *description; + int text_width; + int text_height; + + if (label->is_hidden) + return; + + cairo_context = get_cairo_context_for_pixel_buffer (label, pixel_buffer); + + pango_layout = pango_cairo_create_layout (cairo_context); + + description = pango_font_description_from_string ("Sans 12"); + pango_layout_set_font_description (pango_layout, description); + pango_font_description_free (description); + + pango_layout_set_text (pango_layout, label->text, -1); + pango_cairo_update_layout (cairo_context, pango_layout); + pango_layout_get_size (pango_layout, &text_width, &text_height); + label->area.width = (long) ((double) text_width / PANGO_SCALE) + 1; + label->area.height = (long) ((double) text_height / PANGO_SCALE) + 1; + + cairo_rectangle (cairo_context, x, y, width, height); + cairo_clip (cairo_context); + cairo_move_to (cairo_context, label->area.x + 1, label->area.y + 1); - cairo_set_source_rgba (label->cairo_context, 0.0, 0.0, 0.0, 0.7); - pango_cairo_show_layout (label->cairo_context, - label->pango_layout); - cairo_move_to (label->cairo_context, + cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, 0.7); + pango_cairo_show_layout (cairo_context, + pango_layout); + cairo_move_to (cairo_context, label->area.x, label->area.y); - cairo_set_source_rgb (label->cairo_context, 1.0, 1.0, 1.0); - pango_cairo_show_layout (label->cairo_context, - label->pango_layout); - cairo_surface_flush (label->cairo_surface); - ply_frame_buffer_unpause_updates (label->frame_buffer); + cairo_set_source_rgb (cairo_context, 1.0, 1.0, 1.0); + pango_cairo_show_layout (cairo_context, + pango_layout); + + g_object_unref (pango_layout); + cairo_destroy (cairo_context); } void @@ -151,56 +218,21 @@ set_text_for_control (ply_label_plugin_control_t *label, free (label->text); label->text = strdup (text); } - - if (label->pango_layout != NULL) - { - pango_layout_set_text (label->pango_layout, text, -1); - pango_cairo_update_layout (label->cairo_context, label->pango_layout); - - label->area.width = get_width_of_control (label); - label->area.height = get_height_of_control (label); - - } } bool show_control (ply_label_plugin_control_t *label, - ply_window_t *window, + ply_pixel_display_t *display, long x, long y) { - PangoFontDescription *description; - ply_frame_buffer_area_t size; - unsigned char *data; - - label->window = window; - label->frame_buffer = ply_window_get_frame_buffer (window); - data = (unsigned char *) ply_frame_buffer_get_bytes (label->frame_buffer); - + label->display = display; label->area.x = x; label->area.y = y; - ply_frame_buffer_get_size (label->frame_buffer, &size); - - label->cairo_surface = cairo_image_surface_create_for_data (data, - CAIRO_FORMAT_ARGB32, - size.width, - size.height, - size.width * 4); - - label->cairo_context = cairo_create (label->cairo_surface); - label->pango_layout = pango_cairo_create_layout (label->cairo_context); - - if (label->text != NULL) - set_text_for_control (label, label->text); - - description = pango_font_description_from_string ("Sans 12"); - pango_layout_set_font_description (label->pango_layout, description); - pango_font_description_free (description); - label->is_hidden = false; - draw_control (label); + size_control (label); return true; } @@ -208,22 +240,13 @@ show_control (ply_label_plugin_control_t *label, void hide_control (ply_label_plugin_control_t *label) { - erase_label_area (label); - - g_object_unref (label->pango_layout); - label->pango_layout = NULL; - - cairo_destroy (label->cairo_context); - label->cairo_context = NULL; - - cairo_surface_destroy (label->cairo_surface); - label->cairo_surface = NULL; - - label->frame_buffer = NULL; - label->window = NULL; - label->loop = NULL; - label->is_hidden = true; + ply_pixel_display_draw_area (label->display, + label->area.x, label->area.y, + label->area.width, label->area.height); + + label->display = NULL; + label->loop = NULL; } bool From d27523ddcfebd3c26eb33420a314ce5547deb3a6 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 15:08:59 -0400 Subject: [PATCH 15/43] [entry] Use pixel display instead of window --- src/libplybootsplash/ply-entry.c | 69 ++++++++++++++++---------------- src/libplybootsplash/ply-entry.h | 13 ++++-- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/src/libplybootsplash/ply-entry.c b/src/libplybootsplash/ply-entry.c index d59d9207..1940b368 100644 --- a/src/libplybootsplash/ply-entry.c +++ b/src/libplybootsplash/ply-entry.c @@ -45,10 +45,10 @@ #include "ply-array.h" #include "ply-label.h" #include "ply-logger.h" -#include "ply-frame-buffer.h" #include "ply-image.h" +#include "ply-pixel-buffer.h" +#include "ply-pixel-display.h" #include "ply-utils.h" -#include "ply-window.h" #include @@ -60,9 +60,8 @@ struct _ply_entry { ply_event_loop_t *loop; - ply_window_t *window; - ply_frame_buffer_t *frame_buffer; - ply_frame_buffer_area_t area; + ply_pixel_display_t *display; + ply_rectangle_t area; ply_image_t *text_field_image; ply_image_t *bullet_image; ply_label_t *label; @@ -148,33 +147,36 @@ ply_entry_load (ply_entry_t *entry) } static void -erase_entry_area (ply_entry_t *entry) +ply_entry_draw (ply_entry_t *entry) { - ply_window_erase_area (entry->window, - entry->area.x, entry->area.y, - entry->area.width, entry->area.height); + ply_pixel_display_draw_area (entry->display, + entry->area.x, + entry->area.y, + entry->area.width, + entry->area.height); } void -ply_entry_draw (ply_entry_t *entry) +ply_entry_draw_area (ply_entry_t *entry, + ply_pixel_buffer_t *pixel_buffer, + long x, + long y, + unsigned long width, + unsigned long height) { - ply_frame_buffer_area_t bullet_area; + ply_rectangle_t bullet_area; uint32_t *text_field_data, *bullet_data; int i, number_of_visible_bullets; if (entry->is_hidden) return; - ply_frame_buffer_pause_updates (entry->frame_buffer); - text_field_data = ply_image_get_data (entry->text_field_image); - erase_entry_area (entry); - - ply_frame_buffer_fill_with_argb32_data (entry->frame_buffer, + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &entry->area, 0, 0, text_field_data); - + if (entry->is_password) { bullet_data = ply_image_get_data (entry->bullet_image); @@ -193,7 +195,7 @@ ply_entry_draw (ply_entry_t *entry) bullet_area.x = entry->area.x; bullet_area.y = entry->area.y + entry->area.height / 2.0 - bullet_area.height / 2.0; - ply_frame_buffer_fill_with_argb32_data (entry->frame_buffer, + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &bullet_area, bullet_area.width / 2.0, 0, bullet_data); } @@ -203,7 +205,7 @@ ply_entry_draw (ply_entry_t *entry) bullet_area.x = entry->area.x + i * bullet_area.width + bullet_area.width / 2.0; bullet_area.y = entry->area.y + entry->area.height / 2.0 - bullet_area.height / 2.0; - ply_frame_buffer_fill_with_argb32_data (entry->frame_buffer, + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &bullet_area, 0, 0, bullet_data); } @@ -211,10 +213,10 @@ ply_entry_draw (ply_entry_t *entry) else { ply_label_set_text (entry->label, entry->text); - ply_label_show (entry->label, entry->window, entry->area.x, entry->area.y); - + ply_label_draw_area (entry->label, pixel_buffer, + entry->area.x, entry->area.y, + entry->area.width, entry->area.height); } - ply_frame_buffer_unpause_updates (entry->frame_buffer); } void @@ -266,18 +268,17 @@ ply_entry_set_text (ply_entry_t *entry, const char* text) } void -ply_entry_show (ply_entry_t *entry, - ply_event_loop_t *loop, - ply_window_t *window, - long x, - long y) +ply_entry_show (ply_entry_t *entry, + ply_event_loop_t *loop, + ply_pixel_display_t *display, + long x, + long y) { assert (entry != NULL); assert (entry->loop == NULL); entry->loop = loop; - entry->window = window; - entry->frame_buffer = ply_window_get_frame_buffer (window);; + entry->display = display; entry->area.x = x; entry->area.y = y; @@ -290,13 +291,11 @@ ply_entry_show (ply_entry_t *entry, void ply_entry_hide (ply_entry_t *entry) { - erase_entry_area (entry); - - entry->frame_buffer = NULL; - entry->window = NULL; - entry->loop = NULL; - entry->is_hidden = true; + ply_entry_draw (entry); + + entry->display = NULL; + entry->loop = NULL; } bool diff --git a/src/libplybootsplash/ply-entry.h b/src/libplybootsplash/ply-entry.h index 76bf2adb..658e2db2 100644 --- a/src/libplybootsplash/ply-entry.h +++ b/src/libplybootsplash/ply-entry.h @@ -27,8 +27,8 @@ #include #include "ply-event-loop.h" -#include "ply-frame-buffer.h" -#include "ply-window.h" +#include "ply-pixel-buffer.h" +#include "ply-pixel-display.h" typedef struct _ply_entry ply_entry_t; @@ -39,11 +39,16 @@ bool ply_entry_load (ply_entry_t *entry); void ply_entry_show (ply_entry_t *entry, ply_event_loop_t *loop, - ply_window_t *window, + ply_pixel_display_t *display, long x, long y); void ply_entry_hide (ply_entry_t *entry); -void ply_entry_draw (ply_entry_t *entry); +void ply_entry_draw_area (ply_entry_t *entry, + ply_pixel_buffer_t *buffer, + long x, + long y, + unsigned long width, + unsigned long height); bool ply_entry_is_hidden (ply_entry_t *entry); long ply_entry_get_width (ply_entry_t *entry); From 7376ad9d95d3023dc8aea7248355ed38eb545197 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 15:08:59 -0400 Subject: [PATCH 16/43] [animation] Use pixel display instead of window --- src/libplybootsplash/ply-animation.c | 64 ++++++++++++++-------------- src/libplybootsplash/ply-animation.h | 12 ++++-- 2 files changed, 42 insertions(+), 34 deletions(-) diff --git a/src/libplybootsplash/ply-animation.c b/src/libplybootsplash/ply-animation.c index 7d2c481d..9bd2b147 100644 --- a/src/libplybootsplash/ply-animation.c +++ b/src/libplybootsplash/ply-animation.c @@ -44,10 +44,9 @@ #include "ply-event-loop.h" #include "ply-array.h" #include "ply-logger.h" -#include "ply-frame-buffer.h" #include "ply-image.h" +#include "ply-pixel-buffer.h" #include "ply-utils.h" -#include "ply-window.h" #include @@ -62,9 +61,8 @@ struct _ply_animation char *image_dir; char *frames_prefix; - ply_window_t *window; - ply_frame_buffer_t *frame_buffer; - ply_frame_buffer_area_t frame_area; + ply_pixel_display_t *display; + ply_rectangle_t frame_area; ply_trigger_t *stop_trigger; int frame_number; @@ -128,26 +126,14 @@ ply_animation_free (ply_animation_t *animation) free (animation); } -static void -draw_background (ply_animation_t *animation) -{ - ply_window_erase_area (animation->window, - animation->x, animation->y, - animation->frame_area.width, - animation->frame_area.height); -} - static bool animate_at_time (ply_animation_t *animation, double time) { int number_of_frames; ply_image_t * const * frames; - uint32_t *frame_data; bool should_continue; - ply_window_set_mode (animation->window, PLY_WINDOW_MODE_GRAPHICS); - number_of_frames = ply_array_get_size (animation->frames); if (number_of_frames == 0) @@ -161,22 +147,17 @@ animate_at_time (ply_animation_t *animation, if (animation->stop_requested) should_continue = false; - ply_frame_buffer_pause_updates (animation->frame_buffer); - if (animation->frame_area.width > 0) - draw_background (animation); - frames = (ply_image_t * const *) ply_array_get_elements (animation->frames); animation->frame_area.x = animation->x; animation->frame_area.y = animation->y; animation->frame_area.width = ply_image_get_width (frames[animation->frame_number]); animation->frame_area.height = ply_image_get_height (frames[animation->frame_number]); - frame_data = ply_image_get_data (frames[animation->frame_number]); - ply_frame_buffer_fill_with_argb32_data (animation->frame_buffer, - &animation->frame_area, 0, 0, - frame_data); - ply_frame_buffer_unpause_updates (animation->frame_buffer); + ply_pixel_display_draw_area (animation->display, + animation->x, animation->y, + animation->frame_area.width, + animation->frame_area.height); animation->frame_number++; @@ -314,7 +295,7 @@ ply_animation_load (ply_animation_t *animation) bool ply_animation_start (ply_animation_t *animation, ply_event_loop_t *loop, - ply_window_t *window, + ply_pixel_display_t *display, ply_trigger_t *stop_trigger, long x, long y) @@ -323,9 +304,8 @@ ply_animation_start (ply_animation_t *animation, assert (animation->loop == NULL); animation->loop = loop; - animation->window = window; + animation->display = display; animation->stop_trigger = stop_trigger; - animation->frame_buffer = ply_window_get_frame_buffer (window);; animation->is_stopped = false; animation->stop_requested = false; @@ -345,8 +325,6 @@ ply_animation_start (ply_animation_t *animation, static void ply_animation_stop_now (ply_animation_t *animation) { - animation->frame_buffer = NULL; - animation->window = NULL; animation->is_stopped = true; if (animation->loop != NULL) @@ -356,6 +334,8 @@ ply_animation_stop_now (ply_animation_t *animation) on_timeout, animation); animation->loop = NULL; } + + animation->display = NULL; } void @@ -376,6 +356,28 @@ ply_animation_is_stopped (ply_animation_t *animation) return animation->is_stopped; } +void +ply_animation_draw_area (ply_animation_t *animation, + ply_pixel_buffer_t *buffer, + long x, + long y, + unsigned long width, + unsigned long height) +{ + ply_image_t * const * frames; + uint32_t *frame_data; + + if (animation->is_stopped) + return; + + frames = (ply_image_t * const *) ply_array_get_elements (animation->frames); + frame_data = ply_image_get_data (frames[animation->frame_number]); + + ply_pixel_buffer_fill_with_argb32_data (buffer, + &animation->frame_area, 0, 0, + frame_data); +} + long ply_animation_get_width (ply_animation_t *animation) { diff --git a/src/libplybootsplash/ply-animation.h b/src/libplybootsplash/ply-animation.h index eea68d81..7a0bdf33 100644 --- a/src/libplybootsplash/ply-animation.h +++ b/src/libplybootsplash/ply-animation.h @@ -27,9 +27,8 @@ #include #include "ply-event-loop.h" -#include "ply-frame-buffer.h" +#include "ply-pixel-display.h" #include "ply-trigger.h" -#include "ply-window.h" typedef struct _ply_animation ply_animation_t; @@ -41,13 +40,20 @@ void ply_animation_free (ply_animation_t *animation); bool ply_animation_load (ply_animation_t *animation); bool ply_animation_start (ply_animation_t *animation, ply_event_loop_t *loop, - ply_window_t *window, + ply_pixel_display_t *display, ply_trigger_t *stop_trigger, long x, long y); void ply_animation_stop (ply_animation_t *animation); bool ply_animation_is_stopped (ply_animation_t *animation); +void ply_animation_draw_area (ply_animation_t *animation, + ply_pixel_buffer_t *buffer, + long x, + long y, + unsigned long width, + unsigned long height); + long ply_animation_get_width (ply_animation_t *animation); long ply_animation_get_height (ply_animation_t *animation); #endif From 9c1307267969617d09afab54149e4f9b99a484a5 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 15:08:59 -0400 Subject: [PATCH 17/43] [throbber] Use pixel display instead of window --- src/libplybootsplash/ply-throbber.c | 96 +++++++++++++++-------------- src/libplybootsplash/ply-throbber.h | 19 ++++-- 2 files changed, 62 insertions(+), 53 deletions(-) diff --git a/src/libplybootsplash/ply-throbber.c b/src/libplybootsplash/ply-throbber.c index 7c2d3327..3e463d36 100644 --- a/src/libplybootsplash/ply-throbber.c +++ b/src/libplybootsplash/ply-throbber.c @@ -42,12 +42,12 @@ #include "ply-throbber.h" #include "ply-event-loop.h" +#include "ply-pixel-buffer.h" +#include "ply-pixel-display.h" #include "ply-array.h" #include "ply-logger.h" -#include "ply-frame-buffer.h" #include "ply-image.h" #include "ply-utils.h" -#include "ply-window.h" #include @@ -62,14 +62,15 @@ struct _ply_throbber char *image_dir; char *frames_prefix; - ply_window_t *window; - ply_frame_buffer_t *frame_buffer; - ply_frame_buffer_area_t frame_area; + ply_pixel_display_t *display; + ply_rectangle_t frame_area; ply_trigger_t *stop_trigger; long x, y; long width, height; double start_time, previous_time, now; + + int frame_number; uint32_t is_stopped : 1; }; @@ -94,6 +95,7 @@ ply_throbber_new (const char *image_dir, throbber->frame_area.height = 0; throbber->frame_area.x = 0; throbber->frame_area.y = 0; + throbber->frame_number = 0; return throbber; } @@ -124,27 +126,14 @@ ply_throbber_free (ply_throbber_t *throbber) free (throbber); } -static void -draw_background (ply_throbber_t *throbber) -{ - ply_window_erase_area (throbber->window, - throbber->x, throbber->y, - throbber->frame_area.width, - throbber->frame_area.height); -} - static bool animate_at_time (ply_throbber_t *throbber, double time) { int number_of_frames; - int frame_number; ply_image_t * const * frames; - uint32_t *frame_data; bool should_continue; - ply_window_set_mode (throbber->window, PLY_WINDOW_MODE_GRAPHICS); - number_of_frames = ply_array_get_size (throbber->frames); if (number_of_frames == 0) @@ -152,31 +141,25 @@ animate_at_time (ply_throbber_t *throbber, should_continue = true; - frame_number = (.5 * sin (time) + .5) * number_of_frames; + throbber->frame_number = (.5 * sin (time) + .5) * number_of_frames; if (throbber->stop_trigger != NULL) { if ((time - throbber->previous_time) >= 2 * M_PI) - frame_number = number_of_frames - 1; + throbber->frame_number = number_of_frames - 1; should_continue = false; } - ply_frame_buffer_pause_updates (throbber->frame_buffer); - if (throbber->frame_area.width > 0) - draw_background (throbber); - frames = (ply_image_t * const *) ply_array_get_elements (throbber->frames); throbber->frame_area.x = throbber->x; throbber->frame_area.y = throbber->y; - throbber->frame_area.width = ply_image_get_width (frames[frame_number]); - throbber->frame_area.height = ply_image_get_height (frames[frame_number]); - frame_data = ply_image_get_data (frames[frame_number]); - - ply_frame_buffer_fill_with_argb32_data (throbber->frame_buffer, - &throbber->frame_area, 0, 0, - frame_data); - ply_frame_buffer_unpause_updates (throbber->frame_buffer); + throbber->frame_area.width = ply_image_get_width (frames[throbber->frame_number]); + throbber->frame_area.height = ply_image_get_height (frames[throbber->frame_number]); + ply_pixel_display_draw_area (throbber->display, + throbber->x, throbber->y, + throbber->frame_area.width, + throbber->frame_area.height); return should_continue; } @@ -204,9 +187,6 @@ on_timeout (ply_throbber_t *throbber) if (!should_continue) { - - draw_background (throbber); - if (throbber->stop_trigger != NULL) { ply_trigger_pull (throbber->stop_trigger, NULL); @@ -313,18 +293,17 @@ ply_throbber_load (ply_throbber_t *throbber) } bool -ply_throbber_start (ply_throbber_t *throbber, - ply_event_loop_t *loop, - ply_window_t *window, - long x, - long y) +ply_throbber_start (ply_throbber_t *throbber, + ply_event_loop_t *loop, + ply_pixel_display_t *display, + long x, + long y) { assert (throbber != NULL); assert (throbber->loop == NULL); throbber->loop = loop; - throbber->window = window; - throbber->frame_buffer = ply_window_get_frame_buffer (window);; + throbber->display = display; throbber->is_stopped = false; throbber->x = x; @@ -343,13 +322,13 @@ ply_throbber_start (ply_throbber_t *throbber, static void ply_throbber_stop_now (ply_throbber_t *throbber) { - if (throbber->frame_area.width > 0) - draw_background (throbber); - - throbber->frame_buffer = NULL; - throbber->window = NULL; throbber->is_stopped = true; + ply_pixel_display_draw_area (throbber->display, + throbber->x, + throbber->y, + throbber->frame_area.width, + throbber->frame_area.height); if (throbber->loop != NULL) { ply_event_loop_stop_watching_for_timeout (throbber->loop, @@ -357,6 +336,7 @@ ply_throbber_stop_now (ply_throbber_t *throbber) on_timeout, throbber); throbber->loop = NULL; } + throbber->display = NULL; } void @@ -379,6 +359,28 @@ ply_throbber_is_stopped (ply_throbber_t *throbber) return throbber->is_stopped; } +void +ply_throbber_draw_area (ply_throbber_t *throbber, + ply_pixel_buffer_t *buffer, + long x, + long y, + unsigned long width, + unsigned long height) +{ + ply_image_t * const * frames; + uint32_t *frame_data; + + if (throbber->is_stopped) + return; + + frames = (ply_image_t * const *) ply_array_get_elements (throbber->frames); + frame_data = ply_image_get_data (frames[throbber->frame_number]); + + ply_pixel_buffer_fill_with_argb32_data (buffer, + &throbber->frame_area, 0, 0, + frame_data); +} + long ply_throbber_get_width (ply_throbber_t *throbber) { diff --git a/src/libplybootsplash/ply-throbber.h b/src/libplybootsplash/ply-throbber.h index 647f409c..272a7d92 100644 --- a/src/libplybootsplash/ply-throbber.h +++ b/src/libplybootsplash/ply-throbber.h @@ -27,9 +27,9 @@ #include #include "ply-event-loop.h" -#include "ply-frame-buffer.h" +#include "ply-pixel-buffer.h" +#include "ply-pixel-display.h" #include "ply-trigger.h" -#include "ply-window.h" typedef struct _ply_throbber ply_throbber_t; @@ -40,14 +40,21 @@ void ply_throbber_free (ply_throbber_t *throbber); bool ply_throbber_load (ply_throbber_t *throbber); bool ply_throbber_start (ply_throbber_t *throbber, - ply_event_loop_t *loop, - ply_window_t *window, - long x, - long y); + ply_event_loop_t *loop, + ply_pixel_display_t *display, + long x, + long y); void ply_throbber_stop (ply_throbber_t *throbber, ply_trigger_t *stop_trigger); bool ply_throbber_is_stopped (ply_throbber_t *throbber); +void ply_throbber_draw_area (ply_throbber_t *throbber, + ply_pixel_buffer_t *buffer, + long x, + long y, + unsigned long width, + unsigned long height); + long ply_throbber_get_width (ply_throbber_t *throbber); long ply_throbber_get_height (ply_throbber_t *throbber); #endif From f9fd1c105ca5856a208abc458782723af8b5f709 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 15:08:59 -0400 Subject: [PATCH 18/43] [progress-animation] Use pixel display instead of window --- src/libplybootsplash/ply-progress-animation.c | 168 ++++++++++++------ src/libplybootsplash/ply-progress-animation.h | 11 +- 2 files changed, 119 insertions(+), 60 deletions(-) diff --git a/src/libplybootsplash/ply-progress-animation.c b/src/libplybootsplash/ply-progress-animation.c index 59bdfa18..9d64e713 100644 --- a/src/libplybootsplash/ply-progress-animation.c +++ b/src/libplybootsplash/ply-progress-animation.c @@ -44,10 +44,8 @@ #include "ply-progress-animation.h" #include "ply-array.h" #include "ply-logger.h" -#include "ply-frame-buffer.h" #include "ply-image.h" #include "ply-utils.h" -#include "ply-window.h" #include @@ -60,16 +58,17 @@ struct _ply_progress_animation ply_progress_animation_transition_t transition; double transition_duration; - ply_window_t *window; - ply_frame_buffer_t *frame_buffer; - ply_frame_buffer_area_t area; - ply_frame_buffer_area_t frame_area; + ply_pixel_display_t *display; + ply_rectangle_t area; + ply_rectangle_t frame_area; double percent_done; int previous_frame_number; double transition_start_time; + ply_pixel_buffer_t *last_rendered_frame; + uint32_t is_hidden : 1; uint32_t is_transitioning : 1; }; @@ -99,6 +98,7 @@ ply_progress_animation_new (const char *image_dir, progress_animation->frame_area.width = 0; progress_animation->frame_area.height = 0; progress_animation->previous_frame_number = 0; + progress_animation->last_rendered_frame = NULL; return progress_animation; } @@ -139,16 +139,12 @@ ply_progress_animation_free (ply_progress_animation_t *progress_animation) } static void -draw_background (ply_progress_animation_t *progress_animation) -{ - ply_window_erase_area (progress_animation->window, - progress_animation->area.x, progress_animation->area.y, - progress_animation->frame_area.width, - progress_animation->frame_area.height); -} - -static uint32_t* -image_fade_merge(ply_image_t* frame0, ply_image_t* frame1, float fade, int width, int height) +image_fade_merge (ply_image_t* frame0, + ply_image_t* frame1, + float fade, + int width, + int height, + uint32_t *reply_data) { int frame0_width = ply_image_get_width (frame0); int frame0_height = ply_image_get_height (frame0); @@ -158,10 +154,8 @@ image_fade_merge(ply_image_t* frame0, ply_image_t* frame1, float fade, int width uint32_t *frame0_data = ply_image_get_data (frame0); uint32_t *frame1_data = ply_image_get_data (frame1); - uint32_t *reply_data = malloc (width * height * sizeof (uint32_t)); int x, y, i; - for (y = 0; y < height; y++) { for (x = 0; x < width; x++) @@ -189,7 +183,26 @@ image_fade_merge(ply_image_t* frame0, ply_image_t* frame1, float fade, int width reply_data[y*width+x] = pixelout; } } - return reply_data; +} + +void +ply_progress_animation_draw_area (ply_progress_animation_t *progress_animation, + ply_pixel_buffer_t *buffer, + long x, + long y, + unsigned long width, + unsigned long height) +{ + uint32_t *frame_data; + + if (progress_animation->is_hidden) + return; + + frame_data = ply_pixel_buffer_get_argb32_data (progress_animation->last_rendered_frame); + + ply_pixel_buffer_fill_with_argb32_data (buffer, + &progress_animation->frame_area, 0, 0, + frame_data); } void @@ -203,8 +216,6 @@ ply_progress_animation_draw (ply_progress_animation_t *progress_animation) if (progress_animation->is_hidden) return; - ply_window_set_mode (progress_animation->window, PLY_WINDOW_MODE_GRAPHICS); - number_of_frames = ply_array_get_size (progress_animation->frames); if (number_of_frames == 0) @@ -212,10 +223,6 @@ ply_progress_animation_draw (ply_progress_animation_t *progress_animation) frame_number = progress_animation->percent_done * (number_of_frames - 1); - ply_frame_buffer_pause_updates (progress_animation->frame_buffer); - if (progress_animation->frame_area.width > 0) - draw_background (progress_animation); - if (progress_animation->previous_frame_number != frame_number && progress_animation->transition != PLY_PROGRESS_ANIMATION_TRANSITION_NONE && progress_animation->transition_duration > 0.0) @@ -245,7 +252,6 @@ ply_progress_animation_draw (ply_progress_animation_t *progress_animation) progress_animation->is_transitioning = false; fade_percentage = CLAMP (fade_percentage, 0.0, 1.0); - previous_frame_data = ply_image_get_data (frames[frame_number - 1]); if (progress_animation->transition == PLY_PROGRESS_ANIMATION_TRANSITION_MERGE_FADE) { width = MAX(ply_image_get_width (frames[frame_number]), ply_image_get_width (frames[frame_number - 1])); @@ -253,30 +259,62 @@ ply_progress_animation_draw (ply_progress_animation_t *progress_animation) progress_animation->frame_area.width = width; progress_animation->frame_area.height = height; - faded_data = image_fade_merge(frames[frame_number - 1], frames[frame_number], fade_percentage, width, height); + ply_pixel_buffer_free (progress_animation->last_rendered_frame); + progress_animation->last_rendered_frame = ply_pixel_buffer_new (width, height); + faded_data = ply_pixel_buffer_get_argb32_data (progress_animation->last_rendered_frame); - ply_frame_buffer_fill_with_argb32_data_at_opacity (progress_animation->frame_buffer, - &progress_animation->frame_area, 0, 0, - faded_data, 1.0); - free(faded_data); + image_fade_merge (frames[frame_number - 1], frames[frame_number], fade_percentage, width, height, faded_data); + + ply_pixel_display_draw_area (progress_animation->display, + progress_animation->frame_area.x, + progress_animation->frame_area.y, + progress_animation->frame_area.width, + progress_animation->frame_area.height); } else { - if (progress_animation->transition == PLY_PROGRESS_ANIMATION_TRANSITION_FADE_OVER) - fade_out_opacity = 1.0; - else - fade_out_opacity = 1.0 - fade_percentage; + ply_rectangle_t fill_area; - progress_animation->frame_area.width = ply_image_get_width (frames[frame_number - 1]); - progress_animation->frame_area.height = ply_image_get_height (frames[frame_number - 1]); - ply_frame_buffer_fill_with_argb32_data_at_opacity (progress_animation->frame_buffer, - &progress_animation->frame_area, 0, 0, - previous_frame_data, fade_out_opacity); + previous_frame_data = ply_image_get_data (frames[frame_number - 1]); + if (progress_animation->transition == PLY_PROGRESS_ANIMATION_TRANSITION_FADE_OVER) + { + ply_pixel_buffer_free (progress_animation->last_rendered_frame); + progress_animation->frame_area.width = ply_image_get_width (frames[frame_number - 1]); + progress_animation->frame_area.height = ply_image_get_height (frames[frame_number - 1]); + + progress_animation->last_rendered_frame = ply_pixel_buffer_new (progress_animation->frame_area.width, + progress_animation->frame_area.height); + fill_area.x = 0; + fill_area.y = 0; + fill_area.width = progress_animation->frame_area.width; + fill_area.height = progress_animation->frame_area.height; + ply_pixel_buffer_fill_with_argb32_data (progress_animation->last_rendered_frame, + &fill_area, 0, 0, + previous_frame_data); + } + else + { + fade_out_opacity = 1.0 - fade_percentage; + progress_animation->frame_area.width = ply_image_get_width (frames[frame_number - 1]); + progress_animation->frame_area.height = ply_image_get_height (frames[frame_number - 1]); + + fill_area.x = 0; + fill_area.y = 0; + fill_area.width = progress_animation->frame_area.width; + fill_area.height = progress_animation->frame_area.height; + ply_pixel_buffer_fill_with_argb32_data_at_opacity (progress_animation->last_rendered_frame, + &fill_area, 0, 0, + previous_frame_data, fade_out_opacity); + } progress_animation->frame_area.width = ply_image_get_width (frames[frame_number]); progress_animation->frame_area.height = ply_image_get_height (frames[frame_number]); - ply_frame_buffer_fill_with_argb32_data_at_opacity (progress_animation->frame_buffer, - &progress_animation->frame_area, 0, 0, + fill_area.x = 0; + fill_area.y = 0; + fill_area.width = progress_animation->frame_area.width; + fill_area.height = progress_animation->frame_area.height; + ply_pixel_buffer_fill_with_argb32_data_at_opacity (progress_animation->last_rendered_frame, + &fill_area, 0, 0, frame_data, fade_percentage); width = MAX(ply_image_get_width (frames[frame_number]), ply_image_get_width (frames[frame_number - 1])); @@ -284,20 +322,33 @@ ply_progress_animation_draw (ply_progress_animation_t *progress_animation) progress_animation->frame_area.width = width; progress_animation->frame_area.height = height; } - } else { + ply_rectangle_t fill_area; + + ply_pixel_buffer_free (progress_animation->last_rendered_frame); progress_animation->frame_area.width = ply_image_get_width (frames[frame_number]); progress_animation->frame_area.height = ply_image_get_height (frames[frame_number]); - ply_frame_buffer_fill_with_argb32_data (progress_animation->frame_buffer, - &progress_animation->frame_area, 0, 0, + progress_animation->last_rendered_frame = ply_pixel_buffer_new (progress_animation->frame_area.width, + progress_animation->frame_area.height); + + fill_area.x = 0; + fill_area.y = 0; + fill_area.width = progress_animation->frame_area.width; + fill_area.height = progress_animation->frame_area.height; + ply_pixel_buffer_fill_with_argb32_data (progress_animation->last_rendered_frame, + &fill_area, 0, 0, frame_data); } - ply_frame_buffer_unpause_updates (progress_animation->frame_buffer); - progress_animation->previous_frame_number = frame_number; + + ply_pixel_display_draw_area (progress_animation->display, + progress_animation->frame_area.x, + progress_animation->frame_area.y, + progress_animation->frame_area.width, + progress_animation->frame_area.height); } static bool @@ -392,14 +443,13 @@ ply_progress_animation_load (ply_progress_animation_t *progress_animation) void ply_progress_animation_show (ply_progress_animation_t *progress_animation, - ply_window_t *window, + ply_pixel_display_t *display, long x, long y) { assert (progress_animation != NULL); - progress_animation->window = window; - progress_animation->frame_buffer = ply_window_get_frame_buffer (window);; + progress_animation->display = display; progress_animation->area.x = x; progress_animation->area.y = y; @@ -414,13 +464,16 @@ ply_progress_animation_hide (ply_progress_animation_t *progress_animation) if (progress_animation->is_hidden) return; - if (progress_animation->frame_area.width > 0) - draw_background (progress_animation); - - progress_animation->frame_buffer = NULL; - progress_animation->window = NULL; - progress_animation->is_hidden = true; + if (progress_animation->frame_area.width > 0) + { + ply_pixel_display_draw_area (progress_animation->display, + progress_animation->area.x, progress_animation->area.y, + progress_animation->frame_area.width, + progress_animation->frame_area.height); + } + + progress_animation->display = NULL; } bool @@ -443,9 +496,10 @@ ply_progress_animation_get_height (ply_progress_animation_t *progress_animation) void ply_progress_animation_set_percent_done (ply_progress_animation_t *progress_animation, - double percent_done) + double percent_done) { progress_animation->percent_done = percent_done; + ply_progress_animation_draw (progress_animation); } double diff --git a/src/libplybootsplash/ply-progress-animation.h b/src/libplybootsplash/ply-progress-animation.h index 3c51d10f..274bd1c5 100644 --- a/src/libplybootsplash/ply-progress-animation.h +++ b/src/libplybootsplash/ply-progress-animation.h @@ -26,8 +26,7 @@ #include #include -#include "ply-frame-buffer.h" -#include "ply-window.h" +#include "ply-pixel-display.h" typedef struct _ply_progress_animation ply_progress_animation_t; @@ -49,11 +48,17 @@ void ply_progress_animation_set_transition (ply_progress_animation_t *progress_a ply_progress_animation_transition_t transition, double duration); void ply_progress_animation_show (ply_progress_animation_t *progress_animation, - ply_window_t *window, + ply_pixel_display_t *display, long x, long y); void ply_progress_animation_hide (ply_progress_animation_t *progress_animation); void ply_progress_animation_draw (ply_progress_animation_t *progress_animation); +void ply_progress_animation_draw_area (ply_progress_animation_t *progress_animation, + ply_pixel_buffer_t *buffer, + long x, + long y, + unsigned long width, + unsigned long height); bool ply_progress_animation_is_hidden (ply_progress_animation_t *progress_animation); long ply_progress_animation_get_width (ply_progress_animation_t *progress_animation); From 98ef9818a76031b9cde45f0850e4f11db7840ed2 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 15:08:59 -0400 Subject: [PATCH 19/43] [progress-bar] Use pixel display instead of window --- src/libplybootsplash/ply-progress-bar.c | 84 ++++++++++++++----------- src/libplybootsplash/ply-progress-bar.h | 12 +++- 2 files changed, 58 insertions(+), 38 deletions(-) diff --git a/src/libplybootsplash/ply-progress-bar.c b/src/libplybootsplash/ply-progress-bar.c index ba9c13d1..12ca46a9 100644 --- a/src/libplybootsplash/ply-progress-bar.c +++ b/src/libplybootsplash/ply-progress-bar.c @@ -45,12 +45,10 @@ #include "ply-event-loop.h" #include "ply-array.h" #include "ply-logger.h" -#include "ply-frame-buffer.h" +#include "ply-pixel-buffer.h" +#include "ply-pixel-display.h" #include "ply-image.h" #include "ply-utils.h" -#include "ply-window.h" - -#include #ifndef FRAMES_PER_SECOND #define FRAMES_PER_SECOND 30 @@ -62,9 +60,8 @@ struct _ply_progress_bar { - ply_window_t *window; - ply_frame_buffer_t *frame_buffer; - ply_frame_buffer_area_t area; + ply_pixel_display_t *display; + ply_rectangle_t area; double percent_done; @@ -96,55 +93,68 @@ ply_progress_bar_free (ply_progress_bar_t *progress_bar) free (progress_bar); } -static void -erase_progress_bar_area (ply_progress_bar_t *progress_bar) -{ - ply_window_erase_area (progress_bar->window, - progress_bar->area.x, progress_bar->area.y, - progress_bar->area.width, progress_bar->area.height); -} - static void ply_progress_bar_update_area (ply_progress_bar_t *progress_bar, long x, long y) { - - ply_frame_buffer_get_size (progress_bar->frame_buffer, &progress_bar->area); + unsigned long display_width; progress_bar->area.x = x; progress_bar->area.y = y; progress_bar->area.height = BAR_HEIGHT; - progress_bar->area.width = (long) (progress_bar->area.width * progress_bar->percent_done); + display_width = ply_pixel_display_get_width (progress_bar->display); + progress_bar->area.width = (long) (display_width * progress_bar->percent_done); +} + +void +ply_progress_bar_draw_area (ply_progress_bar_t *progress_bar, + ply_pixel_buffer_t *buffer, + long x, + long y, + unsigned long width, + unsigned long height) +{ + ply_rectangle_t paint_area; + + if (progress_bar->is_hidden) + return; + + paint_area.x = x; + paint_area.y = y; + paint_area.width = width; + paint_area.height = height; + + ply_rectangle_intersect (&progress_bar->area, &paint_area, &paint_area); + ply_pixel_buffer_fill_with_hex_color (buffer, + &paint_area, + 0xffffff); /* white */ } void ply_progress_bar_draw (ply_progress_bar_t *progress_bar) { - if (progress_bar->is_hidden) return; - ply_frame_buffer_pause_updates (progress_bar->frame_buffer); - erase_progress_bar_area (progress_bar); ply_progress_bar_update_area (progress_bar, progress_bar->area.x, progress_bar->area.y); - ply_frame_buffer_fill_with_hex_color (progress_bar->frame_buffer, - &progress_bar->area, - 0xffffff); /* white */ - ply_frame_buffer_unpause_updates (progress_bar->frame_buffer); + ply_pixel_display_draw_area (progress_bar->display, + progress_bar->area.x, + progress_bar->area.y, + progress_bar->area.width, + progress_bar->area.height); } void -ply_progress_bar_show (ply_progress_bar_t *progress_bar, - ply_window_t *window, - long x, - long y) +ply_progress_bar_show (ply_progress_bar_t *progress_bar, + ply_pixel_display_t *display, + long x, + long y) { assert (progress_bar != NULL); - progress_bar->window = window; - progress_bar->frame_buffer = ply_window_get_frame_buffer (window);; + progress_bar->display = display; ply_progress_bar_update_area (progress_bar, x, y); @@ -155,12 +165,16 @@ ply_progress_bar_show (ply_progress_bar_t *progress_bar, void ply_progress_bar_hide (ply_progress_bar_t *progress_bar) { - erase_progress_bar_area (progress_bar); - - progress_bar->frame_buffer = NULL; - progress_bar->window = NULL; + if (progress_bar->is_hidden) + return; progress_bar->is_hidden = true; + ply_pixel_display_draw_area (progress_bar->display, + progress_bar->area.x, progress_bar->area.y, + progress_bar->area.width, progress_bar->area.height); + + progress_bar->display = NULL; + } bool diff --git a/src/libplybootsplash/ply-progress-bar.h b/src/libplybootsplash/ply-progress-bar.h index 7e865605..2fd80e0b 100644 --- a/src/libplybootsplash/ply-progress-bar.h +++ b/src/libplybootsplash/ply-progress-bar.h @@ -28,8 +28,8 @@ #include #include "ply-event-loop.h" -#include "ply-frame-buffer.h" -#include "ply-window.h" +#include "ply-pixel-buffer.h" +#include "ply-pixel-display.h" typedef struct _ply_progress_bar ply_progress_bar_t; @@ -38,11 +38,17 @@ ply_progress_bar_t *ply_progress_bar_new (void); void ply_progress_bar_free (ply_progress_bar_t *bar); void ply_progress_bar_show (ply_progress_bar_t *bar, - ply_window_t *window, + ply_pixel_display_t *display, long x, long y); void ply_progress_bar_hide (ply_progress_bar_t *bar); void ply_progress_bar_draw (ply_progress_bar_t *bar); +void ply_progress_bar_draw_area (ply_progress_bar_t *bar, + ply_pixel_buffer_t *buffer, + long x, + long y, + unsigned long width, + unsigned long height); bool ply_progress_bar_is_hidden (ply_progress_bar_t *bar); long ply_progress_bar_get_width (ply_progress_bar_t *bar); From 096d21883ee9713886b4daa55a577e02fb853a24 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 15:08:59 -0400 Subject: [PATCH 20/43] [text-progress-bar] Use text display instead of window --- src/libplybootsplash/ply-text-progress-bar.c | 65 ++++++++++---------- src/libplybootsplash/ply-text-progress-bar.h | 4 +- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/libplybootsplash/ply-text-progress-bar.c b/src/libplybootsplash/ply-text-progress-bar.c index 1f972067..b7676c91 100644 --- a/src/libplybootsplash/ply-text-progress-bar.c +++ b/src/libplybootsplash/ply-text-progress-bar.c @@ -43,11 +43,11 @@ #include #include +#include "ply-text-display.h" #include "ply-text-progress-bar.h" #include "ply-array.h" #include "ply-logger.h" #include "ply-utils.h" -#include "ply-window.h" #include @@ -61,7 +61,7 @@ static char *os_string; struct _ply_text_progress_bar { - ply_window_t *window; + ply_text_display_t *display; int column, row; int number_of_rows; @@ -124,16 +124,15 @@ out: void ply_text_progress_bar_draw (ply_text_progress_bar_t *progress_bar) { - int i, width = progress_bar->number_of_columns - 2 - strlen(os_string); + int i, width = progress_bar->number_of_columns - 2 - strlen (os_string); double brown_fraction, blue_fraction, white_fraction; if (progress_bar->is_hidden) return; - ply_window_set_mode (progress_bar->window, PLY_WINDOW_MODE_TEXT); - ply_window_set_text_cursor_position(progress_bar->window, - progress_bar->column, - progress_bar->row); + ply_text_display_set_cursor_position (progress_bar->display, + progress_bar->column, + progress_bar->row); brown_fraction = - (progress_bar->percent_done * progress_bar->percent_done) + 2 * progress_bar->percent_done; blue_fraction = progress_bar->percent_done; @@ -144,56 +143,56 @@ ply_text_progress_bar_draw (ply_text_progress_bar_t *progress_bar) f = (double) i / (double) width; if (f < white_fraction) - ply_window_set_background_color (progress_bar->window, - PLY_WINDOW_COLOR_WHITE); + ply_text_display_set_background_color (progress_bar->display, + PLY_TERMINAL_COLOR_WHITE); else if (f < blue_fraction) - ply_window_set_background_color (progress_bar->window, - PLY_WINDOW_COLOR_BLUE); + ply_text_display_set_background_color (progress_bar->display, + PLY_TERMINAL_COLOR_BLUE); else if (f < brown_fraction) - ply_window_set_background_color (progress_bar->window, - PLY_WINDOW_COLOR_BROWN); + ply_text_display_set_background_color (progress_bar->display, + PLY_TERMINAL_COLOR_BROWN); else break; - write (STDOUT_FILENO, " ", strlen (" ")); + ply_text_display_write (progress_bar->display, "%c", ' '); } - ply_window_set_background_color (progress_bar->window, PLY_WINDOW_COLOR_BLACK); + ply_text_display_set_background_color (progress_bar->display, + PLY_TERMINAL_COLOR_BLACK); if (brown_fraction > 0.5) { if (white_fraction > 0.875) - ply_window_set_foreground_color (progress_bar->window, - PLY_WINDOW_COLOR_WHITE); + ply_text_display_set_foreground_color (progress_bar->display, + PLY_TERMINAL_COLOR_WHITE); else if (blue_fraction > 0.66) - ply_window_set_foreground_color (progress_bar->window, - PLY_WINDOW_COLOR_BLUE); + ply_text_display_set_foreground_color (progress_bar->display, + PLY_TERMINAL_COLOR_BLUE); else - ply_window_set_foreground_color (progress_bar->window, - PLY_WINDOW_COLOR_BROWN); + ply_text_display_set_foreground_color (progress_bar->display, + PLY_TERMINAL_COLOR_BROWN); - ply_window_set_text_cursor_position(progress_bar->window, - progress_bar->column + width, - progress_bar->row); + ply_text_display_set_cursor_position (progress_bar->display, + progress_bar->column + width, + progress_bar->row); + ply_text_display_write (progress_bar->display, "%s", os_string); - write (STDOUT_FILENO, os_string, strlen(os_string)); - - ply_window_set_foreground_color (progress_bar->window, - PLY_WINDOW_COLOR_DEFAULT); + ply_text_display_set_foreground_color (progress_bar->display, + PLY_TERMINAL_COLOR_DEFAULT); } } void ply_text_progress_bar_show (ply_text_progress_bar_t *progress_bar, - ply_window_t *window) + ply_text_display_t *display) { assert (progress_bar != NULL); - progress_bar->window = window; + progress_bar->display = display; - progress_bar->number_of_rows = ply_window_get_number_of_text_rows(window); + progress_bar->number_of_rows = ply_text_display_get_number_of_rows (display); progress_bar->row = progress_bar->number_of_rows - 1; - progress_bar->number_of_columns = ply_window_get_number_of_text_columns(window); + progress_bar->number_of_columns = ply_text_display_get_number_of_columns (display); progress_bar->column = 2; get_os_string (); @@ -206,7 +205,7 @@ ply_text_progress_bar_show (ply_text_progress_bar_t *progress_bar, void ply_text_progress_bar_hide (ply_text_progress_bar_t *progress_bar) { - progress_bar->window = NULL; + progress_bar->display = NULL; progress_bar->is_hidden = true; } diff --git a/src/libplybootsplash/ply-text-progress-bar.h b/src/libplybootsplash/ply-text-progress-bar.h index d3a43b66..ebf0644b 100644 --- a/src/libplybootsplash/ply-text-progress-bar.h +++ b/src/libplybootsplash/ply-text-progress-bar.h @@ -29,7 +29,7 @@ #include #include "ply-event-loop.h" -#include "ply-window.h" +#include "ply-text-display.h" typedef struct _ply_text_progress_bar ply_text_progress_bar_t; @@ -39,7 +39,7 @@ void ply_text_progress_bar_free (ply_text_progress_bar_t *progress_bar); void ply_text_progress_bar_draw (ply_text_progress_bar_t *progress_bar); void ply_text_progress_bar_show (ply_text_progress_bar_t *progress_bar, - ply_window_t *window); + ply_text_display_t *display); void ply_text_progress_bar_hide (ply_text_progress_bar_t *progress_bar); void ply_text_progress_bar_set_percent_done (ply_text_progress_bar_t *progress_bar, From 20b9f2e65b171337b6957cb4551a6e827df3f034 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 16:28:04 -0400 Subject: [PATCH 21/43] [details] Update to use new multihead interface --- src/plugins/splash/details/plugin.c | 314 ++++++++++++---------------- 1 file changed, 132 insertions(+), 182 deletions(-) diff --git a/src/plugins/splash/details/plugin.c b/src/plugins/splash/details/plugin.c index 5d37eaaf..25a3aa23 100644 --- a/src/plugins/splash/details/plugin.c +++ b/src/plugins/splash/details/plugin.c @@ -46,11 +46,10 @@ #include "ply-key-file.h" #include "ply-list.h" #include "ply-logger.h" -#include "ply-frame-buffer.h" #include "ply-image.h" +#include "ply-text-display.h" #include "ply-trigger.h" #include "ply-utils.h" -#include "ply-window.h" #include @@ -62,27 +61,66 @@ typedef enum { PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY } ply_boot_splash_display_type_t; - -typedef void (* ply_boot_splash_plugin_window_handler_t) (ply_window_t *window, ply_boot_splash_plugin_t *, void *user_data, void *other_user_data); - -static void uninitialize_window (ply_window_t *window, - ply_boot_splash_plugin_t *plugin); - -static void for_each_window (ply_boot_splash_plugin_t *plugin, - ply_boot_splash_plugin_window_handler_t handler, - void *user_data, - void *other_user_data); +typedef struct +{ + ply_boot_splash_plugin_t *plugin; + ply_text_display_t *display; +} view_t; ply_boot_splash_plugin_interface_t *ply_boot_splash_plugin_get_interface (void); struct _ply_boot_splash_plugin { ply_event_loop_t *loop; ply_boot_splash_mode_t mode; - ply_list_t *windows; + ply_list_t *views; ply_boot_splash_display_type_t state; }; +static view_t * +view_new (ply_boot_splash_plugin_t *plugin, + ply_text_display_t *display) +{ + view_t *view; + + view = calloc (1, sizeof (view_t)); + view->plugin = plugin; + view->display = display; + + return view; +} + +static void +view_free (view_t *view) +{ + free (view); +} + +static void +free_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_free (view); + ply_list_remove_node (plugin->views, node); + + node = next_node; + } + + ply_list_free (plugin->views); + plugin->views = NULL; +} + static ply_boot_splash_plugin_t * create_plugin (ply_key_file_t *key_file) { @@ -91,7 +129,7 @@ create_plugin (ply_key_file_t *key_file) ply_trace ("creating plugin"); plugin = calloc (1, sizeof (ply_boot_splash_plugin_t)); - plugin->windows = ply_list_new (); + plugin->views = ply_list_new (); plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL; return plugin; } @@ -104,11 +142,7 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin) if (plugin == NULL) return; - for_each_window (plugin, - (ply_boot_splash_plugin_window_handler_t) - uninitialize_window, NULL, NULL); - - ply_list_free (plugin->windows); + free_views (plugin); free (plugin); } @@ -122,103 +156,77 @@ detach_from_event_loop (ply_boot_splash_plugin_t *plugin) } static void -for_each_window (ply_boot_splash_plugin_t *plugin, - ply_boot_splash_plugin_window_handler_t handler, - void *user_data, - void *other_user_data) +view_write (view_t *view, + const char *text, + size_t number_of_bytes) +{ + ply_terminal_t *terminal; + + terminal = ply_text_display_get_terminal (view->display); + ply_terminal_write (terminal, "%.*s", (int) number_of_bytes, text); +} + +static void +write_on_views (ply_boot_splash_plugin_t *plugin, + const char *text, + size_t number_of_bytes) { ply_list_node_t *node; - node = ply_list_get_first_node (plugin->windows); + if (number_of_bytes == 0) + return; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { ply_list_node_t *next_node; - ply_window_t *window; + view_t *view; - next_node = ply_list_get_next_node (plugin->windows, node); + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); - window = ply_list_node_get_data (node); - - handler (window, plugin, user_data, other_user_data); + view_write (view, text, number_of_bytes); node = next_node; } + } static void -write_text_on_window (ply_window_t *window, - ply_boot_splash_plugin_t *plugin, - const char *text, - void *user_data) +add_text_display (ply_boot_splash_plugin_t *plugin, + ply_text_display_t *display) { - int fd; - size_t size; + view_t *view; - ply_window_set_mode (window, PLY_WINDOW_MODE_TEXT); + view = view_new (plugin, display); - size = (size_t) user_data; - - fd = ply_window_get_tty_fd (window); - - write (fd, text, size); -} - -void -on_keyboard_input (ply_boot_splash_plugin_t *plugin, - const char *keyboard_input, - size_t character_size) -{ -} - -void -on_backspace (ply_boot_splash_plugin_t *plugin) -{ -} - -void -on_enter (ply_boot_splash_plugin_t *plugin, - const char *line) -{ + ply_list_append_data (plugin->views, view); } static void -add_window (ply_boot_splash_plugin_t *plugin, - ply_window_t *window) +remove_text_display (ply_boot_splash_plugin_t *plugin, + ply_text_display_t *display) { - ply_list_append_data (plugin->windows, window); -} + ply_list_node_t *node; -static void -remove_window (ply_boot_splash_plugin_t *plugin, - ply_window_t *window) -{ - ply_list_remove_data (plugin->windows, window); -} + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; -static void -initialize_window (ply_window_t *window, - ply_boot_splash_plugin_t *plugin) -{ - ply_window_set_mode (window, PLY_WINDOW_MODE_TEXT); + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); - ply_window_add_keyboard_input_handler (window, - (ply_window_keyboard_input_handler_t) - on_keyboard_input, plugin); - ply_window_add_backspace_handler (window, - (ply_window_backspace_handler_t) - on_backspace, plugin); - ply_window_add_enter_handler (window, - (ply_window_enter_handler_t) - on_enter, plugin); -} + if (view->display == display) + { + ply_list_remove_node (plugin->views, node); + return; + } -static void -uninitialize_window (ply_window_t *window, - ply_boot_splash_plugin_t *plugin) -{ - ply_window_remove_keyboard_input_handler (window, (ply_window_keyboard_input_handler_t) on_keyboard_input); - ply_window_remove_backspace_handler (window, (ply_window_backspace_handler_t) on_backspace); - ply_window_remove_enter_handler (window, (ply_window_enter_handler_t) on_enter); + node = next_node; + } } static bool @@ -231,9 +239,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, assert (plugin != NULL); - for_each_window (plugin, - (ply_boot_splash_plugin_window_handler_t) - initialize_window, NULL, NULL); plugin->loop = loop; plugin->mode = mode; @@ -243,10 +248,7 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, size = ply_buffer_get_size (boot_buffer); - if (size > 0) - write (STDOUT_FILENO, - ply_buffer_get_bytes (boot_buffer), - size); + write_on_views (plugin, ply_buffer_get_bytes (boot_buffer), size); return true; } @@ -265,13 +267,9 @@ on_boot_output (ply_boot_splash_plugin_t *plugin, const char *output, size_t size) { - ply_trace ("writing '%s' to all windows (%d bytes)", + ply_trace ("writing '%s' to all views (%d bytes)", output, (int) size); - if (size > 0) - for_each_window (plugin, - (ply_boot_splash_plugin_window_handler_t) - write_text_on_window, - (void *) output, (void *) size); + write_on_views (plugin, output, size); } static void @@ -282,10 +280,6 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin, ply_trace ("hiding splash screen"); - for_each_window (plugin, - (ply_boot_splash_plugin_window_handler_t) - uninitialize_window, NULL, NULL); - ply_event_loop_stop_watching_for_exit (plugin->loop, (ply_event_loop_exit_handler_t) detach_from_event_loop, @@ -297,16 +291,11 @@ static void display_normal (ply_boot_splash_plugin_t *plugin) { if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_NORMAL) - { - for_each_window (plugin, - (ply_boot_splash_plugin_window_handler_t) - write_text_on_window, - (void *) "\r\n", (void *) strlen ("\r\n")); - } + write_on_views (plugin, "\r\n", strlen ("\r\n")); + plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL; } - static void display_password (ply_boot_splash_plugin_t *plugin, const char *prompt, @@ -314,46 +303,26 @@ display_password (ply_boot_splash_plugin_t *plugin, { int i; if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY) - { - for_each_window (plugin, - (ply_boot_splash_plugin_window_handler_t) - write_text_on_window, - (void *) "\r\n", (void *) strlen ("\r\n")); - } + write_on_views (plugin, "\r\n", strlen ("\r\n")); else - { - for_each_window (plugin, - (ply_boot_splash_plugin_window_handler_t) - write_text_on_window, - (void *) CLEAR_LINE_SEQUENCE, - (void *) strlen (CLEAR_LINE_SEQUENCE)); - } + write_on_views (plugin, + CLEAR_LINE_SEQUENCE, + strlen (CLEAR_LINE_SEQUENCE)); plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY; - - if (prompt) - for_each_window (plugin, - (ply_boot_splash_plugin_window_handler_t) - write_text_on_window, - (void *) prompt, - (void *) strlen (prompt)); - else - for_each_window (plugin, - (ply_boot_splash_plugin_window_handler_t) - write_text_on_window, - (void *) "Password", - (void *) strlen ("Password")); - for_each_window (plugin, - (ply_boot_splash_plugin_window_handler_t) - write_text_on_window, - (void *) ":", - (void *) strlen (":")); - for (i=0; istate != PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY) - { - for_each_window (plugin, - (ply_boot_splash_plugin_window_handler_t) - write_text_on_window, - (void *) "\r\n", (void *) strlen ("\r\n")); - } + write_on_views (plugin, "\r\n", strlen ("\r\n")); else - { - for_each_window (plugin, - (ply_boot_splash_plugin_window_handler_t) - write_text_on_window, - (void *) CLEAR_LINE_SEQUENCE, - (void *) strlen (CLEAR_LINE_SEQUENCE)); - } + write_on_views (plugin, + CLEAR_LINE_SEQUENCE, + strlen (CLEAR_LINE_SEQUENCE)); + plugin->state = PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY; if (prompt) - for_each_window (plugin, - (ply_boot_splash_plugin_window_handler_t) - write_text_on_window, - (void *) prompt, - (void *) strlen (prompt)); - for_each_window (plugin, - (ply_boot_splash_plugin_window_handler_t) - write_text_on_window, - (void *) ":", - (void *) strlen (":")); - for_each_window (plugin, - (ply_boot_splash_plugin_window_handler_t) - write_text_on_window, - (void *) entry_text, - (void *) strlen (entry_text)); + write_on_views (plugin, prompt, strlen (prompt)); + + write_on_views (plugin, ":", strlen (":")); + write_on_views (plugin, entry_text, strlen (entry_text)); } ply_boot_splash_plugin_interface_t * @@ -402,8 +352,8 @@ ply_boot_splash_plugin_get_interface (void) { .create_plugin = create_plugin, .destroy_plugin = destroy_plugin, - .add_window = add_window, - .remove_window = remove_window, + .add_text_display = add_text_display, + .remove_text_display = remove_text_display, .show_splash_screen = show_splash_screen, .update_status = update_status, .on_boot_output = on_boot_output, From b66fda6700f075661e759745405a1d7db42b3190 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 16:28:04 -0400 Subject: [PATCH 22/43] [fade-throbber] Update to use new multihead interface --- src/plugins/splash/fade-throbber/plugin.c | 876 +++++++++++++++------- 1 file changed, 608 insertions(+), 268 deletions(-) diff --git a/src/plugins/splash/fade-throbber/plugin.c b/src/plugins/splash/fade-throbber/plugin.c index 64403a4b..d89a562f 100644 --- a/src/plugins/splash/fade-throbber/plugin.c +++ b/src/plugins/splash/fade-throbber/plugin.c @@ -1,6 +1,6 @@ /* fade-throbber.c - boot splash plugin * - * Copyright (C) 2007, 2008 Red Hat, Inc. + * Copyright (C) 2007, 2008, 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 @@ -43,14 +43,15 @@ #include "ply-buffer.h" #include "ply-entry.h" #include "ply-event-loop.h" +#include "ply-label.h" #include "ply-list.h" #include "ply-logger.h" -#include "ply-frame-buffer.h" #include "ply-image.h" #include "ply-key-file.h" +#include "ply-pixel-buffer.h" +#include "ply-pixel-display.h" #include "ply-trigger.h" #include "ply-utils.h" -#include "ply-window.h" #include @@ -58,6 +59,7 @@ #define FRAMES_PER_SECOND 30 #endif + typedef enum { PLY_BOOT_SPLASH_DISPLAY_NORMAL, PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY, @@ -70,20 +72,30 @@ typedef struct unsigned int y; double start_time; double speed; + double opacity; } star_t; +typedef struct +{ + ply_boot_splash_plugin_t *plugin; + ply_pixel_display_t *display; + ply_list_t *stars; + ply_entry_t *entry; + ply_label_t *label; + ply_rectangle_t lock_area; +} view_t; + struct _ply_boot_splash_plugin { ply_event_loop_t *loop; ply_boot_splash_mode_t mode; - ply_frame_buffer_t *frame_buffer; ply_image_t *logo_image; ply_image_t *star_image; ply_image_t *lock_image; - ply_list_t *stars; - ply_window_t *window; + char *image_dir; + ply_list_t *views; + double logo_opacity; - ply_entry_t *entry; ply_boot_splash_display_type_t state; double start_time; @@ -92,6 +104,65 @@ struct _ply_boot_splash_plugin uint32_t is_animating : 1; }; +static void +view_show_prompt (view_t *view, + const char *prompt) +{ + ply_boot_splash_plugin_t *plugin; + int x, y; + int entry_width, entry_height; + + assert (view != NULL); + + plugin = view->plugin; + + if (ply_entry_is_hidden (view->entry)) + { + unsigned long screen_width, screen_height; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + view->lock_area.width = ply_image_get_width (plugin->lock_image); + view->lock_area.height = ply_image_get_height (plugin->lock_image); + + entry_width = ply_entry_get_width (view->entry); + entry_height = ply_entry_get_height (view->entry); + + x = screen_width / 2.0 - (view->lock_area.width + entry_width) / 2.0 + view->lock_area.width; + y = screen_height / 2.0 - entry_height / 2.0; + + view->lock_area.x = screen_width / 2.0 - (view->lock_area.width + entry_width) / 2.0; + view->lock_area.y = screen_height / 2.0 - view->lock_area.height / 2.0; + + ply_entry_show (view->entry, plugin->loop, view->display, x, y); + } + + if (prompt != NULL) + { + int label_width, label_height; + + ply_label_set_text (view->label, prompt); + label_width = ply_label_get_width (view->label); + label_height = ply_label_get_height (view->label); + + x = view->lock_area.x; + y = view->lock_area.y + view->lock_area.height; + + ply_label_show (view->label, view->display, x, y); + } +} + +static void +view_hide_prompt (view_t *view) +{ + assert (view != NULL); + + ply_entry_hide (view->entry); + ply_label_hide (view->label); +} + + static ply_boot_splash_plugin_t * create_plugin (ply_key_file_t *key_file) { @@ -113,16 +184,15 @@ create_plugin (ply_key_file_t *key_file) plugin->lock_image = ply_image_new (image_path); free (image_path); - plugin->entry = ply_entry_new (image_dir); - free (image_dir); + plugin->image_dir = image_dir; plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL; - plugin->stars = ply_list_new (); + plugin->views = ply_list_new (); return plugin; } -star_t * +static star_t * star_new (int x, int y, double speed) @@ -145,13 +215,13 @@ star_free (star_t *star) } static void -free_stars (ply_boot_splash_plugin_t *plugin) +free_stars (view_t *view) { ply_list_node_t *node; - assert (plugin != NULL); + assert (view != NULL); - node = ply_list_get_first_node (plugin->stars); + node = ply_list_get_first_node (view->stars); while (node != NULL) { ply_list_node_t *next_node; @@ -159,29 +229,184 @@ free_stars (ply_boot_splash_plugin_t *plugin) star = (star_t *) ply_list_node_get_data (node); - next_node = ply_list_get_next_node (plugin->stars, node); + next_node = ply_list_get_next_node (view->stars, node); star_free (star); node = next_node; } - ply_list_free (plugin->stars); - plugin->stars = NULL; + ply_list_free (view->stars); + view->stars = NULL; } -static void add_handlers (ply_boot_splash_plugin_t *plugin); -static void remove_handlers (ply_boot_splash_plugin_t *plugin); - static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin); +static view_t * +view_new (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) +{ + view_t *view; + + view = calloc (1, sizeof (view_t)); + view->plugin = plugin; + view->display = display; + + view->entry = ply_entry_new (plugin->image_dir); + view->stars = ply_list_new (); + view->label = ply_label_new (); + + return view; +} + +static void +view_free (view_t *view) +{ + + ply_entry_free (view->entry); + free_stars (view); + + free (view); +} + +static bool +view_load (view_t *view) +{ + ply_trace ("loading entry"); + if (!ply_entry_load (view->entry)) + return false; + + return true; +} + +static bool +load_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + bool view_loaded; + + view_loaded = false; + node = ply_list_get_first_node (plugin->views); + + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view_load (view)) + view_loaded = true; + + node = next_node; + } + + return view_loaded; +} + +static void +view_redraw (view_t *view) +{ + unsigned long screen_width, screen_height; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + ply_pixel_display_draw_area (view->display, 0, 0, + screen_width, screen_height); +} + +static void +redraw_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_redraw (view); + + node = next_node; + } +} + +static void +pause_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_pixel_display_pause_updates (view->display); + + node = next_node; + } +} + +static void +unpause_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_pixel_display_unpause_updates (view->display); + + node = next_node; + } +} + +static void +free_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_free (view); + ply_list_remove_node (plugin->views, node); + + node = next_node; + } + + ply_list_free (plugin->views); + plugin->views = NULL; +} + static void destroy_plugin (ply_boot_splash_plugin_t *plugin) { if (plugin == NULL) return; - remove_handlers (plugin); - if (plugin->loop != NULL) { ply_event_loop_stop_watching_for_exit (plugin->loop, (ply_event_loop_exit_handler_t) @@ -190,28 +415,74 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin) detach_from_event_loop (plugin); } - free_stars (plugin); + free_views (plugin); ply_image_free (plugin->logo_image); ply_image_free (plugin->star_image); ply_image_free (plugin->lock_image); - ply_entry_free (plugin->entry); free (plugin); } static void -draw_background (ply_boot_splash_plugin_t *plugin, - ply_frame_buffer_area_t *area) +view_animate_at_time (view_t *view, + double time) { - ply_frame_buffer_area_t screen_area; + ply_boot_splash_plugin_t *plugin; + ply_list_node_t *node; + double logo_opacity; + uint32_t *logo_data, *star_data; + long logo_x, logo_y; + long logo_width, logo_height; + unsigned long screen_width, screen_height; + unsigned long star_width, star_height; - if (area == NULL) + plugin = view->plugin; + + logo_width = ply_image_get_width (plugin->logo_image); + logo_height = ply_image_get_height (plugin->logo_image); + logo_data = ply_image_get_data (plugin->logo_image); + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + logo_x = (screen_width / 2) - (logo_width / 2); + logo_y = (screen_height / 2) - (logo_height / 2); + + star_data = ply_image_get_data (plugin->star_image); + star_width = ply_image_get_width (plugin->star_image); + star_height = ply_image_get_height (plugin->star_image); + + node = ply_list_get_first_node (view->stars); + while (node != NULL) { - ply_frame_buffer_get_size (plugin->frame_buffer, &screen_area); - area = &screen_area; + ply_list_node_t *next_node; + star_t *star; + + star = (star_t *) ply_list_node_get_data (node); + next_node = ply_list_get_next_node (view->stars, node); + + star->opacity = .5 * sin (((plugin->now - star->start_time) / star->speed) * (2 * M_PI)) + .5; + star->opacity = CLAMP (star->opacity, 0, 1.0); + + ply_pixel_display_draw_area (view->display, + star->x, star->y, + star_width, star_height); + node = next_node; } - ply_window_erase_area (plugin->window, area->x, area->y, - area->width, area->height); + logo_opacity = .5 * sin ((time / 5) * (2 * M_PI)) + .8; + logo_opacity = CLAMP (logo_opacity, 0, 1.0); + + if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN) + logo_opacity = 1.0; + + if (fabs (logo_opacity - plugin->logo_opacity) <= DBL_MIN) + return; + + plugin->logo_opacity = logo_opacity; + + ply_pixel_display_draw_area (view->display, + logo_x, logo_y, + logo_width, logo_height); } static void @@ -219,71 +490,20 @@ animate_at_time (ply_boot_splash_plugin_t *plugin, double time) { ply_list_node_t *node; - ply_frame_buffer_area_t logo_area, star_area; - uint32_t *logo_data, *star_data; - long width, height; - static double last_opacity = 0.0; - double opacity = 0.0; - ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS); - - ply_frame_buffer_pause_updates (plugin->frame_buffer); - - width = ply_image_get_width (plugin->logo_image); - height = ply_image_get_height (plugin->logo_image); - logo_data = ply_image_get_data (plugin->logo_image); - ply_frame_buffer_get_size (plugin->frame_buffer, &logo_area); - logo_area.x = (logo_area.width / 2) - (width / 2); - logo_area.y = (logo_area.height / 2) - (height / 2); - logo_area.width = width; - logo_area.height = height; - - star_data = ply_image_get_data (plugin->star_image); - star_area.width = ply_image_get_width (plugin->star_image); - star_area.height = ply_image_get_height (plugin->star_image); - - node = ply_list_get_first_node (plugin->stars); + node = ply_list_get_first_node (plugin->views); while (node != NULL) { ply_list_node_t *next_node; - star_t *star; + view_t *view; - star = (star_t *) ply_list_node_get_data (node); - next_node = ply_list_get_next_node (plugin->stars, node); + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); - star_area.x = star->x; - star_area.y = star->y; - - opacity = .5 * sin (((plugin->now - star->start_time) / star->speed) * (2 * M_PI)) + .5; - opacity = CLAMP (opacity, 0, 1.0); - - draw_background (plugin, &star_area); - ply_frame_buffer_fill_with_argb32_data_at_opacity (plugin->frame_buffer, - &star_area, 0, 0, - star_data, opacity); + view_animate_at_time (view, time); node = next_node; } - - opacity = .5 * sin ((time / 5) * (2 * M_PI)) + .8; - opacity = CLAMP (opacity, 0, 1.0); - - if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN) - opacity = 1.0; - - if (fabs (opacity - last_opacity) <= DBL_MIN) - { - ply_frame_buffer_unpause_updates (plugin->frame_buffer); - return; - } - - last_opacity = opacity; - - draw_background (plugin, &logo_area); - ply_frame_buffer_fill_with_argb32_data_at_opacity (plugin->frame_buffer, - &logo_area, 0, 0, - logo_data, opacity); - ply_frame_buffer_unpause_updates (plugin->frame_buffer); } static void @@ -291,7 +511,6 @@ on_timeout (ply_boot_splash_plugin_t *plugin) { double sleep_time; - ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS); plugin->now = ply_get_timestamp (); /* The choice below is between @@ -326,15 +545,25 @@ on_timeout (ply_boot_splash_plugin_t *plugin) } static void -start_animation (ply_boot_splash_plugin_t *plugin) +view_start_animation (view_t *view) { - assert (plugin != NULL); + ply_boot_splash_plugin_t *plugin; + unsigned long screen_width, screen_height; + + assert (view != NULL); + + plugin = view->plugin; + assert (plugin->loop != NULL); - + if (plugin->is_animating) return; - draw_background (plugin, NULL); + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + ply_pixel_display_draw_area (view->display, 0, 0, + screen_width, screen_height); plugin->start_time = ply_get_timestamp (); animate_at_time (plugin, plugin->start_time); @@ -350,11 +579,34 @@ start_animation (ply_boot_splash_plugin_t *plugin) plugin->is_animating = true; } +static void +start_animation (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + if (plugin->is_animating) + return; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_start_animation (view); + + node = next_node; + } + + plugin->is_animating = true; +} + static void stop_animation (ply_boot_splash_plugin_t *plugin) { - int i; - assert (plugin != NULL); assert (plugin->loop != NULL); @@ -363,32 +615,13 @@ stop_animation (ply_boot_splash_plugin_t *plugin) plugin->is_animating = false; - for (i = 0; i < 10; i++) - { - ply_frame_buffer_fill_with_hex_color_at_opacity (plugin->frame_buffer, - NULL, - PLYMOUTH_BACKGROUND_COLOR, - .1 + .1 * i); - } - - ply_frame_buffer_fill_with_hex_color (plugin->frame_buffer, NULL, - PLYMOUTH_BACKGROUND_COLOR); - - for (i = 0; i < 20; i++) - { - ply_frame_buffer_fill_with_color (plugin->frame_buffer, NULL, - 0.0, 0.0, 0.0, .05 + .05 * i); - } - - ply_frame_buffer_fill_with_color (plugin->frame_buffer, NULL, - 0.0, 0.0, 0.0, 1.0); - if (plugin->loop != NULL) { ply_event_loop_stop_watching_for_timeout (plugin->loop, (ply_event_loop_timeout_handler_t) on_timeout, plugin); } + redraw_views (plugin); } static void @@ -396,121 +629,188 @@ on_interrupt (ply_boot_splash_plugin_t *plugin) { ply_event_loop_exit (plugin->loop, 1); stop_animation (plugin); - ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT); } static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin) { plugin->loop = NULL; - - ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT); } -void -on_keyboard_input (ply_boot_splash_plugin_t *plugin, - const char *keyboard_input, - size_t character_size) +static void +draw_background (view_t *view, + ply_pixel_buffer_t *pixel_buffer, + int x, + int y, + int width, + int height) { -} + ply_boot_splash_plugin_t *plugin; + ply_rectangle_t area; -void -on_backspace (ply_boot_splash_plugin_t *plugin) -{ -} - -void -on_enter (ply_boot_splash_plugin_t *plugin, - const char *text) -{ -} - -void -on_draw (ply_boot_splash_plugin_t *plugin, - int x, - int y, - int width, - int height) -{ - ply_frame_buffer_area_t area; + plugin = view->plugin; area.x = x; area.y = y; area.width = width; area.height = height; - draw_background (plugin, &area); - - if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) - animate_at_time (plugin, plugin->now); - else - ply_entry_draw (plugin->entry); -} - -void -on_erase (ply_boot_splash_plugin_t *plugin, - int x, - int y, - int width, - int height) -{ - ply_frame_buffer_area_t area; - - area.x = x; - area.y = y; - area.width = width; - area.height = height; - - ply_frame_buffer_fill_with_gradient (plugin->frame_buffer, &area, + ply_pixel_buffer_fill_with_gradient (pixel_buffer, &area, PLYMOUTH_BACKGROUND_START_COLOR, PLYMOUTH_BACKGROUND_END_COLOR); } static void -add_handlers (ply_boot_splash_plugin_t *plugin) +draw_normal_view (view_t *view, + ply_pixel_buffer_t *pixel_buffer, + int x, + int y, + int width, + int height) { - ply_window_add_keyboard_input_handler (plugin->window, - (ply_window_keyboard_input_handler_t) - on_keyboard_input, plugin); - ply_window_add_backspace_handler (plugin->window, - (ply_window_backspace_handler_t) - on_backspace, plugin); - ply_window_add_enter_handler (plugin->window, - (ply_window_enter_handler_t) - on_enter, plugin); + ply_boot_splash_plugin_t *plugin; + ply_list_node_t *node; + ply_rectangle_t logo_area; + ply_rectangle_t star_area; + uint32_t *logo_data, *star_data; + unsigned long screen_width, screen_height; - ply_window_set_draw_handler (plugin->window, - (ply_window_draw_handler_t) - on_draw, plugin); + plugin = view->plugin; - ply_window_set_erase_handler (plugin->window, - (ply_window_erase_handler_t) - on_erase, plugin); + logo_area.width = ply_image_get_width (plugin->logo_image); + logo_area.height = ply_image_get_height (plugin->logo_image); + logo_data = ply_image_get_data (plugin->logo_image); + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + logo_area.x = (screen_width / 2) - (logo_area.width / 2); + logo_area.y = (screen_height / 2) - (logo_area.height / 2); + + star_data = ply_image_get_data (plugin->star_image); + star_area.width = ply_image_get_width (plugin->star_image); + star_area.height = ply_image_get_height (plugin->star_image); + + node = ply_list_get_first_node (view->stars); + while (node != NULL) + { + ply_list_node_t *next_node; + star_t *star; + + star = (star_t *) ply_list_node_get_data (node); + next_node = ply_list_get_next_node (view->stars, node); + + star_area.x = star->x; + star_area.y = star->y; + ply_pixel_buffer_fill_with_argb32_data_at_opacity (pixel_buffer, + &star_area, 0, 0, + star_data, + star->opacity); + node = next_node; + } + + ply_pixel_buffer_fill_with_argb32_data_at_opacity (pixel_buffer, + &logo_area, 0, 0, + logo_data, + plugin->logo_opacity); } static void -remove_handlers (ply_boot_splash_plugin_t *plugin) +draw_prompt_view (view_t *view, + ply_pixel_buffer_t *pixel_buffer, + int x, + int y, + int width, + int height) { + ply_boot_splash_plugin_t *plugin; + uint32_t *lock_data; - ply_window_remove_keyboard_input_handler (plugin->window, (ply_window_keyboard_input_handler_t) on_keyboard_input); - ply_window_remove_backspace_handler (plugin->window, (ply_window_backspace_handler_t) on_backspace); - ply_window_remove_enter_handler (plugin->window, (ply_window_enter_handler_t) on_enter); - ply_window_set_draw_handler (plugin->window, NULL, NULL); - ply_window_set_erase_handler (plugin->window, NULL, NULL); + plugin = view->plugin; + + ply_entry_draw_area (view->entry, + pixel_buffer, + x, y, width, height); + ply_label_draw_area (view->label, + pixel_buffer, + x, y, width, height); + + lock_data = ply_image_get_data (plugin->lock_image); + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, + &view->lock_area, 0, 0, + lock_data); } static void -add_window (ply_boot_splash_plugin_t *plugin, - ply_window_t *window) +on_draw (view_t *view, + ply_pixel_buffer_t *pixel_buffer, + int x, + int y, + int width, + int height) { - plugin->window = window; + ply_boot_splash_plugin_t *plugin; + ply_rectangle_t area; + + plugin = view->plugin; + + area.x = x; + area.y = y; + area.width = width; + area.height = height; + + draw_background (view, pixel_buffer, x, y, width, height); + + if (!plugin->is_animating) + return; + + if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) + draw_normal_view (view, pixel_buffer, x, y, width, height); + else + draw_prompt_view (view, pixel_buffer, x, y, width, height); } static void -remove_window (ply_boot_splash_plugin_t *plugin, - ply_window_t *window) +add_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) { - plugin->window = NULL; + view_t *view; + + view = view_new (plugin, display); + + ply_pixel_display_set_draw_handler (view->display, + (ply_pixel_display_draw_handler_t) + on_draw, view); + + ply_list_append_data (plugin->views, view); +} + +static void +remove_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; + + view = ply_list_node_get_data (node); + 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; + } + + node = next_node; + } } static bool @@ -522,8 +822,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, assert (plugin != NULL); assert (plugin->logo_image != NULL); - add_handlers (plugin); - plugin->loop = loop; plugin->mode = mode; @@ -539,16 +837,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, if (!ply_image_load (plugin->lock_image)) return false; - ply_trace ("loading entry"); - if (!ply_entry_load (plugin->entry)) - return false; - - ply_trace ("setting graphics mode"); - if (!ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS)) - return false; - - plugin->frame_buffer = ply_window_get_frame_buffer (plugin->window); - ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) detach_from_event_loop, plugin); @@ -557,8 +845,11 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, (ply_event_handler_t) on_interrupt, plugin); - ply_window_clear_screen (plugin->window); - ply_window_hide_text_cursor (plugin->window); + if (!load_views (plugin)) + { + ply_trace ("couldn't load views"); + return false; + } ply_trace ("starting boot animation"); start_animation (plugin); @@ -567,21 +858,26 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, } static void -add_star (ply_boot_splash_plugin_t *plugin) +view_add_star (view_t *view) { - ply_frame_buffer_area_t area, logo_area; + ply_boot_splash_plugin_t *plugin; + ply_rectangle_t logo_area; star_t *star; unsigned int x, y; unsigned int width, height; + unsigned long screen_width, screen_height; ply_list_node_t *node; - assert (plugin != NULL); + assert (view != NULL); - ply_frame_buffer_get_size (plugin->frame_buffer, &area); + plugin = view->plugin; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); width = ply_image_get_width (plugin->logo_image); height = ply_image_get_height (plugin->logo_image); - logo_area.x = (area.width / 2) - (width / 2); - logo_area.y = (area.height / 2) - (height / 2); + logo_area.x = (screen_width / 2) - (width / 2); + logo_area.y = (screen_height / 2) - (height / 2); logo_area.width = width; logo_area.height = height; @@ -591,8 +887,8 @@ add_star (ply_boot_splash_plugin_t *plugin) node = NULL; do { - x = rand () % area.width; - y = rand () % area.height; + x = rand () % screen_width; + y = rand () % screen_height; if ((x <= logo_area.x + logo_area.width) && (x >= logo_area.x) @@ -606,13 +902,13 @@ add_star (ply_boot_splash_plugin_t *plugin) && (y + height <= logo_area.y + logo_area.height)) continue; - node = ply_list_get_first_node (plugin->stars); + node = ply_list_get_first_node (view->stars); while (node != NULL) { ply_list_node_t *next_node; star = (star_t *) ply_list_node_get_data (node); - next_node = ply_list_get_next_node (plugin->stars, node); + next_node = ply_list_get_next_node (view->stars, node); if ((x <= star->x + width) && (x >= star->x) @@ -632,7 +928,27 @@ add_star (ply_boot_splash_plugin_t *plugin) } while (node != NULL); star = star_new (x, y, (double) ((rand () % 50) + 1)); - ply_list_append_data (plugin->stars, star); + ply_list_append_data (view->stars, star); +} + +static void +add_stars (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_add_star (view); + + node = next_node; + } } static void @@ -641,7 +957,7 @@ update_status (ply_boot_splash_plugin_t *plugin, { assert (plugin != NULL); - add_star (plugin); + add_stars (plugin); } static void @@ -650,8 +966,6 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin, { assert (plugin != NULL); - remove_handlers (plugin); - if (plugin->loop != NULL) { stop_animation (plugin); @@ -661,63 +975,87 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin, plugin); detach_from_event_loop (plugin); } - - plugin->frame_buffer = NULL; - - ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT); } static void -show_password_entry (ply_boot_splash_plugin_t *plugin) +show_password_prompt (ply_boot_splash_plugin_t *plugin, + const char *text, + int number_of_bullets) { - ply_frame_buffer_area_t area; - ply_frame_buffer_area_t lock_area; - int x, y; - int entry_width, entry_height; - uint32_t *lock_data; + ply_list_node_t *node; - assert (plugin != NULL); - - if (ply_entry_is_hidden (plugin->entry)) + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { - draw_background (plugin, NULL); + ply_list_node_t *next_node; + view_t *view; - ply_frame_buffer_get_size (plugin->frame_buffer, &area); + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); - entry_width = ply_entry_get_width (plugin->entry); - entry_height = ply_entry_get_height (plugin->entry); + view_show_prompt (view, text); + ply_entry_set_bullet_count (view->entry, number_of_bullets); - lock_area.width = ply_image_get_width (plugin->lock_image); - lock_area.height = ply_image_get_height (plugin->lock_image); - lock_area.x = area.width / 2.0 - (lock_area.width + entry_width) / 2.0; - lock_area.y = area.height / 2.0 - lock_area.height / 2.0; - - x = area.width / 2.0 - (lock_area.width + entry_width) / 2.0 + lock_area.width; - y = area.height / 2.0 - entry_height / 2.0; - - ply_entry_show (plugin->entry, plugin->loop, plugin->window, x, y); - - lock_data = ply_image_get_data (plugin->lock_image); - ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer, - &lock_area, 0, 0, - lock_data); + node = next_node; } - else +} + +static void +show_prompt (ply_boot_splash_plugin_t *plugin, + const char *prompt, + const char *entry_text) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { - ply_entry_draw (plugin->entry); + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_show_prompt (view, prompt); + ply_entry_set_text (view->entry, entry_text); + + node = next_node; + } +} + +static void +hide_prompt (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_hide_prompt (view); + + node = next_node; } } static void display_normal (ply_boot_splash_plugin_t *plugin) { + pause_views (plugin); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY || plugin->state == PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY) { plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL; - ply_entry_hide (plugin->entry); - start_animation(plugin); + hide_prompt (plugin); + start_animation (plugin); + redraw_views (plugin); } + unpause_views (plugin); } static void @@ -725,13 +1063,14 @@ display_password (ply_boot_splash_plugin_t *plugin, const char *prompt, int bullets) { + pause_views (plugin); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) - { - stop_animation (plugin); - } + stop_animation (plugin); + plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY; - show_password_entry (plugin); - ply_entry_set_bullet_count (plugin->entry, bullets); + show_password_prompt (plugin, prompt, bullets); + redraw_views (plugin); + unpause_views (plugin); } static void @@ -739,16 +1078,17 @@ display_question (ply_boot_splash_plugin_t *plugin, const char *prompt, const char *entry_text) { + pause_views (plugin); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) - { - stop_animation (plugin); - } + stop_animation (plugin); plugin->state = PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY; - show_password_entry (plugin); - ply_entry_set_text (plugin->entry, entry_text); + show_prompt (plugin, prompt, entry_text); + redraw_views (plugin); + unpause_views (plugin); } + ply_boot_splash_plugin_interface_t * ply_boot_splash_plugin_get_interface (void) { @@ -756,8 +1096,8 @@ ply_boot_splash_plugin_get_interface (void) { .create_plugin = create_plugin, .destroy_plugin = destroy_plugin, - .add_window = add_window, - .remove_window = remove_window, + .add_pixel_display = add_pixel_display, + .remove_pixel_display = remove_pixel_display, .show_splash_screen = show_splash_screen, .update_status = update_status, .hide_splash_screen = hide_splash_screen, From 5d0a49bc1929388c65413c5e000d2fcda89a323a Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 16:28:04 -0400 Subject: [PATCH 23/43] [script] Update to use new multihead interface --- src/plugins/splash/script/plugin.c | 528 +++++++++++++----- src/plugins/splash/script/script-lib-sprite.c | 66 +-- src/plugins/splash/script/script-lib-sprite.h | 13 +- 3 files changed, 434 insertions(+), 173 deletions(-) diff --git a/src/plugins/splash/script/plugin.c b/src/plugins/splash/script/plugin.c index 1a34efab..84915e74 100644 --- a/src/plugins/splash/script/plugin.c +++ b/src/plugins/splash/script/plugin.c @@ -49,11 +49,10 @@ #include "ply-label.h" #include "ply-list.h" #include "ply-logger.h" -#include "ply-frame-buffer.h" #include "ply-image.h" +#include "ply-pixel-display.h" #include "ply-trigger.h" #include "ply-utils.h" -#include "ply-window.h" #include "script.h" #include "script-parse.h" @@ -70,32 +69,120 @@ #define FRAMES_PER_SECOND 50 #endif -struct _ply_boot_splash_plugin +typedef struct { - ply_event_loop_t *loop; - ply_boot_splash_mode_t mode; - ply_frame_buffer_t *frame_buffer; - ply_window_t *window; - - char *script_filename; - char *image_dir; + ply_boot_splash_plugin_t *plugin; + ply_pixel_display_t *display; script_state_t *script_state; - script_op_t *script_main_op; script_lib_sprite_data_t *script_sprite_lib; script_lib_image_data_t *script_image_lib; script_lib_plymouth_data_t *script_plymouth_lib; script_lib_math_data_t *script_math_lib; +} view_t; + +struct _ply_boot_splash_plugin +{ + ply_event_loop_t *loop; + ply_boot_splash_mode_t mode; + ply_list_t *views; + + char *script_filename; + char *image_dir; + + script_op_t *script_main_op; uint32_t is_animating : 1; }; -static void add_handlers (ply_boot_splash_plugin_t *plugin); -static void remove_handlers (ply_boot_splash_plugin_t *plugin); static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin); static void stop_animation (ply_boot_splash_plugin_t *plugin); ply_boot_splash_plugin_interface_t *ply_boot_splash_plugin_get_interface (void); +static view_t * +view_new (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) +{ + view_t *view; + + view = calloc (1, sizeof (view_t)); + view->plugin = plugin; + view->display = display; + + return view; +} + +static void +view_free (view_t *view) +{ + free (view); +} + +static void +pause_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_pixel_display_pause_updates (view->display); + + node = next_node; + } +} + +static void +unpause_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_pixel_display_unpause_updates (view->display); + + node = next_node; + } +} + +static void +free_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_free (view); + ply_list_remove_node (plugin->views, node); + + node = next_node; + } + + ply_list_free (plugin->views); + plugin->views = NULL; +} + static ply_boot_splash_plugin_t * create_plugin (ply_key_file_t *key_file) { @@ -105,6 +192,7 @@ create_plugin (ply_key_file_t *key_file) plugin->script_filename = ply_key_file_get_value (key_file, "script", "ScriptFile"); + plugin->views = ply_list_new (); return plugin; } @@ -113,7 +201,6 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin) { if (plugin == NULL) return; - remove_handlers (plugin); if (plugin->loop != NULL) { @@ -124,27 +211,30 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin) plugin); detach_from_event_loop (plugin); } + + free_views (plugin); free (plugin->script_filename); free (plugin->image_dir); free (plugin); } static void -on_timeout (ply_boot_splash_plugin_t *plugin) +on_timeout (view_t *view) { + ply_boot_splash_plugin_t *plugin; double sleep_time; - ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS); + plugin = view->plugin; - script_lib_plymouth_on_refresh (plugin->script_state, - plugin->script_plymouth_lib); - script_lib_sprite_refresh (plugin->script_sprite_lib); + script_lib_plymouth_on_refresh (view->script_state, + view->script_plymouth_lib); + script_lib_sprite_refresh (view->script_sprite_lib); sleep_time = 1.0 / FRAMES_PER_SECOND; ply_event_loop_watch_for_timeout (plugin->loop, sleep_time, (ply_event_loop_timeout_handler_t) - on_timeout, plugin); + on_timeout, view); } static void @@ -152,63 +242,128 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin, double duration, double percent_done) { - script_lib_plymouth_on_boot_progress (plugin->script_state, - plugin->script_plymouth_lib, - duration, - percent_done); + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + script_lib_plymouth_on_boot_progress (view->script_state, + view->script_plymouth_lib, + duration, + percent_done); + node = next_node; + } +} + +static bool +view_start_animation (view_t *view) +{ + ply_boot_splash_plugin_t *plugin; + + assert (view != NULL); + + plugin = view->plugin; + + view->script_state = script_state_new (view); + view->script_image_lib = script_lib_image_setup (view->script_state, + plugin->image_dir); + view->script_sprite_lib = script_lib_sprite_setup (view->script_state, + view->display); + view->script_plymouth_lib = script_lib_plymouth_setup (view->script_state, + plugin->mode); + view->script_math_lib = script_lib_math_setup (view->script_state); + + ply_trace ("executing script file"); + script_return_t ret = script_execute (view->script_state, + plugin->script_main_op); + script_obj_unref (ret.object); + on_timeout (view); + + return true; } static bool start_animation (ply_boot_splash_plugin_t *plugin) { - ply_frame_buffer_area_t area; + ply_list_node_t *node; assert (plugin != NULL); assert (plugin->loop != NULL); if (plugin->is_animating) return true; - ply_frame_buffer_get_size (plugin->frame_buffer, &area); ply_trace ("parsing script file"); plugin->script_main_op = script_parse_file (plugin->script_filename); - plugin->script_state = script_state_new (plugin); - plugin->script_image_lib = script_lib_image_setup (plugin->script_state, - plugin->image_dir); - plugin->script_sprite_lib = script_lib_sprite_setup (plugin->script_state, - plugin->window); - plugin->script_plymouth_lib = script_lib_plymouth_setup (plugin->script_state, - plugin->mode); - plugin->script_math_lib = script_lib_math_setup (plugin->script_state); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; - ply_trace ("executing script file"); - script_return_t ret = script_execute (plugin->script_state, - plugin->script_main_op); - script_obj_unref (ret.object); - on_timeout (plugin); + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_start_animation (view); + + node = next_node; + } plugin->is_animating = true; return true; } +static void +view_stop_animation (view_t *view) +{ + ply_boot_splash_plugin_t *plugin; + + plugin = view->plugin; + + if (plugin->loop != NULL) + ply_event_loop_stop_watching_for_timeout (plugin->loop, + (ply_event_loop_timeout_handler_t) + on_timeout, view); + + script_state_destroy (view->script_state); + script_lib_sprite_destroy (view->script_sprite_lib); + script_lib_image_destroy (view->script_image_lib); + script_lib_plymouth_destroy (view->script_plymouth_lib); + script_lib_math_destroy (view->script_math_lib); +} + static void stop_animation (ply_boot_splash_plugin_t *plugin) { + ply_list_node_t *node; + assert (plugin != NULL); assert (plugin->loop != NULL); if (!plugin->is_animating) return; plugin->is_animating = false; - if (plugin->loop != NULL) - ply_event_loop_stop_watching_for_timeout (plugin->loop, - (ply_event_loop_timeout_handler_t) - on_timeout, plugin); - script_state_destroy (plugin->script_state); - script_lib_sprite_destroy (plugin->script_sprite_lib); - script_lib_image_destroy (plugin->script_image_lib); - script_lib_plymouth_destroy (plugin->script_plymouth_lib); - script_lib_math_destroy (plugin->script_math_lib); + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_stop_animation (view); + + node = next_node; + } + script_parse_op_free (plugin->script_main_op); } @@ -217,7 +372,6 @@ on_interrupt (ply_boot_splash_plugin_t *plugin) { ply_event_loop_exit (plugin->loop, 1); stop_animation (plugin); - ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT); } static void @@ -232,80 +386,105 @@ on_keyboard_input (ply_boot_splash_plugin_t *plugin, size_t character_size) { char keyboard_string[character_size + 1]; + ply_list_node_t *node; memcpy (keyboard_string, keyboard_input, character_size); keyboard_string[character_size] = '\0'; - script_lib_plymouth_on_keyboard_input (plugin->script_state, - plugin->script_plymouth_lib, - keyboard_string); + /* FIXME: Not sure what to do here. We don't want to feed + * the input once per monitor, I don't think, so we just call + * it on the first available monitor. + * + * I'm not even sure it's useful for scripts to be able to access + * this, but if it is we probably need to encode view awareness + * into the script api somehow. + */ + node = ply_list_get_first_node (plugin->views); + + if (node != NULL) + { + view_t *view; + view = (view_t *) ply_list_node_get_data (node); + + script_lib_plymouth_on_keyboard_input (view->script_state, + view->script_plymouth_lib, + keyboard_string); + } } static void -on_backspace (ply_boot_splash_plugin_t *plugin) -{} - -static void -on_enter (ply_boot_splash_plugin_t *plugin, - const char *text) -{} - -static void -on_draw (ply_boot_splash_plugin_t *plugin, +on_draw (view_t *view, + ply_pixel_buffer_t *pixel_buffer, int x, int y, int width, int height) -{} - -static void -on_erase (ply_boot_splash_plugin_t *plugin, - int x, - int y, - int width, - int height) -{} - -static void -add_handlers (ply_boot_splash_plugin_t *plugin) { - ply_window_add_keyboard_input_handler (plugin->window, - (ply_window_keyboard_input_handler_t) - on_keyboard_input, plugin); - ply_window_add_backspace_handler (plugin->window, - (ply_window_backspace_handler_t) - on_backspace, plugin); - ply_window_add_enter_handler (plugin->window, - (ply_window_enter_handler_t) - on_enter, plugin); - ply_window_set_draw_handler (plugin->window, - (ply_window_draw_handler_t) - on_draw, plugin); - ply_window_set_erase_handler (plugin->window, - (ply_window_erase_handler_t) - on_erase, plugin); + script_lib_sprite_draw_area (view->script_sprite_lib, + pixel_buffer, + x, y, width, height); } static void -remove_handlers (ply_boot_splash_plugin_t *plugin) +set_keyboard (ply_boot_splash_plugin_t *plugin, + ply_keyboard_t *keyboard) { - ply_window_remove_keyboard_input_handler (plugin->window, (ply_window_keyboard_input_handler_t) on_keyboard_input); - ply_window_remove_backspace_handler (plugin->window, (ply_window_backspace_handler_t) on_backspace); - ply_window_remove_enter_handler (plugin->window, (ply_window_enter_handler_t) on_enter); + + ply_keyboard_add_input_handler (keyboard, + (ply_keyboard_input_handler_t) + on_keyboard_input, plugin); } static void -add_window (ply_boot_splash_plugin_t *plugin, - ply_window_t *window) +unset_keyboard (ply_boot_splash_plugin_t *plugin, + ply_keyboard_t *keyboard) { - plugin->window = window; + ply_keyboard_remove_input_handler (keyboard, + (ply_keyboard_input_handler_t) + on_keyboard_input); } static void -remove_window (ply_boot_splash_plugin_t *plugin, - ply_window_t *window) +add_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) { - plugin->window = NULL; + view_t *view; + + view = view_new (plugin, display); + + ply_pixel_display_set_draw_handler (view->display, + (ply_pixel_display_draw_handler_t) + on_draw, view); + + ply_list_append_data (plugin->views, view); +} + +static void +remove_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; + + view = ply_list_node_get_data (node); + 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; + } + + node = next_node; + } } static bool @@ -316,13 +495,9 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, { assert (plugin != NULL); - add_handlers (plugin); - plugin->loop = loop; plugin->mode = mode; - plugin->frame_buffer = ply_window_get_frame_buffer (plugin->window); - ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) detach_from_event_loop, plugin); @@ -332,12 +507,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, (ply_event_handler_t) on_interrupt, plugin); - ply_trace ("setting graphics mode"); - if (!ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS)) - return false; - ply_window_clear_screen (plugin->window); - ply_window_hide_text_cursor (plugin->window); - ply_trace ("starting boot animation"); return start_animation (plugin); } @@ -347,9 +516,23 @@ update_status (ply_boot_splash_plugin_t *plugin, const char *status) { assert (plugin != NULL); - script_lib_plymouth_on_update_status (plugin->script_state, - plugin->script_plymouth_lib, - status); + + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + script_lib_plymouth_on_update_status (view->script_state, + view->script_plymouth_lib, + status); + node = next_node; + } } static void @@ -358,8 +541,6 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin, { assert (plugin != NULL); - remove_handlers (plugin); - if (plugin->loop != NULL) { stop_animation (plugin); @@ -370,16 +551,27 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin, plugin); detach_from_event_loop (plugin); } - plugin->frame_buffer = NULL; - - ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT); } static void on_root_mounted (ply_boot_splash_plugin_t *plugin) { - script_lib_plymouth_on_root_mounted (plugin->script_state, - plugin->script_plymouth_lib); + + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + script_lib_plymouth_on_root_mounted (view->script_state, + view->script_plymouth_lib); + node = next_node; + } } static void @@ -392,8 +584,25 @@ become_idle (ply_boot_splash_plugin_t *plugin, static void display_normal (ply_boot_splash_plugin_t *plugin) { - script_lib_plymouth_on_display_normal (plugin->script_state, - plugin->script_plymouth_lib); + ply_list_node_t *node; + + pause_views (plugin); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + script_lib_plymouth_on_display_normal (view->script_state, + view->script_plymouth_lib); + + + node = next_node; + } + unpause_views (plugin); } static void @@ -401,10 +610,27 @@ display_password (ply_boot_splash_plugin_t *plugin, const char *prompt, int bullets) { - script_lib_plymouth_on_display_password (plugin->script_state, - plugin->script_plymouth_lib, - prompt, - bullets); + ply_list_node_t *node; + + pause_views (plugin); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + script_lib_plymouth_on_display_password (view->script_state, + view->script_plymouth_lib, + prompt, + bullets); + + node = next_node; + } + unpause_views (plugin); + } static void @@ -412,19 +638,51 @@ display_question (ply_boot_splash_plugin_t *plugin, const char *prompt, const char *entry_text) { - script_lib_plymouth_on_display_question (plugin->script_state, - plugin->script_plymouth_lib, - prompt, - entry_text); + ply_list_node_t *node; + + pause_views (plugin); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + script_lib_plymouth_on_display_question (view->script_state, + view->script_plymouth_lib, + prompt, + entry_text); + + node = next_node; + } + unpause_views (plugin); } static void display_message (ply_boot_splash_plugin_t *plugin, const char *message) { - script_lib_plymouth_on_message (plugin->script_state, - plugin->script_plymouth_lib, - message); + ply_list_node_t *node; + + pause_views (plugin); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + script_lib_plymouth_on_message (view->script_state, + view->script_plymouth_lib, + message); + + node = next_node; + } + unpause_views (plugin); } ply_boot_splash_plugin_interface_t * @@ -434,8 +692,10 @@ ply_boot_splash_plugin_get_interface (void) { .create_plugin = create_plugin, .destroy_plugin = destroy_plugin, - .add_window = add_window, - .remove_window = remove_window, + .set_keyboard = set_keyboard, + .unset_keyboard = unset_keyboard, + .add_pixel_display = add_pixel_display, + .remove_pixel_display = remove_pixel_display, .show_splash_screen = show_splash_screen, .update_status = update_status, .on_boot_progress = on_boot_progress, diff --git a/src/plugins/splash/script/script-lib-sprite.c b/src/plugins/splash/script/script-lib-sprite.c index 3beded22..22ad7e21 100644 --- a/src/plugins/splash/script/script-lib-sprite.c +++ b/src/plugins/splash/script/script-lib-sprite.c @@ -21,10 +21,10 @@ */ #include "ply-image.h" #include "ply-utils.h" -#include "ply-window.h" -#include "ply-frame-buffer.h" #include "ply-logger.h" #include "ply-key-file.h" +#include "ply-pixel-buffer.h" +#include "ply-pixel-display.h" #include "script.h" #include "script-parse.h" #include "script-execute.h" @@ -141,22 +141,16 @@ static script_return_t sprite_window_get_width (script_state_t *state, void *user_data) { script_lib_sprite_data_t *data = user_data; - ply_frame_buffer_t *frame_buffer = ply_window_get_frame_buffer (data->window); - ply_frame_buffer_area_t area; - ply_frame_buffer_get_size (frame_buffer, &area); - return script_return_obj (script_obj_new_number (area.width)); + return script_return_obj (script_obj_new_number (ply_pixel_display_get_width (data->display))); } static script_return_t sprite_window_get_height (script_state_t *state, void *user_data) { script_lib_sprite_data_t *data = user_data; - ply_frame_buffer_t *frame_buffer = ply_window_get_frame_buffer (data->window); - ply_frame_buffer_area_t area; - ply_frame_buffer_get_size (frame_buffer, &area); - return script_return_obj (script_obj_new_number (area.height)); + return script_return_obj (script_obj_new_number (ply_pixel_display_get_height (data->display))); } static uint32_t extract_rgb_color (script_state_t *state) @@ -188,29 +182,26 @@ static script_return_t sprite_window_set_background_bottom_color (script_state_t return script_return_obj_null (); } -static void -draw_area (script_lib_sprite_data_t *data, - int x, - int y, - int width, - int height) +void script_lib_sprite_draw_area (script_lib_sprite_data_t *data, + ply_pixel_buffer_t *pixel_buffer, + int x, + int y, + int width, + int height) { - ply_frame_buffer_area_t clip_area; + ply_rectangle_t clip_area; clip_area.x = x; clip_area.y = y; clip_area.width = width; clip_area.height = height; - ply_frame_buffer_t *frame_buffer = ply_window_get_frame_buffer (data->window); - - ply_frame_buffer_pause_updates (frame_buffer); if (data->background_color_start == data->background_color_end) - ply_frame_buffer_fill_with_hex_color (frame_buffer, + ply_pixel_buffer_fill_with_hex_color (pixel_buffer, &clip_area, data->background_color_start); else - ply_frame_buffer_fill_with_gradient (frame_buffer, + ply_pixel_buffer_fill_with_gradient (pixel_buffer, &clip_area, data->background_color_start, data->background_color_end); @@ -220,7 +211,7 @@ draw_area (script_lib_sprite_data_t *data, node = ply_list_get_next_node (data->sprite_list, node)) { sprite_t *sprite = ply_list_node_get_data (node); - ply_frame_buffer_area_t sprite_area; + ply_rectangle_t sprite_area; if (!sprite->image) continue; if (sprite->remove_me) continue; if (sprite->opacity < 0.011) continue; @@ -234,24 +225,32 @@ draw_area (script_lib_sprite_data_t *data, if ((sprite_area.x + (int) sprite_area.width) <= x) continue; if ((sprite_area.y + (int) sprite_area.height) <= y) continue; - ply_frame_buffer_fill_with_argb32_data_at_opacity_with_clip (frame_buffer, + ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (pixel_buffer, &sprite_area, &clip_area, 0, 0, ply_image_get_data (sprite->image), sprite->opacity); } - ply_frame_buffer_unpause_updates (frame_buffer); } -script_lib_sprite_data_t *script_lib_sprite_setup (script_state_t *state, - ply_window_t *window) +void draw_area (script_lib_sprite_data_t *data, + int x, + int y, + int width, + int height) +{ + ply_pixel_display_draw_area (data->display, x, y, width, height); +} + +script_lib_sprite_data_t *script_lib_sprite_setup (script_state_t *state, + ply_pixel_display_t *display) { script_lib_sprite_data_t *data = malloc (sizeof (script_lib_sprite_data_t)); data->class = script_obj_native_class_new (sprite_free, "sprite", data); data->sprite_list = ply_list_new (); - data->window = window; + data->display = display; script_obj_t *sprite_hash = script_obj_hash_get_element (state->global, "Sprite"); script_add_native_function (sprite_hash, @@ -348,14 +347,9 @@ void script_lib_sprite_refresh (script_lib_sprite_data_t *data) if (data->full_refresh) { - ply_frame_buffer_area_t screen_area; - ply_frame_buffer_t *frame_buffer = ply_window_get_frame_buffer (data->window); - ply_frame_buffer_get_size (frame_buffer, &screen_area); - draw_area (data, - screen_area.x, - screen_area.y, - screen_area.width, - screen_area.height); + draw_area (data, 0, 0, + ply_pixel_display_get_width (data->display), + ply_pixel_display_get_height (data->display)); data->full_refresh = false; return; } diff --git a/src/plugins/splash/script/script-lib-sprite.h b/src/plugins/splash/script/script-lib-sprite.h index 60a33908..4d1de5e0 100644 --- a/src/plugins/splash/script/script-lib-sprite.h +++ b/src/plugins/splash/script/script-lib-sprite.h @@ -23,10 +23,11 @@ #define SCRIPT_LIB_SPRITE_H #include "script.h" +#include "ply-pixel-display.h" typedef struct { - ply_window_t *window; + ply_pixel_display_t *display; ply_list_t *sprite_list; script_obj_native_class_t *class; script_op_t *script_main_op; @@ -53,9 +54,15 @@ typedef struct script_obj_t *image_obj; } sprite_t; -script_lib_sprite_data_t *script_lib_sprite_setup (script_state_t *state, - ply_window_t *window); +script_lib_sprite_data_t *script_lib_sprite_setup (script_state_t *state, + ply_pixel_display_t *display); void script_lib_sprite_refresh (script_lib_sprite_data_t *data); void script_lib_sprite_destroy (script_lib_sprite_data_t *data); +void script_lib_sprite_draw_area (script_lib_sprite_data_t *data, + ply_pixel_buffer_t *pixel_buffer, + int x, + int y, + int width, + int height); #endif /* SCRIPT_LIB_SPRITE_H */ From 6e97f03437bbccfe0af35d88b8c10ca0846a9ed2 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 16:28:04 -0400 Subject: [PATCH 24/43] [space-flares] Update to use new multihead interface --- src/plugins/splash/space-flares/plugin.c | 922 ++++++++++++++--------- 1 file changed, 584 insertions(+), 338 deletions(-) diff --git a/src/plugins/splash/space-flares/plugin.c b/src/plugins/splash/space-flares/plugin.c index a2cb7349..3a87161e 100644 --- a/src/plugins/splash/space-flares/plugin.c +++ b/src/plugins/splash/space-flares/plugin.c @@ -49,13 +49,11 @@ #include "ply-label.h" #include "ply-list.h" #include "ply-logger.h" -#include "ply-frame-buffer.h" #include "ply-image.h" +#include "ply-pixel-buffer.h" +#include "ply-pixel-display.h" #include "ply-trigger.h" #include "ply-utils.h" -#include "ply-window.h" - -#include #ifndef FRAMES_PER_SECOND #define FRAMES_PER_SECOND 40 @@ -159,12 +157,21 @@ typedef struct int frame_count; } star_bg_t; +typedef struct +{ + ply_boot_splash_plugin_t *plugin; + ply_pixel_display_t *display; + ply_entry_t *entry; + ply_label_t *label; + ply_list_t *sprites; + ply_rectangle_t box_area, lock_area, logo_area; + ply_image_t *scaled_background_image; +} view_t; + struct _ply_boot_splash_plugin { ply_event_loop_t *loop; ply_boot_splash_mode_t mode; - ply_frame_buffer_t *frame_buffer; - ply_frame_buffer_area_t box_area, lock_area, logo_area; ply_image_t *logo_image; ply_image_t *lock_image; ply_image_t *box_image; @@ -177,18 +184,13 @@ struct _ply_boot_splash_plugin ply_image_t *progress_barimage; #endif - ply_image_t *scaled_background_image; #ifdef SHOW_LOGO_HALO ply_image_t *highlight_logo_image; #endif - ply_window_t *window; - - ply_entry_t *entry; - ply_label_t *label; + char *image_dir; ply_boot_splash_display_type_t state; - - ply_list_t *sprites; + ply_list_t *views; double now; @@ -200,12 +202,298 @@ struct _ply_boot_splash_plugin uint32_t is_animating : 1; }; -static void add_handlers (ply_boot_splash_plugin_t *plugin); -static void remove_handlers (ply_boot_splash_plugin_t *plugin); static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin); +static view_t * +view_new (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) +{ + view_t *view; + view = calloc (1, sizeof (view_t)); + view->plugin = plugin; + view->display = display; + + view->entry = ply_entry_new (plugin->image_dir); + view->label = ply_label_new (); + view->sprites = ply_list_new (); + + return view; +} + +static void view_free_sprites (view_t *view); + +static void +view_free (view_t *view) +{ + + ply_entry_free (view->entry); + ply_label_free (view->label); + view_free_sprites (view); + ply_list_free (view->sprites); + + ply_image_free (view->scaled_background_image); + + free (view); +} + +static void +free_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_free (view); + + node = next_node; + } + + ply_list_free (plugin->views); + plugin->views = NULL; +} + +static bool +view_load (view_t *view) +{ + ply_trace ("loading entry"); + if (!ply_entry_load (view->entry)) + return false; + + return true; +} + +static bool +load_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + bool view_loaded; + + view_loaded = false; + node = ply_list_get_first_node (plugin->views); + + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view_load (view)) + view_loaded = true; + + node = next_node; + } + + return view_loaded; +} + +static void +view_redraw (view_t *view) +{ + unsigned long screen_width, screen_height; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + ply_pixel_display_draw_area (view->display, 0, 0, + screen_width, screen_height); +} + +static void +redraw_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_redraw (view); + + node = next_node; + } +} + +static void +pause_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_pixel_display_pause_updates (view->display); + + node = next_node; + } +} + +static void +unpause_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_pixel_display_unpause_updates (view->display); + + node = next_node; + } +} + +static sprite_t* +add_sprite (view_t *view, + ply_image_t *image, + int type, + void *data) +{ + sprite_t *new_sprite = calloc (1, sizeof (sprite_t)); + + new_sprite->x = 0; + new_sprite->y = 0; + new_sprite->z = 0; + new_sprite->oldx = 0; + new_sprite->oldy = 0; + new_sprite->oldz = 0; + new_sprite->opacity = 1; + new_sprite->refresh_me = 0; + new_sprite->image = image; + new_sprite->type = type; + new_sprite->data = data; + + ply_list_append_data (view->sprites, new_sprite); + + return new_sprite; +} + +static void view_setup_scene (view_t *view); + +static void +view_start_animation (view_t *view) +{ + unsigned long screen_width, screen_height; + + assert (view != NULL); + + view_setup_scene (view); + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + ply_pixel_display_draw_area (view->display, 0, 0, + screen_width, screen_height); +} + +static void +view_show_prompt (view_t *view, + const char *prompt) +{ + ply_boot_splash_plugin_t *plugin; + int x, y; + int entry_width, entry_height; + + assert (view != NULL); + + plugin = view->plugin; + + if (ply_entry_is_hidden (view->entry)) + { + unsigned long screen_width, screen_height; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + view->box_area.width = ply_image_get_width (plugin->box_image); + view->box_area.height = ply_image_get_height (plugin->box_image); + view->box_area.x = screen_width / 2.0 - view->box_area.width / 2.0; + view->box_area.y = screen_height / 2.0 - view->box_area.height / 2.0; + + view->lock_area.width = ply_image_get_width (plugin->lock_image); + view->lock_area.height = ply_image_get_height (plugin->lock_image); + + entry_width = ply_entry_get_width (view->entry); + entry_height = ply_entry_get_height (view->entry); + + x = screen_width / 2.0 - (view->lock_area.width + entry_width) / 2.0 + view->lock_area.width; + y = screen_height / 2.0 - entry_height / 2.0; + + view->lock_area.x = screen_width / 2.0 - (view->lock_area.width + entry_width) / 2.0; + view->lock_area.y = screen_height / 2.0 - view->lock_area.height / 2.0; + + ply_entry_show (view->entry, plugin->loop, view->display, x, y); + } + + if (prompt != NULL) + { + int label_width, label_height; + + ply_label_set_text (view->label, prompt); + label_width = ply_label_get_width (view->label); + label_height = ply_label_get_height (view->label); + + x = view->box_area.x + view->lock_area.width / 2; + y = view->box_area.y + view->box_area.height; + + ply_label_show (view->label, view->display, x, y); + } +} + +static void +view_hide_prompt (view_t *view) +{ + assert (view != NULL); + + ply_entry_hide (view->entry); + ply_label_hide (view->label); +} + +static void +hide_prompt (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_hide_prompt (view); + + node = next_node; + } +} static ply_boot_splash_plugin_t * create_plugin (ply_key_file_t *key_file) @@ -228,8 +516,6 @@ create_plugin (ply_key_file_t *key_file) plugin->box_image = ply_image_new (image_path); free (image_path); - plugin->scaled_background_image = NULL; - asprintf (&image_path, "%s/star.png", image_dir); plugin->star_image = ply_image_new (image_path); free (image_path); @@ -263,13 +549,14 @@ create_plugin (ply_key_file_t *key_file) plugin->progress_barimage = ply_image_new (image_path); free (image_path); #endif - plugin->entry = ply_entry_new (image_dir); - plugin->label = ply_label_new (); plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL; - plugin->sprites = ply_list_new(); plugin->progress = 0; plugin->progress_target = -1; - free(image_dir); + + plugin->image_dir = image_dir; + + plugin->views = ply_list_new (); + return plugin; } @@ -279,7 +566,7 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin) if (plugin == NULL) return; - remove_handlers (plugin); + free (plugin->image_dir); if (plugin->loop != NULL) { @@ -293,7 +580,6 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin) ply_image_free (plugin->lock_image); ply_image_free (plugin->box_image); - ply_image_free (plugin->scaled_background_image); ply_image_free (plugin->star_image); #ifdef SHOW_PLANETS ply_image_free (plugin->planet_image[0]); @@ -306,14 +592,11 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin) ply_image_free (plugin->progress_barimage); #endif - ply_entry_free (plugin->entry); - ply_label_free (plugin->label); - ply_list_free (plugin->sprites); + free_views (plugin); free (plugin); } - static void free_sprite (sprite_t* sprite) { @@ -359,44 +642,6 @@ free_sprite (sprite_t* sprite) return; } - - -static sprite_t* -add_sprite (ply_boot_splash_plugin_t *plugin, ply_image_t *image, int type, void* data) -{ - sprite_t* new_sprite = calloc (1, sizeof (sprite_t)); - new_sprite->x = 0; - new_sprite->y = 0; - new_sprite->z = 0; - new_sprite->oldx = 0; - new_sprite->oldy = 0; - new_sprite->oldz = 0; - new_sprite->opacity = 1; - new_sprite->refresh_me = 0; - new_sprite->image = image; - new_sprite->type = type; - new_sprite->data = data; - ply_list_append_data (plugin->sprites, new_sprite); - return new_sprite; -} - - -static void -draw_background (ply_boot_splash_plugin_t *plugin, - ply_frame_buffer_area_t *area) -{ - ply_frame_buffer_area_t screen_area; - - if (area == NULL) - { - ply_frame_buffer_get_size (plugin->frame_buffer, &screen_area); - area = &screen_area; - } - - ply_window_erase_area (plugin->window, area->x, area->y, - area->width, area->height); -} - int sprite_compare_z(void *data_a, void *data_b) { sprite_t *sprite_a = data_a; @@ -444,10 +689,12 @@ stretch_image(ply_image_t *scaled_image, ply_image_t *orig_image, int width) } static void -progress_update (ply_boot_splash_plugin_t *plugin, sprite_t* sprite, double time) +progress_update (view_t *view, sprite_t* sprite, double time) { progress_t *progress = sprite->data; - int newwidth = plugin->progress*(progress->end_width-progress->start_width)+progress->start_width; + ply_boot_splash_plugin_t *plugin = view->plugin; + int newwidth = plugin->progress * (progress->end_width - progress->start_width) + progress->start_width; + if (progress->current_width >newwidth) return; progress->current_width = newwidth; stretch_image(progress->image_altered, progress->image, newwidth); @@ -511,7 +758,7 @@ star_bg_gradient_colour (int x, int y, int width, int height, bool star, float t static void -star_bg_update (ply_boot_splash_plugin_t *plugin, sprite_t* sprite, double time) +star_bg_update (view_t *view, sprite_t* sprite, double time) { star_bg_t *star_bg = sprite->data; int width = ply_image_get_width (sprite->image); @@ -536,15 +783,14 @@ star_bg_update (ply_boot_splash_plugin_t *plugin, sprite_t* sprite, double time) } static void -satellite_move (ply_boot_splash_plugin_t *plugin, sprite_t* sprite, double time) +satellite_move (view_t *view, sprite_t* sprite, double time) { + ply_boot_splash_plugin_t *plugin = view->plugin; satellite_t *satellite = sprite->data; - ply_frame_buffer_area_t screen_area; - - ply_frame_buffer_get_size (plugin->frame_buffer, &screen_area); int width = ply_image_get_width (sprite->image); int height = ply_image_get_height (sprite->image); + unsigned long screen_width, screen_height; sprite->x=cos(satellite->theta+(1-plugin->progress)*2000/(satellite->distance))*satellite->distance; sprite->y=sin(satellite->theta+(1-plugin->progress)*2000/(satellite->distance))*satellite->distance; @@ -557,12 +803,14 @@ satellite_move (ply_boot_splash_plugin_t *plugin, sprite_t* sprite, double time) float angle_offset = atan2 (sprite->x, sprite->y); float cresent_angle = atan2 (sqrt(sprite->x*sprite->x+sprite->y*sprite->y), sprite->z); - + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + sprite->x+=(float)satellite->end_x*plugin->progress+(float)satellite->start_x*(1-plugin->progress)-width/2; sprite->y+=(float)satellite->end_y*plugin->progress+(float)satellite->start_y*(1-plugin->progress)-height/2; - if (sprite->x > (signed int)screen_area.width) return; - if (sprite->y > (signed int)screen_area.height) return; + if (sprite->x > (signed int) screen_width) return; + if (sprite->y > (signed int) screen_height) return; if (satellite->type == SATELLITE_TYPE_PLANET) { @@ -660,9 +908,9 @@ satellite_move (ply_boot_splash_plugin_t *plugin, sprite_t* sprite, double time) static void -sprite_list_sort (ply_boot_splash_plugin_t *plugin) +sprite_list_sort (view_t *view) { - ply_list_sort (plugin->sprites, &sprite_compare_z); + ply_list_sort (view->sprites, &sprite_compare_z); } static void @@ -803,11 +1051,8 @@ flare_update (sprite_t* sprite, double time) return; } - - - static void -sprite_move (ply_boot_splash_plugin_t *plugin, sprite_t* sprite, double time) +sprite_move (view_t *view, sprite_t* sprite, double time) { sprite->oldx = sprite->x; sprite->oldy = sprite->y; @@ -816,48 +1061,42 @@ sprite_move (ply_boot_splash_plugin_t *plugin, sprite_t* sprite, double time) case SPRITE_TYPE_STATIC: break; case SPRITE_TYPE_PROGRESS: - progress_update (plugin, sprite, time); + progress_update (view, sprite, time); break; case SPRITE_TYPE_FLARE: flare_update (sprite, time); break; case SPRITE_TYPE_SATELLITE: - satellite_move (plugin, sprite, time); + satellite_move (view, sprite, time); break; case SPRITE_TYPE_STAR_BG: - star_bg_update (plugin, sprite, time); + star_bg_update (view, sprite, time); break; } } -void -on_draw (ply_boot_splash_plugin_t *plugin, - int x, - int y, - int width, - int height); - static void -animate_attime (ply_boot_splash_plugin_t *plugin, double time) +view_animate_attime (view_t *view, double time) { ply_list_node_t *node; - - ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS); + ply_boot_splash_plugin_t *plugin; + + plugin = view->plugin; if (plugin->progress_target>=0) plugin->progress = (plugin->progress*10 + plugin->progress_target) /11; - node = ply_list_get_first_node (plugin->sprites); + node = ply_list_get_first_node (view->sprites); while(node) { sprite_t* sprite = ply_list_node_get_data (node); - sprite_move (plugin, sprite, time); - node = ply_list_get_next_node (plugin->sprites, node); + sprite_move (view, sprite, time); + node = ply_list_get_next_node (view->sprites, node); } - sprite_list_sort (plugin); + sprite_list_sort (view); - for(node = ply_list_get_first_node (plugin->sprites); node; node = ply_list_get_next_node (plugin->sprites, node)) + for(node = ply_list_get_first_node (view->sprites); node; node = ply_list_get_next_node (view->sprites, node)) { sprite_t* sprite = ply_list_node_get_data (node); if (sprite->x != sprite->oldx || @@ -875,7 +1114,8 @@ animate_attime (ply_boot_splash_plugin_t *plugin, double time) int i; for (i=0; istar_count; i++){ if (star_bg->star_refresh[i]){ - ply_window_draw_area (plugin->window, sprite->x+star_bg->star_x[i], sprite->y+star_bg->star_y[i], 1, 1); + ply_pixel_display_draw_area (view->display, + sprite->x+star_bg->star_x[i], sprite->y+star_bg->star_y[i], 1, 1); star_bg->star_refresh[i]=0; } } @@ -893,12 +1133,15 @@ animate_attime (ply_boot_splash_plugin_t *plugin, double time) y=MIN(sprite->y, sprite->oldy); width =(MAX(sprite->x, sprite->oldx)-x)+ply_image_get_width (sprite->image); height=(MAX(sprite->y, sprite->oldy)-y)+ply_image_get_height (sprite->image); - ply_window_draw_area (plugin->window, x, y, width, height); + ply_pixel_display_draw_area (view->display, + x, y, width, height); } else { - ply_window_draw_area (plugin->window, sprite->x, sprite->y, width, height); - ply_window_draw_area (plugin->window, sprite->oldx, sprite->oldy, width, height); + ply_pixel_display_draw_area (view->display, + sprite->x, sprite->y, width, height); + ply_pixel_display_draw_area (view->display, + sprite->oldx, sprite->oldy, width, height); } } } @@ -907,12 +1150,26 @@ animate_attime (ply_boot_splash_plugin_t *plugin, double time) static void on_timeout (ply_boot_splash_plugin_t *plugin) { + ply_list_node_t *node; double sleep_time; double now; now = ply_get_timestamp (); - animate_attime (plugin, now); + node = ply_list_get_first_node (plugin->views); + + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_animate_attime (view, now); + + node = next_node; + } plugin->now = now; sleep_time = 1.0 / FRAMES_PER_SECOND; @@ -933,34 +1190,48 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin, plugin->progress_target = percent_done; } -void -setup_scene (ply_boot_splash_plugin_t *plugin); - static void start_animation (ply_boot_splash_plugin_t *plugin) { - - ply_frame_buffer_area_t area; - assert (plugin != NULL); - assert (plugin->loop != NULL); + ply_list_node_t *node; if (plugin->is_animating) return; - ply_frame_buffer_get_size (plugin->frame_buffer, &area); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; - plugin->now = ply_get_timestamp (); - setup_scene (plugin); - ply_window_draw_area (plugin->window, area.x, area.y, area.width, area.height); + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); - if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN) - return; + view_start_animation (view); + + node = next_node; + } on_timeout (plugin); plugin->is_animating = true; } +static void +view_free_sprites (view_t *view) +{ + ply_list_node_t *node; + + for (node = ply_list_get_first_node (view->sprites); + node != NULL; + node = ply_list_get_next_node (view->sprites, node)) + { + sprite_t* sprite = ply_list_node_get_data (node); + free_sprite (sprite); + } + ply_list_remove_all_nodes (view->sprites); +} + static void stop_animation (ply_boot_splash_plugin_t *plugin) { @@ -985,12 +1256,11 @@ stop_animation (ply_boot_splash_plugin_t *plugin) ply_image_free(plugin->highlight_logo_image); #endif - for(node = ply_list_get_first_node (plugin->sprites); node; node = ply_list_get_next_node (plugin->sprites, node)) + for(node = ply_list_get_first_node (plugin->views); node; node = ply_list_get_next_node (plugin->views, node)) { - sprite_t* sprite = ply_list_node_get_data (node); - free_sprite (sprite); + view_t *view = ply_list_node_get_data (node); + view_free_sprites (view); } - ply_list_remove_all_nodes (plugin->sprites); } static void @@ -998,7 +1268,6 @@ on_interrupt (ply_boot_splash_plugin_t *plugin) { ply_event_loop_exit (plugin->loop, 1); stop_animation (plugin); - ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT); } static void @@ -1007,33 +1276,23 @@ detach_from_event_loop (ply_boot_splash_plugin_t *plugin) plugin->loop = NULL; } +static void +draw_background (view_t *view, + ply_pixel_buffer_t *pixel_buffer, + int x, + int y, + int width, + int height); void -on_keyboard_input (ply_boot_splash_plugin_t *plugin, - const char *keyboard_input, - size_t character_size) -{ -} - -void -on_backspace (ply_boot_splash_plugin_t *plugin) -{ -} - -void -on_enter (ply_boot_splash_plugin_t *plugin, - const char *text) -{ -} - - -void -on_draw (ply_boot_splash_plugin_t *plugin, +on_draw (view_t *view, + ply_pixel_buffer_t *pixel_buffer, int x, int y, int width, int height) { - ply_frame_buffer_area_t clip_area; + ply_boot_splash_plugin_t *plugin; + ply_rectangle_t clip_area; clip_area.x = x; clip_area.y = y; clip_area.width = width; @@ -1043,25 +1302,40 @@ on_draw (ply_boot_splash_plugin_t *plugin, float pixel_r=0; float pixel_g=0; float pixel_b=0; + + plugin = view->plugin; + if (width==1 && height==1) single_pixel = true; - else - ply_frame_buffer_pause_updates (plugin->frame_buffer); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY || plugin->state == PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY ) { - draw_background (plugin, &clip_area); - ply_entry_draw (plugin->entry); - ply_label_draw (plugin->label); + uint32_t *box_data, *lock_data; + + draw_background (view, pixel_buffer, x, y, width, height); + + box_data = ply_image_get_data (plugin->box_image); + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, + &view->box_area, 0, 0, + box_data); + ply_entry_draw_area (view->entry, pixel_buffer, x, y, width, height); + ply_label_draw_area (view->label, pixel_buffer, x, y, width, height); + lock_data = ply_image_get_data (plugin->lock_image); + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, + &view->lock_area, 0, 0, + lock_data); } else { ply_list_node_t *node; - for(node = ply_list_get_first_node (plugin->sprites); node; node = ply_list_get_next_node (plugin->sprites, node)) + + draw_background (view, pixel_buffer, x, y, width, height); + + for(node = ply_list_get_first_node (view->sprites); node; node = ply_list_get_next_node (view->sprites, node)) { sprite_t* sprite = ply_list_node_get_data (node); - ply_frame_buffer_area_t sprite_area; + ply_rectangle_t sprite_area; sprite_area.x = sprite->x; @@ -1090,29 +1364,30 @@ on_draw (ply_boot_splash_plugin_t *plugin, } else { - ply_frame_buffer_fill_with_argb32_data_at_opacity_with_clip (plugin->frame_buffer, - &sprite_area, &clip_area, 0, 0, - ply_image_get_data (sprite->image), sprite->opacity); + ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (pixel_buffer, + &sprite_area, &clip_area, 0, 0, + ply_image_get_data (sprite->image), sprite->opacity); } } } if (single_pixel){ - ply_frame_buffer_fill_with_color (plugin->frame_buffer, &clip_area, pixel_r, pixel_g, pixel_b, 1.0); - } - else { - ply_frame_buffer_unpause_updates (plugin->frame_buffer); + ply_pixel_buffer_fill_with_color (pixel_buffer, &clip_area, pixel_r, pixel_g, pixel_b, 1.0); } } -void -on_erase (ply_boot_splash_plugin_t *plugin, - int x, - int y, - int width, - int height) +static void +draw_background (view_t *view, + ply_pixel_buffer_t *pixel_buffer, + int x, + int y, + int width, + int height) { - ply_frame_buffer_area_t area; - ply_frame_buffer_area_t image_area; + ply_boot_splash_plugin_t *plugin; + ply_rectangle_t area; + ply_rectangle_t image_area; + + plugin = view->plugin; area.x = x; area.y = y; @@ -1121,12 +1396,12 @@ on_erase (ply_boot_splash_plugin_t *plugin, image_area.x = 0; image_area.y = 0; - image_area.width = ply_image_get_width(plugin->scaled_background_image); - image_area.height = ply_image_get_height(plugin->scaled_background_image); + image_area.width = ply_image_get_width (view->scaled_background_image); + image_area.height = ply_image_get_height (view->scaled_background_image); - ply_frame_buffer_fill_with_argb32_data_with_clip (plugin->frame_buffer, - &image_area, &area, 0, 0, - ply_image_get_data (plugin->scaled_background_image)); + ply_pixel_buffer_fill_with_argb32_data_with_clip (pixel_buffer, + &image_area, &area, 0, 0, + ply_image_get_data (view->scaled_background_image)); image_area.x = image_area.width-ply_image_get_width(plugin->star_image); image_area.y = image_area.height-ply_image_get_height(plugin->star_image); @@ -1134,7 +1409,7 @@ on_erase (ply_boot_splash_plugin_t *plugin, image_area.height = ply_image_get_height(plugin->star_image); - ply_frame_buffer_fill_with_argb32_data_with_clip (plugin->frame_buffer, + ply_pixel_buffer_fill_with_argb32_data_with_clip (pixel_buffer, &image_area, &area, 0, 0, ply_image_get_data (plugin->star_image)); @@ -1144,57 +1419,54 @@ on_erase (ply_boot_splash_plugin_t *plugin, image_area.height = ply_image_get_height(plugin->logo_image); - ply_frame_buffer_fill_with_argb32_data_with_clip (plugin->frame_buffer, + ply_pixel_buffer_fill_with_argb32_data_with_clip (pixel_buffer, &image_area, &area, 0, 0, ply_image_get_data (plugin->logo_image)); } static void -add_handlers (ply_boot_splash_plugin_t *plugin) +add_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) { - ply_window_add_keyboard_input_handler (plugin->window, - (ply_window_keyboard_input_handler_t) - on_keyboard_input, plugin); - ply_window_add_backspace_handler (plugin->window, - (ply_window_backspace_handler_t) - on_backspace, plugin); - ply_window_add_enter_handler (plugin->window, - (ply_window_enter_handler_t) - on_enter, plugin); + view_t *view; - ply_window_set_draw_handler (plugin->window, - (ply_window_draw_handler_t) - on_draw, plugin); + view = view_new (plugin, display); - ply_window_set_erase_handler (plugin->window, - (ply_window_erase_handler_t) - on_erase, 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); } static void -remove_handlers (ply_boot_splash_plugin_t *plugin) +remove_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) { + ply_list_node_t *node; - ply_window_remove_keyboard_input_handler (plugin->window, (ply_window_keyboard_input_handler_t) on_keyboard_input); - ply_window_remove_backspace_handler (plugin->window, (ply_window_backspace_handler_t) on_backspace); - ply_window_remove_enter_handler (plugin->window, (ply_window_enter_handler_t) on_enter); - ply_window_set_draw_handler (plugin->window, NULL, NULL); - ply_window_set_erase_handler (plugin->window, NULL, NULL); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; + + view = ply_list_node_get_data (node); + 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; + } + + node = next_node; + } } -static void -add_window (ply_boot_splash_plugin_t *plugin, - ply_window_t *window) -{ - plugin->window = window; -} - -static void -remove_window (ply_boot_splash_plugin_t *plugin, - ply_window_t *window) -{ - plugin->window = NULL; -} void highlight_image (ply_image_t *highlighted_image, ply_image_t *orig_image, int distance) { @@ -1232,93 +1504,97 @@ void highlight_image (ply_image_t *highlighted_image, ply_image_t *orig_image, i } -void -setup_scene (ply_boot_splash_plugin_t *plugin) + +static void +view_setup_scene (view_t *view) { - ply_frame_buffer_area_t screen_area; + ply_boot_splash_plugin_t *plugin; sprite_t *sprite; int i; int x, y; int width = 360; int height = 460; + unsigned long screen_width, screen_height; + + plugin = view->plugin; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); - ply_frame_buffer_get_size (plugin->frame_buffer, &screen_area); - { star_bg_t* star_bg; - if (plugin->scaled_background_image) - ply_image_free(plugin->scaled_background_image); - - plugin->scaled_background_image = ply_image_resize (plugin->logo_image, screen_area.width, screen_area.height); + if (view->scaled_background_image) + ply_image_free (view->scaled_background_image); + view->scaled_background_image = ply_image_resize (plugin->logo_image, screen_width, screen_height); star_bg = malloc(sizeof(star_bg_t)); - star_bg->star_count = (screen_area.width * screen_area.height)/400; + star_bg->star_count = (screen_width * screen_height)/400; star_bg->star_x = malloc(sizeof(int)*star_bg->star_count); star_bg->star_y = malloc(sizeof(int)*star_bg->star_count); star_bg->star_refresh = malloc(sizeof(int)*star_bg->star_count); star_bg->frame_count=0; - sprite = add_sprite (plugin, plugin->scaled_background_image, SPRITE_TYPE_STAR_BG, star_bg); + sprite = add_sprite (view, view->scaled_background_image, SPRITE_TYPE_STAR_BG, star_bg); sprite->z = -10000; - uint32_t* image_data = ply_image_get_data (plugin->scaled_background_image); - for (y=0; y< (int) screen_area.height; y++) for (x=0; x< (int) screen_area.width; x++){ - image_data[x + y * screen_area.width] = star_bg_gradient_colour(x, y, screen_area.width, screen_area.height, false, 0); + uint32_t* image_data = ply_image_get_data (view->scaled_background_image); + for (y=0; y< (int) screen_height; y++) for (x=0; x< (int) screen_width; x++){ + image_data[x + y * screen_width] = star_bg_gradient_colour(x, y, screen_width, screen_height, false, 0); } for (i=0; istar_count; i++){ do { - x = rand()%screen_area.width; - y = rand()%screen_area.height; + x = rand()%screen_width; + y = rand()%screen_height; } - while (image_data[x + y * screen_area.width] == 0xFFFFFFFF); + while (image_data[x + y * screen_width] == 0xFFFFFFFF); star_bg->star_refresh[i] = 0; star_bg->star_x[i] = x; star_bg->star_y[i] = y; - image_data[x + y * screen_area.width] = 0xFFFFFFFF; + image_data[x + y * screen_width] = 0xFFFFFFFF; } - for (i=0; i<(int) (screen_area.width * screen_area.height)/400; i++){ - x = rand()%screen_area.width; - y = rand()%screen_area.height; - image_data[x + y * screen_area.width] = star_bg_gradient_colour(x, y, screen_area.width, screen_area.height, true, ((float)x*y*13/10000)); + for (i=0; i<(int) (screen_width * screen_height)/400; i++){ + x = rand()%screen_width; + y = rand()%screen_height; + image_data[x + y * screen_width] = star_bg_gradient_colour(x, y, screen_width, screen_height, true, ((float)x*y*13/10000)); } for (i=0; istar_count; i++){ - image_data[star_bg->star_x[i] + star_bg->star_y[i] * screen_area.width] = - star_bg_gradient_colour(star_bg->star_x[i], star_bg->star_y[i], screen_area.width, screen_area.height, true, 0.0); + image_data[star_bg->star_x[i] + star_bg->star_y[i] * screen_width] = + star_bg_gradient_colour(star_bg->star_x[i], star_bg->star_y[i], screen_width, screen_height, true, 0.0); } } - sprite = add_sprite (plugin, plugin->logo_image, SPRITE_TYPE_STATIC, NULL); - sprite->x=screen_area.width/2-ply_image_get_width(plugin->logo_image)/2; - sprite->y=screen_area.height/2-ply_image_get_height(plugin->logo_image)/2; + sprite = add_sprite (view, plugin->logo_image, SPRITE_TYPE_STATIC, NULL); + sprite->x=screen_width/2-ply_image_get_width(plugin->logo_image)/2; + sprite->y=screen_height/2-ply_image_get_height(plugin->logo_image)/2; sprite->z=1000; #ifdef SHOW_LOGO_HALO plugin->highlight_logo_image = ply_image_resize (plugin->logo_image, ply_image_get_width(plugin->logo_image)+HALO_BLUR*2, ply_image_get_height(plugin->logo_image)+HALO_BLUR*2); highlight_image (plugin->highlight_logo_image, plugin->logo_image, HALO_BLUR); - sprite = add_sprite (plugin, plugin->highlight_logo_image, SPRITE_TYPE_STATIC, NULL); + sprite = add_sprite (view, plugin->highlight_logo_image, SPRITE_TYPE_STATIC, NULL); sprite->x=10-HALO_BLUR; sprite->y=10-HALO_BLUR; sprite->z=-910; #endif - sprite = add_sprite (plugin, plugin->star_image, SPRITE_TYPE_STATIC, NULL); - sprite->x=screen_area.width-ply_image_get_width(plugin->star_image); - sprite->y=screen_area.height-ply_image_get_height(plugin->star_image); + sprite = add_sprite (view, plugin->star_image, SPRITE_TYPE_STATIC, NULL); + sprite->x=screen_width-ply_image_get_width(plugin->star_image); + sprite->y=screen_height-ply_image_get_height(plugin->star_image); sprite->z=0; #ifdef SHOW_PLANETS for (i=0; i<5; i++) { satellite_t* satellite = malloc(sizeof(satellite_t)); satellite->type=SATELLITE_TYPE_PLANET; - satellite->end_x=satellite->start_x=720-800+screen_area.width; - satellite->end_y=satellite->start_y=300-480+screen_area.height; + satellite->end_x=satellite->start_x=720-800+screen_width; + satellite->end_y=satellite->start_y=300-480+screen_height; satellite->distance=i*100+280; satellite->theta=M_PI*0.8; satellite->image=plugin->planet_image[i]; satellite->image_altered=ply_image_resize (satellite->image, ply_image_get_width(satellite->image), ply_image_get_height(satellite->image)); - sprite = add_sprite (plugin, satellite->image_altered, SPRITE_TYPE_SATELLITE, satellite); + sprite = add_sprite (view, satellite->image_altered, SPRITE_TYPE_SATELLITE, satellite); satellite_move (plugin, sprite, 0); } @@ -1328,8 +1604,8 @@ setup_scene (ply_boot_splash_plugin_t *plugin) { satellite_t* satellite = malloc(sizeof(satellite_t)); satellite->type=SATELLITE_TYPE_COMET; - satellite->end_x=satellite->start_x=720-800+screen_area.width; - satellite->end_y=satellite->start_y=300-480+screen_area.height; + satellite->end_x=satellite->start_x=720-800+screen_width; + satellite->end_y=satellite->start_y=300-480+screen_height; satellite->distance=550+i*50; satellite->theta=M_PI*0.8; #define COMET_SIZE 64 @@ -1344,7 +1620,7 @@ setup_scene (ply_boot_splash_plugin_t *plugin) image_altered_data[x + y * COMET_SIZE] = 0x0; } - sprite = add_sprite (plugin, satellite->image_altered, SPRITE_TYPE_SATELLITE, satellite); + sprite = add_sprite (view, satellite->image_altered, SPRITE_TYPE_SATELLITE, satellite); for (x=0; ximage = plugin->progress_barimage; - x = screen_area.width/2-ply_image_get_width(plugin->logo_image)/2;; - y = screen_area.height/2+ply_image_get_height(plugin->logo_image)/2+20; + x = screen_width/2-ply_image_get_width(plugin->logo_image)/2;; + y = screen_height/2+ply_image_get_height(plugin->logo_image)/2+20; progress->image_altered = ply_image_resize (plugin->progress_barimage, ply_image_get_width(plugin->logo_image), ply_image_get_height(plugin->progress_barimage)); progress->start_width = 1; progress->end_width = ply_image_get_width(plugin->logo_image); progress->current_width = 0; - sprite = add_sprite (plugin, progress->image_altered, SPRITE_TYPE_PROGRESS, progress); + sprite = add_sprite (view, progress->image_altered, SPRITE_TYPE_PROGRESS, progress); sprite->x=x; sprite->y=y; sprite->z=10011; - progress_update (plugin, sprite, 0); + progress_update (view, sprite, 0); @@ -1376,12 +1652,12 @@ setup_scene (ply_boot_splash_plugin_t *plugin) flare->image_a = ply_image_resize (plugin->star_image, width, height); flare->image_b = ply_image_resize (plugin->star_image, width, height); - sprite = add_sprite (plugin, flare->image_a, SPRITE_TYPE_FLARE, flare); - sprite->x=screen_area.width-width; - sprite->y=screen_area.height-height; + sprite = add_sprite (view, flare->image_a, SPRITE_TYPE_FLARE, flare); + sprite->x=screen_width-width; + sprite->y=screen_height-height; sprite->z=1; - sprite_list_sort (plugin); + sprite_list_sort (view); uint32_t * old_image_data = ply_image_get_data (flare->image_a); uint32_t * new_image_data = ply_image_get_data (flare->image_b); @@ -1413,8 +1689,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, assert (plugin != NULL); assert (plugin->logo_image != NULL); - add_handlers (plugin); - plugin->loop = loop; plugin->mode = mode; @@ -1452,15 +1726,11 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, if (!ply_image_load (plugin->box_image)) return false; - ply_trace ("loading entry"); - if (!ply_entry_load (plugin->entry)) - return false; - - ply_trace ("setting graphics mode"); - if (!ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS)) - return false; - - plugin->frame_buffer = ply_window_get_frame_buffer (plugin->window); + if (!load_views (plugin)) + { + ply_trace ("couldn't load views"); + return false; + } ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) detach_from_event_loop, @@ -1471,9 +1741,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, (ply_event_handler_t) on_interrupt, plugin); - ply_window_clear_screen (plugin->window); - ply_window_hide_text_cursor (plugin->window); - ply_trace ("starting boot animation"); start_animation (plugin); @@ -1496,8 +1763,6 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin, { assert (plugin != NULL); - remove_handlers (plugin); - if (plugin->loop != NULL) { stop_animation (plugin); @@ -1508,76 +1773,53 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin, detach_from_event_loop (plugin); } - plugin->frame_buffer = NULL; plugin->is_visible = false; - - ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT); } static void show_password_prompt (ply_boot_splash_plugin_t *plugin, - const char *prompt) + const char *text, + int number_of_bullets) { - ply_frame_buffer_area_t area; - int x, y; - int entry_width, entry_height; + ply_list_node_t *node; - uint32_t *box_data, *lock_data; - - assert (plugin != NULL); - - if (ply_entry_is_hidden (plugin->entry)) + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { - draw_background (plugin, NULL); + ply_list_node_t *next_node; + view_t *view; - ply_frame_buffer_get_size (plugin->frame_buffer, &area); - plugin->box_area.width = ply_image_get_width (plugin->box_image); - plugin->box_area.height = ply_image_get_height (plugin->box_image); - plugin->box_area.x = area.width / 2.0 - plugin->box_area.width / 2.0; - plugin->box_area.y = area.height / 2.0 - plugin->box_area.height / 2.0; + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); - plugin->lock_area.width = ply_image_get_width (plugin->lock_image); - plugin->lock_area.height = ply_image_get_height (plugin->lock_image); + view_show_prompt (view, text); + ply_entry_set_bullet_count (view->entry, number_of_bullets); - entry_width = ply_entry_get_width (plugin->entry); - entry_height = ply_entry_get_height (plugin->entry); - - x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0 + plugin->lock_area.width; - y = area.height / 2.0 - entry_height / 2.0; - - plugin->lock_area.x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0; - plugin->lock_area.y = area.height / 2.0 - plugin->lock_area.height / 2.0; - - box_data = ply_image_get_data (plugin->box_image); - ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer, - &plugin->box_area, 0, 0, - box_data); - - ply_entry_show (plugin->entry, plugin->loop, plugin->window, x, y); - - lock_data = ply_image_get_data (plugin->lock_image); - ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer, - &plugin->lock_area, 0, 0, - lock_data); + node = next_node; } - else +} + +static void +show_prompt (ply_boot_splash_plugin_t *plugin, + const char *prompt, + const char *entry_text) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { - ply_entry_draw (plugin->entry); + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_show_prompt (view, prompt); + ply_entry_set_text (view->entry, entry_text); + + node = next_node; } - if (prompt != NULL) - { - int label_width, label_height; - - ply_label_set_text (plugin->label, prompt); - label_width = ply_label_get_width (plugin->label); - label_height = ply_label_get_height (plugin->label); - - x = plugin->box_area.x + plugin->lock_area.width / 2; - y = plugin->box_area.y + plugin->box_area.height; - - ply_label_show (plugin->label, plugin->window, x, y); - } - } static void @@ -1597,12 +1839,15 @@ become_idle (ply_boot_splash_plugin_t *plugin, static void display_normal (ply_boot_splash_plugin_t *plugin) { + pause_views (plugin); if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_NORMAL) { plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL; - ply_entry_hide (plugin->entry); - start_animation(plugin); + hide_prompt (plugin); + start_animation (plugin); + redraw_views (plugin); } + unpause_views (plugin); } static void @@ -1610,13 +1855,14 @@ display_password (ply_boot_splash_plugin_t *plugin, const char *prompt, int bullets) { + pause_views (plugin); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) - { - stop_animation (plugin); - } + stop_animation (plugin); + plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY; - show_password_prompt (plugin, prompt); - ply_entry_set_bullet_count (plugin->entry, bullets); + show_password_prompt (plugin, prompt, bullets); + redraw_views (plugin); + unpause_views (plugin); } static void @@ -1624,14 +1870,14 @@ display_question (ply_boot_splash_plugin_t *plugin, const char *prompt, const char *entry_text) { + pause_views (plugin); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) - { - stop_animation (plugin); - } + stop_animation (plugin); plugin->state = PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY; - show_password_prompt (plugin, prompt); - ply_entry_set_text (plugin->entry, entry_text); + show_prompt (plugin, prompt, entry_text); + redraw_views (plugin); + unpause_views (plugin); } ply_boot_splash_plugin_interface_t * @@ -1641,8 +1887,8 @@ ply_boot_splash_plugin_get_interface (void) { .create_plugin = create_plugin, .destroy_plugin = destroy_plugin, - .add_window = add_window, - .remove_window = remove_window, + .add_pixel_display = add_pixel_display, + .remove_pixel_display = remove_pixel_display, .show_splash_screen = show_splash_screen, .update_status = update_status, .on_boot_progress = on_boot_progress, From d0f225b93a9427484c8fe06f19dce02e9e7bac02 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 16:28:04 -0400 Subject: [PATCH 25/43] [text] Update to use new multihead interface --- src/plugins/splash/text/plugin.c | 635 +++++++++++++++++++++++-------- 1 file changed, 471 insertions(+), 164 deletions(-) diff --git a/src/plugins/splash/text/plugin.c b/src/plugins/splash/text/plugin.c index 60edf491..6ca7ee1b 100644 --- a/src/plugins/splash/text/plugin.c +++ b/src/plugins/splash/text/plugin.c @@ -48,36 +48,270 @@ #include "ply-key-file.h" #include "ply-list.h" #include "ply-logger.h" -#include "ply-frame-buffer.h" -#include "ply-image.h" +#include "ply-text-display.h" #include "ply-text-progress-bar.h" #include "ply-utils.h" -#include "ply-window.h" #include #define CLEAR_LINE_SEQUENCE "\033[2K\r\n" #define BACKSPACE "\b\033[0K" +typedef enum { + PLY_BOOT_SPLASH_DISPLAY_NORMAL, + PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY, + PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY +} ply_boot_splash_display_type_t; struct _ply_boot_splash_plugin { ply_event_loop_t *loop; ply_boot_splash_mode_t mode; - ply_window_t *window; + ply_list_t *views; - ply_text_progress_bar_t *progress_bar; + ply_boot_splash_display_type_t state; char *message; uint32_t is_animating : 1; }; +typedef struct +{ + ply_boot_splash_plugin_t *plugin; + ply_text_display_t *display; + ply_text_progress_bar_t *progress_bar; + +} view_t; + static void hide_splash_screen (ply_boot_splash_plugin_t *plugin, ply_event_loop_t *loop); -static void add_handlers (ply_boot_splash_plugin_t *plugin); -static void remove_handlers (ply_boot_splash_plugin_t *plugin); + +static view_t * +view_new (ply_boot_splash_plugin_t *plugin, + ply_text_display_t *display) +{ + view_t *view; + + view = calloc (1, sizeof (view_t)); + view->plugin = plugin; + view->display = display; + + view->progress_bar = ply_text_progress_bar_new (); + + return view; +} + +static void +view_free (view_t *view) +{ + ply_text_progress_bar_free (view->progress_bar); + + free (view); +} + +static void +view_show_message (view_t *view) +{ + ply_boot_splash_plugin_t *plugin; + int display_width, display_height; + + plugin = view->plugin; + + display_width = ply_text_display_get_number_of_columns (view->display); + display_height = ply_text_display_get_number_of_rows (view->display); + + ply_text_display_set_cursor_position (view->display, 0, + display_height / 2); + ply_text_display_clear_line (view->display); + ply_text_display_set_cursor_position (view->display, + (display_width - + strlen (plugin->message)) / 2, + display_height / 2); + + ply_text_display_write (view->display, "%s", plugin->message); +} + +static void +view_show_prompt (view_t *view, + const char *prompt, + const char *entered_text) +{ + + ply_boot_splash_plugin_t *plugin; + int display_width, display_height; + int i; + + plugin = view->plugin; + + display_width = ply_text_display_get_number_of_columns (view->display); + display_height = ply_text_display_get_number_of_rows (view->display); + ply_text_display_set_background_color (view->display, PLY_TERMINAL_COLOR_DEFAULT); + ply_text_display_clear_screen (view->display); + + ply_text_display_set_cursor_position (view->display, 0, display_height / 2); + + for (i=0; i < display_width; i++) + ply_text_display_write (view->display, "%c", ' '); + + ply_text_display_set_cursor_position (view->display, + display_width / 2 - (strlen (prompt)), + display_height / 2); + + ply_text_display_write (view->display, "%s:%s", prompt, entered_text); + + ply_text_display_show_cursor (view->display); +} + +static void +view_start_animation (view_t *view) +{ + ply_boot_splash_plugin_t *plugin; + ply_terminal_t *terminal; + + assert (view != NULL); + + plugin = view->plugin; + + terminal = ply_text_display_get_terminal (view->display); + + ply_terminal_set_color_hex_value (terminal, + PLY_TERMINAL_COLOR_BLACK, + 0x000000); + ply_terminal_set_color_hex_value (terminal, + PLY_TERMINAL_COLOR_WHITE, + 0xffffff); + ply_terminal_set_color_hex_value (terminal, + PLY_TERMINAL_COLOR_BLUE, + 0x0073B3); + ply_terminal_set_color_hex_value (terminal, + PLY_TERMINAL_COLOR_BROWN, + 0x00457E); + + ply_text_display_set_background_color (view->display, + PLY_TERMINAL_COLOR_BLACK); + ply_text_display_clear_screen (view->display); + ply_text_display_hide_cursor (view->display); + + if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN) + { + ply_text_progress_bar_hide (view->progress_bar); + return; + } + + ply_text_progress_bar_show (view->progress_bar, + view->display); +} + +static void +view_redraw (view_t *view) +{ + unsigned long screen_width, screen_height; + + screen_width = ply_text_display_get_number_of_columns (view->display); + screen_height = ply_text_display_get_number_of_rows (view->display); + + ply_text_display_draw_area (view->display, 0, 0, + screen_width, screen_height); +} + +static void +redraw_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_redraw (view); + + node = next_node; + } +} + +static void +view_hide (view_t *view) +{ + if (view->display != NULL) + { + ply_terminal_t *terminal; + + terminal = ply_text_display_get_terminal (view->display); + + ply_text_display_set_background_color (view->display, PLY_TERMINAL_COLOR_DEFAULT); + ply_text_display_clear_screen (view->display); + ply_text_display_show_cursor (view->display); + + ply_terminal_reset_colors (terminal); + } +} + +static void +hide_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_hide (view); + + node = next_node; + } +} + +static void +pause_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_text_display_pause_updates (view->display); + + node = next_node; + } +} + +static void +unpause_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_text_display_unpause_updates (view->display); + + node = next_node; + } +} static ply_boot_splash_plugin_t * create_plugin (ply_key_file_t *key_file) @@ -87,9 +321,10 @@ create_plugin (ply_key_file_t *key_file) ply_trace ("creating plugin"); plugin = calloc (1, sizeof (ply_boot_splash_plugin_t)); - plugin->progress_bar = ply_text_progress_bar_new (); plugin->message = NULL; + plugin->views = ply_list_new (); + return plugin; } @@ -101,6 +336,31 @@ detach_from_event_loop (ply_boot_splash_plugin_t *plugin) ply_trace ("detaching from event loop"); } +static void +free_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_free (view); + ply_list_remove_node (plugin->views, node); + + node = next_node; + } + + ply_list_free (plugin->views); + plugin->views = NULL; +} + static void destroy_plugin (ply_boot_splash_plugin_t *plugin) { @@ -109,14 +369,12 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin) if (plugin == NULL) return; - remove_handlers (plugin); - /* It doesn't ever make sense to keep this plugin on screen * after exit */ hide_splash_screen (plugin, plugin->loop); - ply_text_progress_bar_free (plugin->progress_bar); + free_views (plugin); if (plugin->message != NULL) free (plugin->message); @@ -126,67 +384,52 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin) static void show_message (ply_boot_splash_plugin_t *plugin) { - int window_width, window_height; + ply_list_node_t *node; - window_width = ply_window_get_number_of_text_columns (plugin->window); - window_height = ply_window_get_number_of_text_rows (plugin->window); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; - ply_window_set_text_cursor_position (plugin->window, - 0, window_height / 2); - ply_window_clear_text_line (plugin->window); - ply_window_set_text_cursor_position (plugin->window, - (window_width - strlen (plugin->message)) / 2, - window_height / 2); + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); - write (STDOUT_FILENO, plugin->message, strlen (plugin->message)); + view_show_message (view); + + node = next_node; + } } static void start_animation (ply_boot_splash_plugin_t *plugin) { + ply_list_node_t *node; assert (plugin != NULL); assert (plugin->loop != NULL); + redraw_views (plugin); + if (plugin->message != NULL) show_message (plugin); if (plugin->is_animating) return; - ply_window_set_color_hex_value (plugin->window, - PLY_WINDOW_COLOR_BLACK, - 0x000000); - ply_window_set_color_hex_value (plugin->window, - PLY_WINDOW_COLOR_WHITE, - 0xffffff); - ply_window_set_color_hex_value (plugin->window, - PLY_WINDOW_COLOR_BLUE, - 0x0073B3); - ply_window_set_color_hex_value (plugin->window, - PLY_WINDOW_COLOR_BROWN, - 0x00457E); -#if 0 - ply_window_set_color_hex_value (plugin->window, - PLY_WINDOW_COLOR_BLUE, - PLYMOUTH_BACKGROUND_START_COLOR); - ply_window_set_color_hex_value (plugin->window, - PLY_WINDOW_COLOR_GREEN, - PLYMOUTH_BACKGROUND_COLOR); -#endif - - ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_BLACK); - ply_window_clear_screen (plugin->window); - ply_window_hide_text_cursor (plugin->window); - - if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN) + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { - ply_text_progress_bar_hide (plugin->progress_bar); - return; - } + ply_list_node_t *next_node; + view_t *view; - ply_text_progress_bar_show (plugin->progress_bar, - plugin->window); + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_start_animation (view); + + node = next_node; + } plugin->is_animating = true; } @@ -194,6 +437,8 @@ start_animation (ply_boot_splash_plugin_t *plugin) static void stop_animation (ply_boot_splash_plugin_t *plugin) { + ply_list_node_t *node; + assert (plugin != NULL); assert (plugin->loop != NULL); @@ -202,64 +447,97 @@ stop_animation (ply_boot_splash_plugin_t *plugin) plugin->is_animating = false; + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; - ply_text_progress_bar_hide (plugin->progress_bar); + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_text_progress_bar_hide (view->progress_bar); + + node = next_node; + } + redraw_views (plugin); +} + +static void +clear_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + assert (plugin != NULL); + assert (plugin->loop != NULL); + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_text_display_clear_screen (view->display); + + node = next_node; + } } static void on_draw (ply_boot_splash_plugin_t *plugin, + ply_terminal_t *terminal, int x, int y, int width, int height) { - ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_BLUE); - ply_window_clear_screen (plugin->window); + clear_views (plugin); } static void -on_erase (ply_boot_splash_plugin_t *plugin, - int x, - int y, - int width, - int height) +add_text_display (ply_boot_splash_plugin_t *plugin, + ply_text_display_t *display) { - ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_BLUE); - ply_window_clear_screen (plugin->window); + view_t *view; + + view = view_new (plugin, display); + + ply_text_display_set_draw_handler (view->display, + (ply_text_display_draw_handler_t) + on_draw, view); + + ply_list_append_data (plugin->views, view); } static void -add_handlers (ply_boot_splash_plugin_t *plugin) +remove_text_display (ply_boot_splash_plugin_t *plugin, + ply_text_display_t *display) { - ply_window_set_draw_handler (plugin->window, - (ply_window_draw_handler_t) - on_draw, plugin); - ply_window_set_erase_handler (plugin->window, - (ply_window_erase_handler_t) - on_erase, plugin); -} + ply_list_node_t *node; -static void -remove_handlers (ply_boot_splash_plugin_t *plugin) -{ + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; - ply_window_set_draw_handler (plugin->window, NULL, NULL); - ply_window_set_erase_handler (plugin->window, NULL, NULL); + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); -} + if (view->display == display) + { + ply_text_display_set_draw_handler (view->display, + NULL, NULL); + view_free (view); + ply_list_remove_node (plugin->views, node); + return; + } -static void -add_window (ply_boot_splash_plugin_t *plugin, - ply_window_t *window) -{ - plugin->window = window; -} - -static void -remove_window (ply_boot_splash_plugin_t *plugin, - ply_window_t *window) -{ - plugin->window = NULL; + node = next_node; + } } static bool @@ -270,11 +548,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, { assert (plugin != NULL); - add_handlers (plugin); - - ply_window_hide_text_cursor (plugin->window); - ply_window_set_text_cursor_position (plugin->window, 0, 0); - plugin->loop = loop; plugin->mode = mode; ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) @@ -301,15 +574,30 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin, double duration, double percent_done) { + ply_list_node_t *node; double total_duration; total_duration = duration / percent_done; - /* Hi Will! */ + /* Fun made-up smoothing function to make the growth asymptotic: + * fraction(time,estimate)=1-2^(-(time^1.45)/estimate) */ percent_done = 1.0 - pow (2.0, -pow (duration, 1.45) / total_duration) * (1.0 - percent_done); - ply_text_progress_bar_set_percent_done (plugin->progress_bar, percent_done); - ply_text_progress_bar_draw (plugin->progress_bar); + node = ply_list_get_first_node (plugin->views); + + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + 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); + + node = next_node; + } } static void @@ -331,23 +619,21 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin, detach_from_event_loop (plugin); } - if (plugin->window != NULL) - { - remove_handlers (plugin); - - ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_DEFAULT); - ply_window_clear_screen (plugin->window); - ply_window_show_text_cursor (plugin->window); - ply_window_reset_colors (plugin->window); - } - + hide_views (plugin); ply_show_new_kernel_messages (true); } static void display_normal (ply_boot_splash_plugin_t *plugin) { - start_animation(plugin); + pause_views (plugin); + if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_NORMAL) + { + plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL; + start_animation (plugin); + redraw_views (plugin); + } + unpause_views (plugin); } static void @@ -361,40 +647,76 @@ display_message (ply_boot_splash_plugin_t *plugin, start_animation (plugin); } +static void +show_password_prompt (ply_boot_splash_plugin_t *plugin, + const char *prompt, + int bullets) +{ + ply_list_node_t *node; + int i; + char *entered_text; + + entered_text = calloc (bullets + 1, sizeof (char)); + + for (i = 0; i < bullets; i++) + entered_text[i] = '*'; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_show_prompt (view, prompt, entered_text); + + node = next_node; + } + free (entered_text); +} + +static void +show_prompt (ply_boot_splash_plugin_t *plugin, + const char *prompt, + const char *text) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_show_prompt (view, prompt, text); + + node = next_node; + } +} + static void display_password (ply_boot_splash_plugin_t *plugin, const char *prompt, int bullets) { - int window_width, window_height; - int i; - stop_animation (plugin); - ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_DEFAULT); - ply_window_clear_screen (plugin->window); + pause_views (plugin); + if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) + stop_animation (plugin); - window_width = ply_window_get_number_of_text_columns (plugin->window); - window_height = ply_window_get_number_of_text_rows (plugin->window); - - if (!prompt) - prompt = "Password"; - - ply_window_set_text_cursor_position (plugin->window, 0, window_height / 2); - - for (i=0; i < window_width; i++) - { - write (STDOUT_FILENO, " ", strlen (" ")); - } - ply_window_set_text_cursor_position (plugin->window, - window_width / 2 - (strlen (prompt)), - window_height / 2); - write (STDOUT_FILENO, prompt, strlen (prompt)); - write (STDOUT_FILENO, ":", strlen (":")); - - for (i=0; i < bullets; i++) - { - write (STDOUT_FILENO, "*", strlen ("*")); - } - ply_window_show_text_cursor (plugin->window); + plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY; + + if (!prompt) + prompt = "Password"; + + show_password_prompt (plugin, prompt, bullets); + + redraw_views (plugin); + unpause_views (plugin); } static void @@ -402,36 +724,21 @@ display_question (ply_boot_splash_plugin_t *plugin, const char *prompt, const char *entry_text) { - int window_width, window_height; - int i; - stop_animation (plugin); - ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_DEFAULT); - ply_window_clear_screen (plugin->window); + pause_views (plugin); + if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) + stop_animation (plugin); - window_width = ply_window_get_number_of_text_columns (plugin->window); - window_height = ply_window_get_number_of_text_rows (plugin->window); - - if (!prompt) - prompt = ""; - - ply_window_set_text_cursor_position (plugin->window, - 0, window_height / 2); - - for (i=0; i < window_width; i++) - { - write (STDOUT_FILENO, " ", strlen (" ")); - } - ply_window_set_text_cursor_position (plugin->window, - window_width / 2 - (strlen (prompt)), - window_height / 2); - write (STDOUT_FILENO, prompt, strlen (prompt)); - write (STDOUT_FILENO, ":", strlen (":")); - - write (STDOUT_FILENO, entry_text, strlen (entry_text)); - ply_window_show_text_cursor (plugin->window); + plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY; + + if (!prompt) + prompt = "Password"; + + show_prompt (plugin, prompt, entry_text); + + redraw_views (plugin); + unpause_views (plugin); } - ply_boot_splash_plugin_interface_t * ply_boot_splash_plugin_get_interface (void) { @@ -439,8 +746,8 @@ ply_boot_splash_plugin_get_interface (void) { .create_plugin = create_plugin, .destroy_plugin = destroy_plugin, - .add_window = add_window, - .remove_window = remove_window, + .add_text_display = add_text_display, + .remove_text_display = remove_text_display, .show_splash_screen = show_splash_screen, .update_status = update_status, .on_boot_progress = on_boot_progress, From 1a516d3635ead9e499b5daa4c5d056e2552f2f0f Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 16:28:04 -0400 Subject: [PATCH 26/43] [throbgress] Update to use new multihead interface --- src/plugins/splash/throbgress/plugin.c | 758 ++++++++++++++++--------- 1 file changed, 496 insertions(+), 262 deletions(-) diff --git a/src/plugins/splash/throbgress/plugin.c b/src/plugins/splash/throbgress/plugin.c index 89986274..02b334df 100644 --- a/src/plugins/splash/throbgress/plugin.c +++ b/src/plugins/splash/throbgress/plugin.c @@ -49,16 +49,14 @@ #include "ply-list.h" #include "ply-progress-bar.h" #include "ply-logger.h" -#include "ply-frame-buffer.h" #include "ply-image.h" #include "ply-trigger.h" +#include "ply-pixel-buffer.h" +#include "ply-pixel-display.h" #include "ply-utils.h" -#include "ply-window.h" #include "ply-throbber.h" -#include - #ifndef FRAMES_PER_SECOND #define FRAMES_PER_SECOND 30 #endif @@ -73,21 +71,27 @@ typedef enum { PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY } ply_boot_splash_display_type_t; +typedef struct +{ + ply_boot_splash_plugin_t *plugin; + ply_pixel_display_t *display; + ply_entry_t *entry; + ply_throbber_t *throbber; + ply_progress_bar_t *progress_bar; + ply_label_t *label; + ply_rectangle_t box_area, lock_area, logo_area, bar_area; +} view_t; + struct _ply_boot_splash_plugin { ply_event_loop_t *loop; ply_boot_splash_mode_t mode; - ply_frame_buffer_t *frame_buffer; - ply_frame_buffer_area_t box_area, lock_area, logo_area, bar_area; ply_image_t *logo_image; ply_image_t *lock_image; ply_image_t *box_image; - ply_window_t *window; + ply_list_t *views; - ply_entry_t *entry; - ply_throbber_t *throbber; - ply_label_t *label; - ply_progress_bar_t *progress_bar; + char *image_dir; ply_boot_splash_display_type_t state; ply_trigger_t *idle_trigger; @@ -97,11 +101,276 @@ struct _ply_boot_splash_plugin uint32_t is_animating : 1; }; -static void add_handlers (ply_boot_splash_plugin_t *plugin); -static void remove_handlers (ply_boot_splash_plugin_t *plugin); - static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin); +static view_t * +view_new (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) +{ + view_t *view; + + view = calloc (1, sizeof (view_t)); + view->plugin = plugin; + view->display = display; + + view->entry = ply_entry_new (plugin->image_dir); + view->throbber = ply_throbber_new (plugin->image_dir, + "throbber-"); + view->progress_bar = ply_progress_bar_new (); + view->label = ply_label_new (); + + return view; +} + +static void +view_free (view_t *view) +{ + + ply_entry_free (view->entry); + ply_throbber_free (view->throbber); + ply_progress_bar_free (view->progress_bar); + ply_label_free (view->label); + + free (view); +} + +static void +free_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_free (view); + ply_list_remove_node (plugin->views, node); + + node = next_node; + } + + ply_list_free (plugin->views); + plugin->views = NULL; +} + +static bool +view_load (view_t *view) +{ + ply_trace ("loading entry"); + if (!ply_entry_load (view->entry)) + return false; + + ply_trace ("loading throbber"); + if (!ply_throbber_load (view->throbber)) + return false; + + return true; +} + +static bool +load_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + bool view_loaded; + + view_loaded = false; + node = ply_list_get_first_node (plugin->views); + + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view_load (view)) + view_loaded = true; + + node = next_node; + } + + return view_loaded; +} + +static void +view_redraw (view_t *view) +{ + unsigned long screen_width, screen_height; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + ply_pixel_display_draw_area (view->display, 0, 0, + screen_width, screen_height); +} + +static void +redraw_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_redraw (view); + + node = next_node; + } +} + +static void +pause_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_pixel_display_pause_updates (view->display); + + node = next_node; + } +} + +static void +unpause_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_pixel_display_unpause_updates (view->display); + + node = next_node; + } +} + +static void +view_start_animation (view_t *view) +{ + ply_boot_splash_plugin_t *plugin; + + unsigned long screen_width, screen_height; + long width, height; + + assert (view != NULL); + + plugin = view->plugin; + + assert (plugin != NULL); + assert (plugin->loop != NULL); + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + ply_pixel_display_draw_area (view->display, 0, 0, + screen_width, screen_height); + + if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN) + return; + + width = ply_throbber_get_width (view->throbber); + height = ply_throbber_get_height (view->throbber); + ply_throbber_start (view->throbber, + plugin->loop, + view->display, + screen_width / 2.0 - width / 2.0, + view->logo_area.y + view->logo_area.height + height / 2); + ply_progress_bar_show (view->progress_bar, + view->display, + 0, screen_height - ply_progress_bar_get_height (view->progress_bar)); + view_redraw (view); +} + +static void +view_show_prompt (view_t *view, + const char *prompt) +{ + ply_boot_splash_plugin_t *plugin; + int x, y; + int entry_width, entry_height; + + assert (view != NULL); + + plugin = view->plugin; + + if (ply_entry_is_hidden (view->entry)) + { + unsigned long screen_width, screen_height; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + view->box_area.width = ply_image_get_width (plugin->box_image); + view->box_area.height = ply_image_get_height (plugin->box_image); + view->box_area.x = screen_width / 2.0 - view->box_area.width / 2.0; + view->box_area.y = screen_height / 2.0 - view->box_area.height / 2.0; + + view->lock_area.width = ply_image_get_width (plugin->lock_image); + view->lock_area.height = ply_image_get_height (plugin->lock_image); + + entry_width = ply_entry_get_width (view->entry); + entry_height = ply_entry_get_height (view->entry); + + x = screen_width / 2.0 - (view->lock_area.width + entry_width) / 2.0 + view->lock_area.width; + y = screen_height / 2.0 - entry_height / 2.0; + + view->lock_area.x = screen_width / 2.0 - (view->lock_area.width + entry_width) / 2.0; + view->lock_area.y = screen_height / 2.0 - view->lock_area.height / 2.0; + + ply_entry_show (view->entry, plugin->loop, view->display, x, y); + } + + if (prompt != NULL) + { + int label_width, label_height; + + ply_label_set_text (view->label, prompt); + label_width = ply_label_get_width (view->label); + label_height = ply_label_get_height (view->label); + + x = view->box_area.x + view->lock_area.width / 2; + y = view->box_area.y + view->box_area.height; + + ply_label_show (view->label, view->display, x, y); + } +} + +static void +view_hide_prompt (view_t *view) +{ + assert (view != NULL); + + ply_entry_hide (view->entry); + ply_label_hide (view->label); +} + static ply_boot_splash_plugin_t * create_plugin (ply_key_file_t *key_file) { @@ -122,11 +391,8 @@ create_plugin (ply_key_file_t *key_file) plugin->box_image = ply_image_new (image_path); free (image_path); - plugin->entry = ply_entry_new (image_dir); - plugin->throbber = ply_throbber_new (image_dir, "throbber-"); - plugin->label = ply_label_new (); - plugin->progress_bar = ply_progress_bar_new (); - free(image_dir); + plugin->image_dir = image_dir; + plugin->views = ply_list_new (); return plugin; } @@ -137,8 +403,6 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin) if (plugin == NULL) return; - remove_handlers (plugin); - if (plugin->loop != NULL) { ply_event_loop_stop_watching_for_exit (plugin->loop, (ply_event_loop_exit_handler_t) @@ -150,83 +414,83 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin) ply_image_free (plugin->logo_image); ply_image_free (plugin->box_image); ply_image_free (plugin->lock_image); - ply_entry_free (plugin->entry); - ply_throbber_free (plugin->throbber); - ply_label_free (plugin->label); - ply_progress_bar_free (plugin->progress_bar); + + free_views (plugin); free (plugin); } static void -draw_background (ply_boot_splash_plugin_t *plugin, - ply_frame_buffer_area_t *area) +draw_background (view_t *view, + ply_pixel_buffer_t *pixel_buffer, + int x, + int y, + int width, + int height) { - ply_frame_buffer_area_t screen_area; + ply_boot_splash_plugin_t *plugin; + ply_rectangle_t area; - if (area == NULL) - { - ply_frame_buffer_get_size (plugin->frame_buffer, &screen_area); - area = &screen_area; - } + plugin = view->plugin; - ply_window_erase_area (plugin->window, area->x, area->y, - area->width, area->height); + area.x = x; + area.y = y; + area.width = width; + area.height = height; + + ply_pixel_buffer_fill_with_gradient (pixel_buffer, &area, + PLYMOUTH_BACKGROUND_START_COLOR, + PLYMOUTH_BACKGROUND_END_COLOR); } static void -draw_logo (ply_boot_splash_plugin_t *plugin) +draw_logo (view_t *view, + ply_pixel_buffer_t *pixel_buffer) { + ply_boot_splash_plugin_t *plugin; uint32_t *logo_data; + unsigned long screen_width, screen_height; long width, height; + plugin = view->plugin; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + width = ply_image_get_width (plugin->logo_image); height = ply_image_get_height (plugin->logo_image); logo_data = ply_image_get_data (plugin->logo_image); - ply_frame_buffer_get_size (plugin->frame_buffer, &plugin->logo_area); - plugin->logo_area.x = (plugin->logo_area.width / 2) - (width / 2); - plugin->logo_area.y = (plugin->logo_area.height / 2) - (height / 2); - plugin->logo_area.width = width; - plugin->logo_area.height = height; + view->logo_area.x = (screen_width / 2) - (width / 2); + view->logo_area.y = (screen_height / 2) - (height / 2); + view->logo_area.width = width; + view->logo_area.height = height; - ply_frame_buffer_pause_updates (plugin->frame_buffer); - draw_background (plugin, &plugin->logo_area); - ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer, - &plugin->logo_area, 0, 0, + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, + &view->logo_area, 0, 0, logo_data); - ply_frame_buffer_unpause_updates (plugin->frame_buffer); } static void start_animation (ply_boot_splash_plugin_t *plugin) { - - long width, height; - ply_frame_buffer_area_t area; - assert (plugin != NULL); - assert (plugin->loop != NULL); + ply_list_node_t *node; if (plugin->is_animating) return; - draw_background (plugin, NULL); - draw_logo (plugin); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; - if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN) - return; + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); - ply_frame_buffer_get_size (plugin->frame_buffer, &area); + view_start_animation (view); - width = ply_throbber_get_width (plugin->throbber); - height = ply_throbber_get_height (plugin->throbber); - ply_throbber_start (plugin->throbber, - plugin->loop, - plugin->window, - area.width / 2.0 - width / 2.0, - plugin->logo_area.y + plugin->logo_area.height + height / 2); - ply_progress_bar_show (plugin->progress_bar, - plugin->window, - 0, area.height - ply_progress_bar_get_height (plugin->progress_bar)); + node = next_node; + } plugin->is_animating = true; } @@ -235,6 +499,8 @@ static void stop_animation (ply_boot_splash_plugin_t *plugin, ply_trigger_t *trigger) { + ply_list_node_t *node; + assert (plugin != NULL); assert (plugin->loop != NULL); @@ -243,30 +509,25 @@ stop_animation (ply_boot_splash_plugin_t *plugin, plugin->is_animating = false; - ply_progress_bar_hide (plugin->progress_bar); - ply_throbber_stop (plugin->throbber, trigger); - -#ifdef ENABLE_FADE_OUT - int i; - for (i = 0; i < 10; i++) + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { - ply_frame_buffer_fill_with_hex_color_at_opacity (plugin->frame_buffer, NULL, - PLYMOUTH_BACKGROUND_COLOR, - .1 + .1 * i); + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_progress_bar_hide (view->progress_bar); + if (trigger != NULL) + ply_trigger_ignore_next_pull (trigger); + ply_throbber_stop (view->throbber, trigger); + + node = next_node; } - ply_frame_buffer_fill_with_hex_color (plugin->frame_buffer, NULL, - PLYMOUTH_BACKGROUND_COLOR); - - for (i = 0; i < 20; i++) - { - ply_frame_buffer_fill_with_color (plugin->frame_buffer, NULL, - 0.0, 0.0, 0.0, .05 + .05 * i); - } - - ply_frame_buffer_fill_with_color (plugin->frame_buffer, NULL, - 0.0, 0.0, 0.0, 1.0); -#endif + if (trigger != NULL) + ply_trigger_pull (trigger, NULL); } static void @@ -274,7 +535,6 @@ on_interrupt (ply_boot_splash_plugin_t *plugin) { ply_event_loop_exit (plugin->loop, 1); stop_animation (plugin, NULL); - ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT); } static void @@ -283,119 +543,93 @@ detach_from_event_loop (ply_boot_splash_plugin_t *plugin) plugin->loop = NULL; } -void -on_keyboard_input (ply_boot_splash_plugin_t *plugin, - const char *keyboard_input, - size_t character_size) -{ -} - -void -on_backspace (ply_boot_splash_plugin_t *plugin) -{ -} - -void -on_enter (ply_boot_splash_plugin_t *plugin, - const char *text) -{ -} - -void -on_draw (ply_boot_splash_plugin_t *plugin, +static void +on_draw (view_t *view, + ply_pixel_buffer_t *pixel_buffer, int x, int y, int width, int height) { - ply_frame_buffer_area_t area; + ply_boot_splash_plugin_t *plugin; + ply_rectangle_t area; area.x = x; area.y = y; area.width = width; area.height = height; - ply_frame_buffer_pause_updates (plugin->frame_buffer); - draw_background (plugin, &area); + plugin = view->plugin; - if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY || + draw_background (view, pixel_buffer, x, y, width, height); + + if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY || plugin->state == PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY ) { - ply_entry_draw (plugin->entry); - ply_label_draw (plugin->label); + uint32_t *box_data, *lock_data; + + box_data = ply_image_get_data (plugin->box_image); + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, + &view->box_area, 0, 0, + box_data); + ply_entry_draw_area (view->entry, pixel_buffer, x, y, width, height); + ply_label_draw_area (view->label, pixel_buffer, x, y, width, height); + lock_data = ply_image_get_data (plugin->lock_image); + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, + &view->lock_area, 0, 0, + lock_data); } else { - draw_logo (plugin); - ply_progress_bar_draw (plugin->progress_bar); + draw_logo (view, pixel_buffer); + ply_throbber_draw_area (view->throbber, + pixel_buffer, x, y, width, height); + ply_progress_bar_draw_area (view->progress_bar, + pixel_buffer, x, y, width, height); } - ply_frame_buffer_unpause_updates (plugin->frame_buffer); -} - -void -on_erase (ply_boot_splash_plugin_t *plugin, - int x, - int y, - int width, - int height) -{ - ply_frame_buffer_area_t area; - - area.x = x; - area.y = y; - area.width = width; - area.height = height; - - ply_frame_buffer_fill_with_gradient (plugin->frame_buffer, &area, - PLYMOUTH_BACKGROUND_START_COLOR, - PLYMOUTH_BACKGROUND_END_COLOR); } static void -add_handlers (ply_boot_splash_plugin_t *plugin) +add_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) { - ply_window_add_keyboard_input_handler (plugin->window, - (ply_window_keyboard_input_handler_t) - on_keyboard_input, plugin); - ply_window_add_backspace_handler (plugin->window, - (ply_window_backspace_handler_t) - on_backspace, plugin); - ply_window_add_enter_handler (plugin->window, - (ply_window_enter_handler_t) - on_enter, plugin); + view_t *view; - ply_window_set_draw_handler (plugin->window, - (ply_window_draw_handler_t) - on_draw, plugin); + view = view_new (plugin, display); - ply_window_set_erase_handler (plugin->window, - (ply_window_erase_handler_t) - on_erase, 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); } static void -remove_handlers (ply_boot_splash_plugin_t *plugin) +remove_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) { + ply_list_node_t *node; - ply_window_remove_keyboard_input_handler (plugin->window, (ply_window_keyboard_input_handler_t) on_keyboard_input); - ply_window_remove_backspace_handler (plugin->window, (ply_window_backspace_handler_t) on_backspace); - ply_window_remove_enter_handler (plugin->window, (ply_window_enter_handler_t) on_enter); - ply_window_set_draw_handler (plugin->window, NULL, NULL); - ply_window_set_erase_handler (plugin->window, NULL, NULL); -} + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; -static void -add_window (ply_boot_splash_plugin_t *plugin, - ply_window_t *window) -{ - plugin->window = window; -} + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); -static void -remove_window (ply_boot_splash_plugin_t *plugin, - ply_window_t *window) -{ - plugin->window = NULL; + 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; + } + + node = next_node; + } } static bool @@ -407,8 +641,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, assert (plugin != NULL); assert (plugin->logo_image != NULL); - add_handlers (plugin); - plugin->loop = loop; plugin->mode = mode; @@ -424,19 +656,11 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, if (!ply_image_load (plugin->box_image)) return false; - ply_trace ("loading entry"); - if (!ply_entry_load (plugin->entry)) - return false; - - ply_trace ("loading throbber"); - if (!ply_throbber_load (plugin->throbber)) - return false; - - ply_trace ("setting graphics mode"); - if (!ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS)) - return false; - - plugin->frame_buffer = ply_window_get_frame_buffer (plugin->window); + if (!load_views (plugin)) + { + ply_trace ("couldn't load views"); + return false; + } ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) detach_from_event_loop, @@ -447,9 +671,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, (ply_event_handler_t) on_interrupt, plugin); - ply_window_clear_screen (plugin->window); - ply_window_hide_text_cursor (plugin->window); - ply_trace ("starting boot animation"); start_animation (plugin); @@ -470,6 +691,7 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin, double duration, double percent_done) { + ply_list_node_t *node; double total_duration; total_duration = duration / percent_done; @@ -478,8 +700,21 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin, * fraction(time,estimate)=1-2^(-(time^1.45)/estimate) */ percent_done = 1.0 - pow (2.0, -pow (duration, 1.45) / total_duration) * (1.0 - percent_done); - ply_progress_bar_set_percent_done (plugin->progress_bar, percent_done); - ply_progress_bar_draw (plugin->progress_bar); + node = ply_list_get_first_node (plugin->views); + + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_progress_bar_set_percent_done (view->progress_bar, percent_done); + ply_progress_bar_draw (view->progress_bar); + + node = next_node; + } } static void @@ -488,8 +723,6 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin, { assert (plugin != NULL); - remove_handlers (plugin); - if (plugin->loop != NULL) { stop_animation (plugin, NULL); @@ -500,76 +733,53 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin, detach_from_event_loop (plugin); } - plugin->frame_buffer = NULL; plugin->is_visible = false; - - ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT); } static void show_password_prompt (ply_boot_splash_plugin_t *plugin, - const char *prompt) + const char *text, + int number_of_bullets) { - ply_frame_buffer_area_t area; - int x, y; - int entry_width, entry_height; + ply_list_node_t *node; - uint32_t *box_data, *lock_data; - - assert (plugin != NULL); - - if (ply_entry_is_hidden (plugin->entry)) + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { - draw_background (plugin, NULL); + ply_list_node_t *next_node; + view_t *view; - ply_frame_buffer_get_size (plugin->frame_buffer, &area); - plugin->box_area.width = ply_image_get_width (plugin->box_image); - plugin->box_area.height = ply_image_get_height (plugin->box_image); - plugin->box_area.x = area.width / 2.0 - plugin->box_area.width / 2.0; - plugin->box_area.y = area.height / 2.0 - plugin->box_area.height / 2.0; + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); - plugin->lock_area.width = ply_image_get_width (plugin->lock_image); - plugin->lock_area.height = ply_image_get_height (plugin->lock_image); + view_show_prompt (view, text); + ply_entry_set_bullet_count (view->entry, number_of_bullets); - entry_width = ply_entry_get_width (plugin->entry); - entry_height = ply_entry_get_height (plugin->entry); - - x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0 + plugin->lock_area.width; - y = area.height / 2.0 - entry_height / 2.0; - - plugin->lock_area.x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0; - plugin->lock_area.y = area.height / 2.0 - plugin->lock_area.height / 2.0; - - box_data = ply_image_get_data (plugin->box_image); - ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer, - &plugin->box_area, 0, 0, - box_data); - - ply_entry_show (plugin->entry, plugin->loop, plugin->window, x, y); - - lock_data = ply_image_get_data (plugin->lock_image); - ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer, - &plugin->lock_area, 0, 0, - lock_data); + node = next_node; } - else +} + +static void +show_prompt (ply_boot_splash_plugin_t *plugin, + const char *prompt, + const char *entry_text) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { - ply_entry_draw (plugin->entry); + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_show_prompt (view, prompt); + ply_entry_set_text (view->entry, entry_text); + + node = next_node; } - if (prompt != NULL) - { - int label_width, label_height; - - ply_label_set_text (plugin->label, prompt); - label_width = ply_label_get_width (plugin->label); - label_height = ply_label_get_height (plugin->label); - - x = plugin->box_area.x + plugin->lock_area.width / 2; - y = plugin->box_area.y + plugin->box_area.height; - - ply_label_show (plugin->label, plugin->window, x, y); - } - } static void @@ -585,15 +795,38 @@ become_idle (ply_boot_splash_plugin_t *plugin, stop_animation (plugin, idle_trigger); } +static void +hide_prompt (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_hide_prompt (view); + + node = next_node; + } +} + static void display_normal (ply_boot_splash_plugin_t *plugin) { + pause_views (plugin); if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_NORMAL) { plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL; - ply_entry_hide (plugin->entry); - start_animation(plugin); + hide_prompt (plugin); + start_animation (plugin); + redraw_views (plugin); } + unpause_views (plugin); } static void @@ -601,13 +834,14 @@ display_password (ply_boot_splash_plugin_t *plugin, const char *prompt, int bullets) { + pause_views (plugin); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) - { - stop_animation (plugin, NULL); - } + stop_animation (plugin, NULL); + plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY; - show_password_prompt (plugin, prompt); - ply_entry_set_bullet_count (plugin->entry, bullets); + show_password_prompt (plugin, prompt, bullets); + redraw_views (plugin); + unpause_views (plugin); } static void @@ -615,14 +849,14 @@ display_question (ply_boot_splash_plugin_t *plugin, const char *prompt, const char *entry_text) { + pause_views (plugin); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) - { - stop_animation (plugin, NULL); - } + stop_animation (plugin, NULL); plugin->state = PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY; - show_password_prompt (plugin, prompt); - ply_entry_set_text (plugin->entry, entry_text); + show_prompt (plugin, prompt, entry_text); + redraw_views (plugin); + unpause_views (plugin); } ply_boot_splash_plugin_interface_t * @@ -632,8 +866,8 @@ ply_boot_splash_plugin_get_interface (void) { .create_plugin = create_plugin, .destroy_plugin = destroy_plugin, - .add_window = add_window, - .remove_window = remove_window, + .add_pixel_display = add_pixel_display, + .remove_pixel_display = remove_pixel_display, .show_splash_screen = show_splash_screen, .update_status = update_status, .on_boot_progress = on_boot_progress, From dfa457ba50250e104c117cd1bf1fa35878f7d9aa Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 13:39:35 -0400 Subject: [PATCH 27/43] [trigger] add new ignore_next_pull method It can be cumbersome to wait for multiple operations to finish before pulling a trigger. In those cases, one option would be to have a separate trigger for each operation, and then wait until every trigger is pulled before pulling the main trigger. This commit instead allows a trigger to get pulled more than once before it actually fires. By calling ignore_next_pull once for each suboperaton, and immediately pulling the trigger, it won't fire until the last operation finishes. --- src/libply/ply-trigger.c | 15 +++++++++++++++ src/libply/ply-trigger.h | 1 + 2 files changed, 16 insertions(+) diff --git a/src/libply/ply-trigger.c b/src/libply/ply-trigger.c index b1952d71..46ea5477 100644 --- a/src/libply/ply-trigger.c +++ b/src/libply/ply-trigger.c @@ -41,6 +41,7 @@ struct _ply_trigger ply_list_t *closures; ply_trigger_t **free_address; + int ignore_count; }; ply_trigger_t * @@ -51,6 +52,7 @@ ply_trigger_new (ply_trigger_t **free_address) trigger = calloc (1, sizeof (ply_trigger_t)); trigger->free_address = free_address; trigger->closures = ply_list_new (); + trigger->ignore_count = 0; return trigger; } @@ -131,6 +133,12 @@ ply_trigger_remove_handler (ply_trigger_t *trigger, } } +void +ply_trigger_ignore_next_pull (ply_trigger_t *trigger) +{ + trigger->ignore_count++; +} + void ply_trigger_pull (ply_trigger_t *trigger, const void *data) @@ -138,6 +146,13 @@ ply_trigger_pull (ply_trigger_t *trigger, ply_list_node_t *node; assert (trigger != NULL); + assert (trigger->ignore_count >= 0); + + if (trigger->ignore_count > 0) + { + trigger->ignore_count--; + return; + } node = ply_list_get_first_node (trigger->closures); while (node != NULL) diff --git a/src/libply/ply-trigger.h b/src/libply/ply-trigger.h index cf9fbf09..d543f042 100644 --- a/src/libply/ply-trigger.h +++ b/src/libply/ply-trigger.h @@ -44,6 +44,7 @@ void ply_trigger_remove_handler (ply_trigger_t *trigger, void *user_data); void ply_trigger_free (ply_trigger_t *trigger); +void ply_trigger_ignore_next_pull (ply_trigger_t *trigger); void ply_trigger_pull (ply_trigger_t *trigger, const void *data); #endif From 4b64ff4e56fd9c6c1b973f1a889b500262d6aaa6 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 16:28:04 -0400 Subject: [PATCH 28/43] [two-step] Update to use new multihead interface --- src/plugins/splash/two-step/plugin.c | 881 +++++++++++++++++---------- 1 file changed, 576 insertions(+), 305 deletions(-) diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c index 7b70202b..d52a8e4b 100644 --- a/src/plugins/splash/two-step/plugin.c +++ b/src/plugins/splash/two-step/plugin.c @@ -47,12 +47,12 @@ #include "ply-label.h" #include "ply-list.h" #include "ply-logger.h" -#include "ply-frame-buffer.h" #include "ply-image.h" #include "ply-key-file.h" #include "ply-trigger.h" +#include "ply-pixel-buffer.h" +#include "ply-pixel-display.h" #include "ply-utils.h" -#include "ply-window.h" #include "ply-animation.h" #include "ply-progress-animation.h" @@ -73,21 +73,26 @@ typedef enum { PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY } ply_boot_splash_display_type_t; +typedef struct +{ + ply_boot_splash_plugin_t *plugin; + ply_pixel_display_t *display; + ply_entry_t *entry; + ply_animation_t *end_animation; + ply_progress_animation_t *progress_animation; + ply_label_t *label; + ply_rectangle_t box_area, lock_area; +} view_t; + struct _ply_boot_splash_plugin { ply_event_loop_t *loop; ply_boot_splash_mode_t mode; - ply_frame_buffer_t *frame_buffer; - ply_frame_buffer_area_t box_area, lock_area; ply_image_t *lock_image; ply_image_t *box_image; ply_image_t *corner_image; - ply_window_t *window; + ply_list_t *views; - ply_entry_t *entry; - ply_animation_t *animation; - ply_progress_animation_t *progress_animation; - ply_label_t *label; ply_boot_splash_display_type_t state; double animation_horizontal_alignment; @@ -109,12 +114,287 @@ struct _ply_boot_splash_plugin uint32_t is_idle : 1; }; -static void add_handlers (ply_boot_splash_plugin_t *plugin); -static void remove_handlers (ply_boot_splash_plugin_t *plugin); static void stop_animation (ply_boot_splash_plugin_t *plugin); static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin); +static view_t * +view_new (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) +{ + view_t *view; + + view = calloc (1, sizeof (view_t)); + view->plugin = plugin; + view->display = display; + + view->entry = ply_entry_new (plugin->animation_dir); + view->end_animation = ply_animation_new (plugin->animation_dir, + "throbber-"); + view->progress_animation = ply_progress_animation_new (plugin->animation_dir, + "progress-"); + ply_progress_animation_set_transition (view->progress_animation, + plugin->transition, + plugin->transition_duration); + + view->label = ply_label_new (); + + return view; +} + +static void +view_free (view_t *view) +{ + + ply_entry_free (view->entry); + ply_animation_free (view->end_animation); + ply_progress_animation_free (view->progress_animation); + ply_label_free (view->label); + + free (view); +} + +static bool +view_load (view_t *view) +{ + ply_trace ("loading entry"); + if (!ply_entry_load (view->entry)) + return false; + + ply_trace ("loading animation"); + if (!ply_animation_load (view->end_animation)) + return false; + + ply_trace ("loading progress animation"); + if (!ply_progress_animation_load (view->progress_animation)) + return false; + + return true; +} + +static bool +load_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + bool view_loaded; + + view_loaded = false; + node = ply_list_get_first_node (plugin->views); + + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view_load (view)) + view_loaded = true; + + node = next_node; + } + + return view_loaded; +} + +static void +view_redraw (view_t *view) +{ + unsigned long screen_width, screen_height; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + ply_pixel_display_draw_area (view->display, 0, 0, + screen_width, screen_height); +} + +static void +redraw_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_redraw (view); + + node = next_node; + } +} + +static void +pause_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_pixel_display_pause_updates (view->display); + + node = next_node; + } +} + +static void +unpause_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_pixel_display_unpause_updates (view->display); + + node = next_node; + } +} + +static void +view_start_end_animation (view_t *view, + ply_trigger_t *trigger) +{ + ply_boot_splash_plugin_t *plugin; + + long x, y; + long width, height; + unsigned long screen_width, screen_height; + + plugin = view->plugin; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + width = ply_animation_get_width (view->end_animation); + height = ply_animation_get_height (view->end_animation); + x = plugin->animation_horizontal_alignment * screen_width - width / 2.0; + y = plugin->animation_vertical_alignment * screen_height - height / 2.0; + + ply_animation_start (view->end_animation, + plugin->loop, + view->display, + trigger, x, y); +} + +static void +view_start_progress_animation (view_t *view) +{ + ply_boot_splash_plugin_t *plugin; + + long x, y; + long width, height; + unsigned long screen_width, screen_height; + + assert (view != NULL); + + plugin = view->plugin; + + plugin->is_idle = false; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + ply_pixel_display_draw_area (view->display, 0, 0, + screen_width, screen_height); + + if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN) + { + view_start_end_animation (view, NULL); + return; + } + + width = ply_progress_animation_get_width (view->progress_animation); + height = ply_progress_animation_get_height (view->progress_animation); + x = plugin->animation_horizontal_alignment * screen_width - width / 2.0; + y = plugin->animation_vertical_alignment * screen_height - height / 2.0; + ply_progress_animation_show (view->progress_animation, + view->display, x, y); + + ply_pixel_display_draw_area (view->display, x, y, width, height); +} + +static void +view_show_prompt (view_t *view, + const char *prompt) +{ + ply_boot_splash_plugin_t *plugin; + int x, y; + int entry_width, entry_height; + + assert (view != NULL); + + plugin = view->plugin; + + if (ply_entry_is_hidden (view->entry)) + { + unsigned long screen_width, screen_height; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + view->box_area.width = ply_image_get_width (plugin->box_image); + view->box_area.height = ply_image_get_height (plugin->box_image); + view->box_area.x = screen_width / 2.0 - view->box_area.width / 2.0; + view->box_area.y = screen_height / 2.0 - view->box_area.height / 2.0; + + view->lock_area.width = ply_image_get_width (plugin->lock_image); + view->lock_area.height = ply_image_get_height (plugin->lock_image); + + entry_width = ply_entry_get_width (view->entry); + entry_height = ply_entry_get_height (view->entry); + + x = screen_width / 2.0 - (view->lock_area.width + entry_width) / 2.0 + view->lock_area.width; + y = screen_height / 2.0 - entry_height / 2.0; + + view->lock_area.x = screen_width / 2.0 - (view->lock_area.width + entry_width) / 2.0; + view->lock_area.y = screen_height / 2.0 - view->lock_area.height / 2.0; + + ply_entry_show (view->entry, plugin->loop, view->display, x, y); + } + + if (prompt != NULL) + { + int label_width, label_height; + + ply_label_set_text (view->label, prompt); + label_width = ply_label_get_width (view->label); + label_height = ply_label_get_height (view->label); + + x = view->box_area.x + view->lock_area.width / 2; + y = view->box_area.y + view->box_area.height; + + ply_label_show (view->label, view->display, x, y); + } +} + +static void +view_hide_prompt (view_t *view) +{ + assert (view != NULL); + + ply_entry_hide (view->entry); + ply_label_hide (view->label); +} + static ply_boot_splash_plugin_t * create_plugin (ply_key_file_t *key_file) { @@ -142,8 +422,6 @@ create_plugin (ply_key_file_t *key_file) plugin->corner_image = ply_image_new (image_path); free (image_path); - plugin->entry = ply_entry_new (image_dir); - plugin->label = ply_label_new (); plugin->animation_dir = image_dir; alignment = ply_key_file_get_value (key_file, "two-step", "HorizontalAlignment"); @@ -160,7 +438,6 @@ create_plugin (ply_key_file_t *key_file) plugin->animation_vertical_alignment = .5; free (alignment); - plugin->transition = PLY_PROGRESS_ANIMATION_TRANSITION_NONE; transition = ply_key_file_get_value (key_file, "two-step", "Transition"); if (transition != NULL) @@ -199,17 +476,42 @@ create_plugin (ply_key_file_t *key_file) free (color); + plugin->views = ply_list_new (); + return plugin; } +static void +free_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_free (view); + ply_list_remove_node (plugin->views, node); + + node = next_node; + } + + ply_list_free (plugin->views); + plugin->views = NULL; +} + static void destroy_plugin (ply_boot_splash_plugin_t *plugin) { if (plugin == NULL) return; - remove_handlers (plugin); - if (plugin->loop != NULL) { stop_animation (plugin); @@ -226,86 +528,66 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin) if (plugin->corner_image != NULL) ply_image_free (plugin->corner_image); - ply_entry_free (plugin->entry); - ply_animation_free (plugin->animation); - ply_progress_animation_free (plugin->progress_animation); - ply_label_free (plugin->label); + free_views (plugin); free (plugin); } static void -draw_background (ply_boot_splash_plugin_t *plugin, - ply_frame_buffer_area_t *area) +start_end_animation (ply_boot_splash_plugin_t *plugin, + ply_trigger_t *trigger) { - ply_frame_buffer_area_t screen_area; - if (area == NULL) + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { - ply_frame_buffer_get_size (plugin->frame_buffer, &screen_area); - area = &screen_area; + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_progress_animation_hide (view->progress_animation); + ply_trigger_ignore_next_pull (trigger); + view_start_end_animation (view, trigger); + + node = next_node; } - - ply_window_erase_area (plugin->window, area->x, area->y, - area->width, area->height); + ply_trigger_pull (trigger, NULL); } static void -begin_animation (ply_boot_splash_plugin_t *plugin, - ply_trigger_t *trigger) +start_progress_animation (ply_boot_splash_plugin_t *plugin) { - long width, height; - ply_frame_buffer_area_t area; - ply_frame_buffer_get_size (plugin->frame_buffer, &area); - width = ply_animation_get_width (plugin->animation); - height = ply_animation_get_height (plugin->animation); - ply_animation_start (plugin->animation, - plugin->loop, - plugin->window, - trigger, - plugin->animation_horizontal_alignment * area.width - width / 2.0, - plugin->animation_vertical_alignment * area.height - height / 2.0); -} - -static void -start_animation (ply_boot_splash_plugin_t *plugin) -{ - - long width, height; - ply_frame_buffer_area_t area; - assert (plugin != NULL); - assert (plugin->loop != NULL); + ply_list_node_t *node; if (plugin->is_animating) return; - plugin->is_idle = false; - - draw_background (plugin, NULL); - - if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN) + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { - begin_animation (plugin, NULL); - return; + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_start_progress_animation (view); + + node = next_node; } - ply_frame_buffer_get_size (plugin->frame_buffer, &area); - - width = ply_progress_animation_get_width (plugin->progress_animation); - height = ply_progress_animation_get_height (plugin->progress_animation); - ply_progress_animation_show (plugin->progress_animation, - plugin->window, - plugin->animation_horizontal_alignment * area.width - width / 2.0, - plugin->animation_vertical_alignment * area.height - height / 2.0); - plugin->is_animating = true; - - ply_window_draw_area (plugin->window, 0, 0, area.width, area.height); } static void stop_animation (ply_boot_splash_plugin_t *plugin) { + ply_list_node_t *node; + assert (plugin != NULL); assert (plugin->loop != NULL); @@ -314,29 +596,20 @@ stop_animation (ply_boot_splash_plugin_t *plugin) plugin->is_animating = false; - ply_progress_animation_hide (plugin->progress_animation); - ply_animation_stop (plugin->animation); - -#ifdef ENABLE_FADE_OUT - for (i = 0; i < 10; i++) + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { - ply_frame_buffer_fill_with_hex_color_at_opacity (plugin->frame_buffer, NULL, - PLYMOUTH_BACKGROUND_COLOR, - .1 + .1 * i); + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_progress_animation_hide (view->progress_animation); + ply_animation_stop (view->end_animation); + + node = next_node; } - - ply_frame_buffer_fill_with_hex_color (plugin->frame_buffer, NULL, - PLYMOUTH_BACKGROUND_COLOR); - - for (i = 0; i < 20; i++) - { - ply_frame_buffer_fill_with_color (plugin->frame_buffer, NULL, - 0.0, 0.0, 0.0, .05 + .05 * i); - } - - ply_frame_buffer_fill_with_color (plugin->frame_buffer, NULL, - 0.0, 0.0, 0.0, 1.0); -#endif } static void @@ -344,7 +617,6 @@ on_interrupt (ply_boot_splash_plugin_t *plugin) { ply_event_loop_exit (plugin->loop, 1); stop_animation (plugin); - ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT); } static void @@ -353,78 +625,18 @@ detach_from_event_loop (ply_boot_splash_plugin_t *plugin) plugin->loop = NULL; } -void -on_keyboard_input (ply_boot_splash_plugin_t *plugin, - const char *keyboard_input, - size_t character_size) +static void +draw_background (view_t *view, + ply_pixel_buffer_t *pixel_buffer, + int x, + int y, + int width, + int height) { -} + ply_boot_splash_plugin_t *plugin; + ply_rectangle_t area; -void -on_backspace (ply_boot_splash_plugin_t *plugin) -{ -} - -void -on_enter (ply_boot_splash_plugin_t *plugin, - const char *text) -{ -} - -void -on_draw (ply_boot_splash_plugin_t *plugin, - int x, - int y, - int width, - int height) -{ - ply_frame_buffer_area_t area; - - area.x = x; - area.y = y; - area.width = width; - area.height = height; - - ply_frame_buffer_pause_updates (plugin->frame_buffer); - draw_background (plugin, &area); - - if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY || - plugin->state == PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY ) - { - ply_entry_draw (plugin->entry); - ply_label_draw (plugin->label); - } - else - { - ply_progress_animation_draw (plugin->progress_animation); - - if (plugin->corner_image != NULL) - { - ply_frame_buffer_area_t screen_area; - ply_frame_buffer_area_t image_area; - - ply_frame_buffer_get_size (plugin->frame_buffer, &screen_area); - - image_area.width = ply_image_get_width (plugin->corner_image); - image_area.height = ply_image_get_height (plugin->corner_image); - image_area.x = screen_area.width - image_area.width - 20; - image_area.y = screen_area.height - image_area.height - 20; - - ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer, &image_area, 0, 0, ply_image_get_data (plugin->corner_image)); - - } - } - ply_frame_buffer_unpause_updates (plugin->frame_buffer); -} - -void -on_erase (ply_boot_splash_plugin_t *plugin, - int x, - int y, - int width, - int height) -{ - ply_frame_buffer_area_t area; + plugin = view->plugin; area.x = x; area.y = y; @@ -432,59 +644,125 @@ on_erase (ply_boot_splash_plugin_t *plugin, area.height = height; if (plugin->background_start_color != plugin->background_end_color) - ply_frame_buffer_fill_with_gradient (plugin->frame_buffer, &area, + ply_pixel_buffer_fill_with_gradient (pixel_buffer, &area, plugin->background_start_color, plugin->background_end_color); else - ply_frame_buffer_fill_with_hex_color (plugin->frame_buffer, &area, + ply_pixel_buffer_fill_with_hex_color (pixel_buffer, &area, plugin->background_start_color); } static void -add_handlers (ply_boot_splash_plugin_t *plugin) +on_draw (view_t *view, + ply_pixel_buffer_t *pixel_buffer, + int x, + int y, + int width, + int height) { - ply_window_add_keyboard_input_handler (plugin->window, - (ply_window_keyboard_input_handler_t) - on_keyboard_input, plugin); - ply_window_add_backspace_handler (plugin->window, - (ply_window_backspace_handler_t) - on_backspace, plugin); - ply_window_add_enter_handler (plugin->window, - (ply_window_enter_handler_t) - on_enter, plugin); + ply_boot_splash_plugin_t *plugin; + ply_rectangle_t area; - ply_window_set_draw_handler (plugin->window, - (ply_window_draw_handler_t) - on_draw, plugin); + area.x = x; + area.y = y; + area.width = width; + area.height = height; - ply_window_set_erase_handler (plugin->window, - (ply_window_erase_handler_t) - on_erase, plugin); + plugin = view->plugin; + + draw_background (view, pixel_buffer, x, y, width, height); + + if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY || + plugin->state == PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY ) + { + uint32_t *box_data, *lock_data; + + box_data = ply_image_get_data (plugin->box_image); + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, + &view->box_area, 0, 0, + box_data); + + ply_entry_draw_area (view->entry, + pixel_buffer, + x, y, width, height); + ply_label_draw_area (view->label, + pixel_buffer, + x, y, width, height); + + lock_data = ply_image_get_data (plugin->lock_image); + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, + &view->lock_area, 0, 0, + lock_data); + } + else + { + if (!ply_progress_animation_is_hidden (view->progress_animation)) + ply_progress_animation_draw_area (view->progress_animation, + pixel_buffer, + x, y, width, height); + else if (!ply_animation_is_stopped (view->end_animation)) + ply_animation_draw_area (view->end_animation, + pixel_buffer, + x, y, width, height); + + if (plugin->corner_image != NULL) + { + ply_rectangle_t screen_area; + ply_rectangle_t image_area; + + ply_pixel_buffer_get_size (pixel_buffer, &screen_area); + + image_area.width = ply_image_get_width (plugin->corner_image); + image_area.height = ply_image_get_height (plugin->corner_image); + image_area.x = screen_area.width - image_area.width - 20; + image_area.y = screen_area.height - image_area.height - 20; + + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &image_area, 0, 0, ply_image_get_data (plugin->corner_image)); + + } + } } static void -remove_handlers (ply_boot_splash_plugin_t *plugin) +add_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) { + view_t *view; - ply_window_remove_keyboard_input_handler (plugin->window, (ply_window_keyboard_input_handler_t) on_keyboard_input); - ply_window_remove_backspace_handler (plugin->window, (ply_window_backspace_handler_t) on_backspace); - ply_window_remove_enter_handler (plugin->window, (ply_window_enter_handler_t) on_enter); - ply_window_set_draw_handler (plugin->window, NULL, NULL); - ply_window_set_erase_handler (plugin->window, NULL, NULL); + view = view_new (plugin, display); + + ply_pixel_display_set_draw_handler (view->display, + (ply_pixel_display_draw_handler_t) + on_draw, view); + ply_list_append_data (plugin->views, view); } static void -add_window (ply_boot_splash_plugin_t *plugin, - ply_window_t *window) +remove_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) { - plugin->window = window; -} + ply_list_node_t *node; -static void -remove_window (ply_boot_splash_plugin_t *plugin, - ply_window_t *window) -{ - plugin->window = NULL; + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; + + view = ply_list_node_get_data (node); + 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; + } + + node = next_node; + } } static bool @@ -495,19 +773,9 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, { assert (plugin != NULL); - add_handlers (plugin); - plugin->loop = loop; plugin->mode = mode; - plugin->animation = ply_animation_new (plugin->animation_dir, - "throbber-"); - plugin->progress_animation = ply_progress_animation_new (plugin->animation_dir, - "progress-"); - ply_progress_animation_set_transition (plugin->progress_animation, - plugin->transition, - plugin->transition_duration); - ply_trace ("loading lock image"); if (!ply_image_load (plugin->lock_image)) return false; @@ -527,23 +795,11 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, } } - ply_trace ("loading entry"); - if (!ply_entry_load (plugin->entry)) - return false; - - ply_trace ("loading animation"); - if (!ply_animation_load (plugin->animation)) - return false; - - ply_trace ("loading progress animation"); - if (!ply_progress_animation_load (plugin->progress_animation)) - return false; - - ply_trace ("setting graphics mode"); - if (!ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS)) - return false; - - plugin->frame_buffer = ply_window_get_frame_buffer (plugin->window); + if (!load_views (plugin)) + { + ply_trace ("couldn't load views"); + return false; + } ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) detach_from_event_loop, @@ -554,11 +810,8 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, (ply_event_handler_t) on_interrupt, plugin); - ply_window_clear_screen (plugin->window); - ply_window_hide_text_cursor (plugin->window); - ply_trace ("starting boot animation"); - start_animation (plugin); + start_progress_animation (plugin); plugin->is_visible = true; @@ -583,6 +836,28 @@ on_animation_stopped (ply_boot_splash_plugin_t *plugin) plugin->is_idle = true; } +static void +update_progress_animation (ply_boot_splash_plugin_t *plugin, + double percent_done) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + 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, + percent_done); + + node = next_node; + } +} + static void on_boot_progress (ply_boot_splash_plugin_t *plugin, double duration, @@ -592,15 +867,14 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin, if (percent_done >= SHOW_ANIMATION_PERCENT) { - if (ply_animation_is_stopped (plugin->animation)) + if (plugin->stop_trigger == NULL) { plugin->stop_trigger = ply_trigger_new (&plugin->stop_trigger); ply_trigger_add_handler (plugin->stop_trigger, (ply_trigger_handler_t) on_animation_stopped, plugin); - ply_progress_animation_hide (plugin->progress_animation); - begin_animation (plugin, plugin->stop_trigger); + start_end_animation (plugin, plugin->stop_trigger); } } else @@ -614,11 +888,8 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin, * fraction(time,estimate)=1-2^(-(time^1.45)/estimate) */ percent_done = 1.0 - pow (2.0, -pow (duration, 1.45) / total_duration) * (1.0 - percent_done); - ply_progress_animation_set_percent_done (plugin->progress_animation, - percent_done); + update_progress_animation (plugin, percent_done); } - - ply_progress_animation_draw (plugin->progress_animation); } static void @@ -627,8 +898,6 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin, { assert (plugin != NULL); - remove_handlers (plugin); - if (plugin->loop != NULL) { stop_animation (plugin); @@ -639,74 +908,52 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin, detach_from_event_loop (plugin); } - plugin->frame_buffer = NULL; plugin->is_visible = false; - - ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT); } static void show_password_prompt (ply_boot_splash_plugin_t *plugin, - const char *prompt) + const char *text, + int number_of_bullets) { - ply_frame_buffer_area_t area; - int x, y; - int entry_width, entry_height; + ply_list_node_t *node; - uint32_t *box_data, *lock_data; - - assert (plugin != NULL); - - if (ply_entry_is_hidden (plugin->entry)) + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { - draw_background (plugin, NULL); + ply_list_node_t *next_node; + view_t *view; - ply_frame_buffer_get_size (plugin->frame_buffer, &area); - plugin->box_area.width = ply_image_get_width (plugin->box_image); - plugin->box_area.height = ply_image_get_height (plugin->box_image); - plugin->box_area.x = area.width / 2.0 - plugin->box_area.width / 2.0; - plugin->box_area.y = area.height / 2.0 - plugin->box_area.height / 2.0; + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); - plugin->lock_area.width = ply_image_get_width (plugin->lock_image); - plugin->lock_area.height = ply_image_get_height (plugin->lock_image); + view_show_prompt (view, text); + ply_entry_set_bullet_count (view->entry, number_of_bullets); - entry_width = ply_entry_get_width (plugin->entry); - entry_height = ply_entry_get_height (plugin->entry); - - x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0 + plugin->lock_area.width; - y = area.height / 2.0 - entry_height / 2.0; - - plugin->lock_area.x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0; - plugin->lock_area.y = area.height / 2.0 - plugin->lock_area.height / 2.0; - - box_data = ply_image_get_data (plugin->box_image); - ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer, - &plugin->box_area, 0, 0, - box_data); - - ply_entry_show (plugin->entry, plugin->loop, plugin->window, x, y); - - lock_data = ply_image_get_data (plugin->lock_image); - ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer, - &plugin->lock_area, 0, 0, - lock_data); + node = next_node; } - else +} + +static void +show_prompt (ply_boot_splash_plugin_t *plugin, + const char *prompt, + const char *entry_text) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { - ply_entry_draw (plugin->entry); - } - if (prompt != NULL) - { - int label_width, label_height; + ply_list_node_t *next_node; + view_t *view; - ply_label_set_text (plugin->label, prompt); - label_width = ply_label_get_width (plugin->label); - label_height = ply_label_get_height (plugin->label); + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); - x = plugin->box_area.x + plugin->lock_area.width / 2; - y = plugin->box_area.y + plugin->box_area.height; + view_show_prompt (view, prompt); + ply_entry_set_text (view->entry, entry_text); - ply_label_show (plugin->label, plugin->window, x, y); + node = next_node; } } @@ -728,27 +975,50 @@ become_idle (ply_boot_splash_plugin_t *plugin, plugin->idle_trigger = idle_trigger; - if (ply_animation_is_stopped (plugin->animation)) + if (plugin->stop_trigger == NULL) { plugin->stop_trigger = ply_trigger_new (&plugin->stop_trigger); ply_trigger_add_handler (plugin->stop_trigger, (ply_trigger_handler_t) on_animation_stopped, plugin); - ply_progress_animation_hide (plugin->progress_animation); - begin_animation (plugin, plugin->stop_trigger); + start_end_animation (plugin, plugin->stop_trigger); + } +} + +static void +hide_prompt (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_hide_prompt (view); + + node = next_node; } } static void display_normal (ply_boot_splash_plugin_t *plugin) { + pause_views (plugin); if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_NORMAL) { plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL; - ply_entry_hide (plugin->entry); - start_animation (plugin); + hide_prompt (plugin); + start_progress_animation (plugin); + + redraw_views (plugin); } + unpause_views (plugin); } static void @@ -756,13 +1026,14 @@ display_password (ply_boot_splash_plugin_t *plugin, const char *prompt, int bullets) { + pause_views (plugin); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) - { - stop_animation (plugin); - } + stop_animation (plugin); + plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY; - show_password_prompt (plugin, prompt); - ply_entry_set_bullet_count (plugin->entry, bullets); + show_password_prompt (plugin, prompt, bullets); + redraw_views (plugin); + unpause_views (plugin); } static void @@ -770,14 +1041,14 @@ display_question (ply_boot_splash_plugin_t *plugin, const char *prompt, const char *entry_text) { + pause_views (plugin); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) - { - stop_animation (plugin); - } + stop_animation (plugin); plugin->state = PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY; - show_password_prompt (plugin, prompt); - ply_entry_set_text (plugin->entry, entry_text); + show_prompt (plugin, prompt, entry_text); + redraw_views (plugin); + unpause_views (plugin); } ply_boot_splash_plugin_interface_t * @@ -787,8 +1058,8 @@ ply_boot_splash_plugin_get_interface (void) { .create_plugin = create_plugin, .destroy_plugin = destroy_plugin, - .add_window = add_window, - .remove_window = remove_window, + .add_pixel_display = add_pixel_display, + .remove_pixel_display = remove_pixel_display, .show_splash_screen = show_splash_screen, .update_status = update_status, .on_boot_progress = on_boot_progress, @@ -803,4 +1074,4 @@ ply_boot_splash_plugin_get_interface (void) return &plugin_interface; } -/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ +/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ From ae60ff52cdfc2afa34a0dad2636f7821d1f7ab05 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 17:03:47 -0400 Subject: [PATCH 29/43] [main] Update to use new multihead interface --- src/libplybootsplash/ply-renderer.c | 1 + src/main.c | 337 +++++++++++++++++----------- 2 files changed, 205 insertions(+), 133 deletions(-) diff --git a/src/libplybootsplash/ply-renderer.c b/src/libplybootsplash/ply-renderer.c index 510479d8..9320030f 100644 --- a/src/libplybootsplash/ply-renderer.c +++ b/src/libplybootsplash/ply-renderer.c @@ -50,6 +50,7 @@ struct _ply_renderer ply_renderer_backend_t *backend; char *device_name; + ply_terminal_t *terminal; ply_console_t *console; }; diff --git a/src/main.c b/src/main.c index 3b40afab..2b5e13a3 100644 --- a/src/main.c +++ b/src/main.c @@ -79,8 +79,11 @@ typedef struct typedef struct { ply_event_loop_t *loop; + ply_console_t *console; ply_boot_server_t *boot_server; - ply_list_t *windows; + ply_list_t *pixel_displays; + ply_list_t *text_displays; + ply_keyboard_t *keyboard; ply_boot_splash_t *boot_splash; ply_terminal_session_t *session; ply_buffer_t *boot_buffer; @@ -90,6 +93,7 @@ typedef struct ply_buffer_t *entry_buffer; ply_command_parser_t *command_parser; ply_mode_t mode; + ply_renderer_t *renderer; ply_trigger_t *quit_trigger; @@ -104,6 +108,7 @@ typedef struct char *kernel_console_tty; char *override_splash_path; + const char *default_tty; int number_of_errors; } state_t; @@ -111,8 +116,10 @@ typedef struct static ply_boot_splash_t *start_boot_splash (state_t *state, const char *theme_path); -static ply_window_t *create_window (state_t *state, - const char *tty_name); +static void add_display_and_keyboard_for_terminal (state_t *state, + const char *tty_name); + +static void add_default_displays_and_keyboard (state_t *state); static bool attach_to_running_session (state_t *state); static void on_escape_pressed (state_t *state); @@ -460,47 +467,6 @@ on_error (state_t *state) state->number_of_errors++; } -static bool -has_open_window (state_t *state) -{ - ply_list_node_t *node; - - ply_trace ("checking for open windows"); - - node = ply_list_get_first_node (state->windows); - while (node != NULL) - { - ply_list_node_t *next_node; - ply_window_t *window; - - next_node = ply_list_get_next_node (state->windows, node); - - window = ply_list_node_get_data (node); - - if (ply_window_is_open (window)) - { - int fd; - const char *name; - - fd = ply_window_get_tty_fd (window); - - if (fd >= 0) - name = ttyname (fd); - else - name = NULL; - - ply_trace ("window %s%sis open", - name != NULL? name : "", - name != NULL? " " : ""); - return true; - } - - node = next_node; - } - - return false; -} - static bool plymouth_should_ignore_show_splash_calls (state_t *state) { @@ -526,9 +492,6 @@ plymouth_should_show_default_splash (state_t *state) if (state->kernel_console_tty != NULL) return false; - if (!has_open_window (state)) - return false; - for (i = 0; strings[i] != NULL; i++) { int cmp; @@ -549,53 +512,47 @@ plymouth_should_show_default_splash (state_t *state) } static void -open_windows (state_t *state) +remove_displays_and_keyboard (state_t *state) { ply_list_node_t *node; - node = ply_list_get_first_node (state->windows); + node = ply_list_get_first_node (state->pixel_displays); while (node != NULL) { ply_list_node_t *next_node; - ply_window_t *window; + ply_pixel_display_t *display; - next_node = ply_list_get_next_node (state->windows, node); + next_node = ply_list_get_next_node (state->pixel_displays, node); + display = ply_list_node_get_data (node); + ply_pixel_display_free (display); - window = ply_list_node_get_data (node); - - if (!ply_window_is_open (window)) - ply_window_open (window); + ply_list_remove_node (state->pixel_displays, node); node = next_node; } -} -static void -close_windows (state_t *state) -{ - ply_list_node_t *node; - - node = ply_list_get_first_node (state->windows); + node = ply_list_get_first_node (state->text_displays); while (node != NULL) { ply_list_node_t *next_node; - ply_window_t *window; + ply_text_display_t *display; - next_node = ply_list_get_next_node (state->windows, node); + next_node = ply_list_get_next_node (state->text_displays, node); + display = ply_list_node_get_data (node); + ply_text_display_free (display); - window = ply_list_node_get_data (node); - - if (ply_window_is_open (window)) - ply_window_close (window); + ply_list_remove_node (state->text_displays, node); node = next_node; } + + state->keyboard = NULL; } static void on_show_splash (state_t *state) { - bool has_window; + bool has_display; if (plymouth_should_ignore_show_splash_calls (state)) { @@ -603,16 +560,15 @@ on_show_splash (state_t *state) return; } - open_windows (state); + has_display = ply_list_get_length (state->pixel_displays) > 0 || + ply_list_get_length (state->text_displays) > 0; - has_window = has_open_window (state); - - if (!state->is_attached && state->should_be_attached && has_window) + if (!state->is_attached && state->should_be_attached && has_display) attach_to_running_session (state); - if (!has_window && state->is_attached) + if (!has_display && state->is_attached) { - ply_trace ("no open windows, detaching session"); + ply_trace ("no open seats, detaching session"); ply_terminal_session_detach (state->session); state->is_redirected = false; state->is_attached = false; @@ -641,8 +597,15 @@ quit_splash (state_t *state) state->boot_splash = NULL; } - ply_trace ("closing windows"); - close_windows (state); + ply_trace ("removing displays and keyboard"); + remove_displays_and_keyboard (state); + + if (state->renderer != NULL) + { + ply_renderer_close (state->renderer); + ply_renderer_free (state->renderer); + state->renderer = NULL; + } if (state->session != NULL) { @@ -927,43 +890,160 @@ on_enter (state_t *state, } } -static ply_window_t * -create_window (state_t *state, - const char *tty_name) +static void +set_keyboard (state_t *state, + ply_keyboard_t *keyboard) { - ply_window_t *window; + state->keyboard = keyboard; - ply_trace ("creating window on %s", tty_name != NULL? tty_name : "active vt"); - window = ply_window_new (tty_name); + ply_keyboard_add_escape_handler (keyboard, (ply_keyboard_escape_handler_t) + on_escape_pressed, state); + ply_trace ("listening for keystrokes"); + ply_keyboard_add_input_handler (keyboard, + (ply_keyboard_input_handler_t) + on_keyboard_input, state); + ply_trace ("listening for backspace"); + ply_keyboard_add_backspace_handler (keyboard, + (ply_keyboard_backspace_handler_t) + on_backspace, state); + ply_trace ("listening for enter"); + ply_keyboard_add_enter_handler (keyboard, + (ply_keyboard_enter_handler_t) + on_enter, state); + ply_keyboard_watch_for_input (keyboard); +} +static void +add_display_and_keyboard_for_terminal (state_t *state, + const char *tty_name) +{ + ply_terminal_t *terminal; + ply_text_display_t *display; + ply_keyboard_t *keyboard; - ply_window_attach_to_event_loop (window, state->loop); + ply_trace ("adding display and keyboard for %s", tty_name); - return window; + terminal = ply_terminal_new (tty_name); + + if (!ply_terminal_open (terminal)) + { + ply_trace ("could not open terminal '%s': %m", tty_name); + ply_terminal_free (terminal); + return; + } + + keyboard = ply_keyboard_new_for_terminal (terminal); + display = ply_text_display_new (terminal, state->console); + + ply_list_append_data (state->text_displays, display); + state->keyboard = keyboard; + set_keyboard (state, keyboard); } static void -add_windows_to_boot_splash (state_t *state, - ply_boot_splash_t *splash) +add_pixel_displays_from_renderer (state_t *state, + ply_renderer_t *renderer) { + ply_list_t *heads; ply_list_node_t *node; - ply_trace ("There are %d windows in list", - ply_list_get_length (state->windows)); - node = ply_list_get_first_node (state->windows); + heads = ply_renderer_get_heads (renderer); + + node = ply_list_get_first_node (heads); while (node != NULL) { ply_list_node_t *next_node; - ply_window_t *window; + ply_renderer_head_t *head; + ply_pixel_display_t *display; - next_node = ply_list_get_next_node (state->windows, node); + head = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (heads, node); - window = ply_list_node_get_data (node); + display = ply_pixel_display_new (renderer, head); + + ply_list_append_data (state->pixel_displays, display); + + node = next_node; + } + +} + +static void +add_default_displays_and_keyboard (state_t *state) +{ + ply_renderer_t *renderer; + ply_keyboard_t *keyboard; + ply_terminal_t *terminal; + ply_text_display_t *text_display; + + ply_trace ("adding default displays and keyboard"); + + terminal = ply_terminal_new (state->default_tty); + + if (!ply_terminal_open (terminal)) + { + ply_trace ("could not open terminal '%s': %m", state->default_tty); + ply_terminal_free (terminal); + return; + } + + renderer = ply_renderer_new (NULL, terminal, state->console); + + if (!ply_renderer_open (renderer)) + { + ply_trace ("could not open renderer /dev/fb"); + ply_renderer_free (renderer); + ply_terminal_free (terminal); + + add_display_and_keyboard_for_terminal (state, state->default_tty); + return; + } + + keyboard = ply_keyboard_new_for_renderer (renderer); + set_keyboard (state, keyboard); + + add_pixel_displays_from_renderer (state, renderer); + + text_display = ply_text_display_new (terminal, state->console); + ply_list_append_data (state->text_displays, text_display); + + state->renderer = renderer; +} + +static void +add_displays_and_keyboard_to_boot_splash (state_t *state, + ply_boot_splash_t *splash) +{ + ply_list_node_t *node; + + ply_trace ("setting keyboard on boot splash"); + ply_boot_splash_set_keyboard (splash, state->keyboard); + + node = ply_list_get_first_node (state->pixel_displays); + while (node != NULL) + { + ply_pixel_display_t *display; + ply_list_node_t *next_node; + + display = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (state->pixel_displays, node); + ply_trace ("adding pixel display on boot splash"); + ply_boot_splash_add_pixel_display (splash, display); + + node = next_node; + } + + node = ply_list_get_first_node (state->text_displays); + while (node != NULL) + { + ply_text_display_t *display; + ply_list_node_t *next_node; + + display = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (state->text_displays, node); + + ply_trace ("adding text display on boot splash"); + ply_boot_splash_add_text_display (splash, display); - if (ply_window_is_open (window)) - { - ply_trace ("adding window to boot splash"); - ply_boot_splash_add_window (splash, window); - } node = next_node; } } @@ -978,7 +1058,10 @@ start_boot_splash (state_t *state, ply_trace ("Loading boot splash theme '%s'", theme_path); - splash = ply_boot_splash_new (theme_path, PLYMOUTH_PLUGIN_PATH, state->boot_buffer); + splash = ply_boot_splash_new (theme_path, + PLYMOUTH_PLUGIN_PATH, + state->boot_buffer, + state->console); if (!ply_boot_splash_load (splash)) { @@ -994,8 +1077,8 @@ start_boot_splash (state_t *state, ply_trace ("attaching progress to plugin"); ply_boot_splash_attach_progress (splash, state->progress); - ply_trace ("adding windows to boot splash"); - add_windows_to_boot_splash (state, splash); + add_displays_and_keyboard_to_boot_splash (state, splash); + ply_trace ("showing plugin"); if (state->mode == PLY_MODE_SHUTDOWN) splash_mode = PLY_BOOT_SPLASH_MODE_SHUTDOWN; @@ -1179,6 +1262,16 @@ check_for_consoles (state_t *state, ply_trace ("checking if splash screen should be disabled"); + state->console = ply_console_new (); + + if (!ply_console_open (state->console)) + { + ply_trace ("could not open /dev/tty0"); + ply_console_free (state->console); + state->console = NULL; + return; + } + remaining_command_line = state->kernel_command_line; while ((console_key = strstr (remaining_command_line, " console=")) != NULL) { @@ -1204,11 +1297,11 @@ check_for_consoles (state_t *state, state->kernel_console_tty = strdup (default_tty); } - ply_list_append_data (state->windows, create_window (state, state->kernel_console_tty)); + add_display_and_keyboard_for_terminal (state, state->kernel_console_tty); } - if (ply_list_get_length (state->windows) == 0) - ply_list_append_data (state->windows, create_window (state, default_tty)); + if (ply_list_get_length (state->text_displays) == 0) + add_default_displays_and_keyboard (state); } static bool @@ -1241,10 +1334,7 @@ redirect_standard_io_to_device (const char *device) static bool initialize_environment (state_t *state) { - const char *default_tty; - ply_trace ("initializing minimal work environment"); - ply_list_node_t *node; if (!get_kernel_command_line (state)) return false; @@ -1252,46 +1342,28 @@ initialize_environment (state_t *state) check_verbosity (state); check_logging (state); - state->windows = ply_list_new (); state->keystroke_triggers = ply_list_new (); state->entry_triggers = ply_list_new (); state->entry_buffer = ply_buffer_new(); + state->pixel_displays = ply_list_new (); + state->text_displays = ply_list_new (); + state->keyboard = NULL; if (state->mode == PLY_MODE_SHUTDOWN) { - default_tty = "tty63"; + state->default_tty = "tty63"; ply_switch_to_vt (63); } else - default_tty = "tty1"; + state->default_tty = "tty1"; - check_for_consoles (state, default_tty); + check_for_consoles (state, state->default_tty); if (state->kernel_console_tty != NULL) redirect_standard_io_to_device (state->kernel_console_tty); else - redirect_standard_io_to_device (default_tty); + redirect_standard_io_to_device (state->default_tty); - for (node = ply_list_get_first_node (state->windows); node; - node = ply_list_get_next_node (state->windows, node)) - { - ply_window_t *window = ply_list_node_get_data (node); - - ply_trace ("listening for escape key"); - ply_window_add_escape_handler (window, (ply_window_escape_handler_t) - on_escape_pressed, state); - ply_trace ("listening for keystrokes"); - ply_window_add_keyboard_input_handler (window, - (ply_window_keyboard_input_handler_t) on_keyboard_input, state); - ply_trace ("listening for backspace"); - ply_window_add_backspace_handler (window, - (ply_window_backspace_handler_t) on_backspace, state); - ply_trace ("listening for enter"); - ply_window_add_enter_handler (window, - (ply_window_enter_handler_t) on_enter, state); - } - - ply_trace ("initialized minimal work environment"); return true; } @@ -1515,7 +1587,6 @@ main (int argc, state.boot_splash = NULL; ply_command_parser_free (state.command_parser); - ply_list_free (state.windows); ply_boot_server_free (state.boot_server); state.boot_server = NULL; From a9160a9b5423dc84af0416b4a638259d758aa9f6 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 23 Sep 2009 22:54:26 -0400 Subject: [PATCH 30/43] [main] switch to vt that plymouth is running on at startup --- src/main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 2b5e13a3..d79b816e 100644 --- a/src/main.c +++ b/src/main.c @@ -931,6 +931,9 @@ add_display_and_keyboard_for_terminal (state_t *state, return; } + ply_console_set_active_vt (state->console, + ply_terminal_get_vt_number (terminal)); + keyboard = ply_keyboard_new_for_terminal (terminal); display = ply_text_display_new (terminal, state->console); @@ -986,6 +989,9 @@ add_default_displays_and_keyboard (state_t *state) return; } + ply_console_set_active_vt (state->console, + ply_terminal_get_vt_number (terminal)); + renderer = ply_renderer_new (NULL, terminal, state->console); if (!ply_renderer_open (renderer)) @@ -1352,7 +1358,6 @@ initialize_environment (state_t *state) if (state->mode == PLY_MODE_SHUTDOWN) { state->default_tty = "tty63"; - ply_switch_to_vt (63); } else state->default_tty = "tty1"; From c858c06ad54423e35b305d5cad155444cff15bc8 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 23 Sep 2009 23:21:52 -0400 Subject: [PATCH 31/43] [utils] drop ply_switch_to_vt It's been replaced by ply_console_set_active_vt, and won't work right because of ply-console anyway. --- src/libply/ply-utils.c | 21 --------------------- src/libply/ply-utils.h | 2 -- 2 files changed, 23 deletions(-) diff --git a/src/libply/ply-utils.c b/src/libply/ply-utils.c index 37b986be..b26773c5 100644 --- a/src/libply/ply-utils.c +++ b/src/libply/ply-utils.c @@ -894,25 +894,4 @@ ply_utf8_string_get_length (const char *string, return count; } -void -ply_switch_to_vt (int vt_number) -{ - int fd; - - fd = open ("/dev/tty0", O_RDWR | O_NOCTTY); - - if (fd < 0) - return; - - if (ioctl (fd, VT_ACTIVATE, vt_number) < 0) - { - close (fd); - return; - } - - ioctl (fd, VT_WAITACTIVE, vt_number); - close (fd); -} - - /* 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 62149ba3..592a8e4e 100644 --- a/src/libply/ply-utils.h +++ b/src/libply/ply-utils.h @@ -104,8 +104,6 @@ int ply_utf8_character_get_size (const char *string, int ply_utf8_string_get_length (const char *string, size_t n); -void ply_switch_to_vt (int vt_number); - #endif #endif /* PLY_UTILS_H */ From b71822f58c0995296dc2540c9c57910436899f4d Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 23:06:41 -0400 Subject: [PATCH 32/43] [image] Drop test code It won't work when frame buffer is removed. I really want to redo how tests are done anyway, to be more automated. --- src/libplybootsplash/ply-image.c | 146 ------------------------------- 1 file changed, 146 deletions(-) diff --git a/src/libplybootsplash/ply-image.c b/src/libplybootsplash/ply-image.c index 812313c5..94bc6afa 100644 --- a/src/libplybootsplash/ply-image.c +++ b/src/libplybootsplash/ply-image.c @@ -400,150 +400,4 @@ ply_image_rotate (ply_image_t *image, return new_image; } -#ifdef PLY_IMAGE_ENABLE_TEST - -#include "ply-frame-buffer.h" - -#include -#include -#include -#include -#include -#include - -#include - -#ifndef FRAMES_PER_SECOND -#define FRAMES_PER_SECOND 50 -#endif - -static int console_fd; - -static bool -hide_cursor (void) -{ - static const char invisible_cursor[] = "\033[?25l\033[?1c"; - - if (write (STDOUT_FILENO, invisible_cursor, - sizeof (invisible_cursor) - 1) != sizeof (invisible_cursor) - 1) - return false; - - return true; -} - -static double -get_current_time (void) -{ - const double microseconds_per_second = 1000000.0; - double timestamp; - struct timeval now = { 0L, /* zero-filled */ }; - - gettimeofday (&now, NULL); - timestamp = ((microseconds_per_second * now.tv_sec) + now.tv_usec) / - microseconds_per_second; - - return timestamp; -} - -double start_time = 0.0; -int num_frames = 0; - -static void -animate_at_time (ply_frame_buffer_t *buffer, - ply_image_t *image, - double time) -{ - ply_frame_buffer_area_t area; - uint32_t *data; - long width, height; - static double last_opacity = 0.0; - double opacity = 0.0; - - data = ply_image_get_data (image); - width = ply_image_get_width (image); - height = ply_image_get_height (image); - - ply_frame_buffer_get_size (buffer, &area); - area.x = (area.width / 2) - (width / 2); - area.y = (area.height / 2) - (height / 2); - area.width = width; - area.height = height; - - opacity = .5 * sin ((time / 4) * (2 * M_PI)) + .8; - opacity = CLAMP (opacity, 0, 1.0); - - num_frames++; - if (fabs (opacity - last_opacity) <= DBL_MIN) - return; - - last_opacity = opacity; - - ply_frame_buffer_pause_updates (buffer); - ply_frame_buffer_fill_with_color (buffer, &area, 0.1, 0.1, .7, 1.0); - ply_frame_buffer_fill_with_argb32_data_at_opacity (buffer, &area, - 0, 0, data, opacity); - ply_frame_buffer_unpause_updates (buffer); - - if (time > 10.0) - ioctl (console_fd, KDSETMODE, KD_TEXT); -} - -int -main (int argc, - char **argv) -{ - ply_image_t *image; - ply_frame_buffer_t *buffer; - int exit_code; - - exit_code = 0; - - hide_cursor (); - - if (argc == 1) - image = ply_image_new ("booting.png"); - else - image = ply_image_new (argv[1]); - - if (!ply_image_load (image)) - { - exit_code = errno; - perror ("could not load image"); - return exit_code; - } - - console_fd = open ("/dev/tty0", O_RDWR); - - buffer = ply_frame_buffer_new (NULL); - - if (!ply_frame_buffer_open (buffer)) - { - exit_code = errno; - perror ("could not open framebuffer"); - return exit_code; - } - - start_time = get_current_time (); - ply_frame_buffer_fill_with_color (buffer, NULL, 0.1, 0.1, .7, 1.0); - while ("we want to see ad-hoc animations") - { - long sleep_time; - double now; - - now = get_current_time (); - animate_at_time (buffer, image, now - start_time); - sleep_time = 1000000 / FRAMES_PER_SECOND; - sleep_time = MAX (sleep_time - ((get_current_time () - now) / 1000000), - 10000); - usleep (sleep_time); - } - ply_frame_buffer_close (buffer); - ply_frame_buffer_free (buffer); - - ply_image_free (image); - - return exit_code; -} - -#endif /* PLY_IMAGE_ENABLE_TEST */ /* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ From c7881116169efad70df24793c6fa6c40f26d5315 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Thu, 20 Aug 2009 00:18:48 -0400 Subject: [PATCH 33/43] [libply] Drop frame-buffer class We no longer use it now that we have the pixel-display class, pixel buffers, etc. --- src/libply/Makefile.am | 2 - src/libply/ply-frame-buffer.c | 1422 --------------------- src/libply/ply-frame-buffer.h | 112 -- src/libply/tests/Makefile.am | 1 - src/libply/tests/ply-frame-buffer-test.am | 14 - 5 files changed, 1551 deletions(-) delete mode 100644 src/libply/ply-frame-buffer.c delete mode 100644 src/libply/ply-frame-buffer.h delete mode 100644 src/libply/tests/ply-frame-buffer-test.am diff --git a/src/libply/Makefile.am b/src/libply/Makefile.am index f87bf25d..50b4d069 100644 --- a/src/libply/Makefile.am +++ b/src/libply/Makefile.am @@ -14,7 +14,6 @@ libplydir = $(includedir)/plymouth-1/ply libply_HEADERS = \ ply-event-loop.h \ ply-command-parser.h \ - ply-frame-buffer.h \ ply-buffer.h \ ply-array.h \ ply-bitarray.h \ @@ -37,7 +36,6 @@ libply_la_LDFLAGS = -export-symbols-regex '^[^_].*' \ libply_la_SOURCES = ply-event-loop.c \ $(libply_HEADERS) \ ply-command-parser.c \ - ply-frame-buffer.c \ ply-buffer.c \ ply-array.c \ ply-bitarray.c \ diff --git a/src/libply/ply-frame-buffer.c b/src/libply/ply-frame-buffer.c deleted file mode 100644 index a1e4fcda..00000000 --- a/src/libply/ply-frame-buffer.c +++ /dev/null @@ -1,1422 +0,0 @@ -/* ply-frame-buffer.c - framebuffer abstraction - * - * Copyright (C) 2006, 2007, 2008 Red Hat, Inc. - * 2008 Charlie Brej - * - * 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: Charlie Brej - * Kristian Høgsberg - * Ray Strode - */ -#include "config.h" -#include "ply-list.h" -#include "ply-frame-buffer.h" -#include "ply-logger.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifndef PLY_FRAME_BUFFER_DEFAULT_FB_DEVICE_NAME -#define PLY_FRAME_BUFFER_DEFAULT_FB_DEVICE_NAME "/dev/fb" -#endif - -struct _ply_frame_buffer -{ - char *device_name; - int device_fd; - - char *map_address; - size_t size; - - uint32_t *shadow_buffer; - - uint32_t red_bit_position; - uint32_t green_bit_position; - uint32_t blue_bit_position; - uint32_t alpha_bit_position; - - uint32_t bits_for_red; - uint32_t bits_for_green; - uint32_t bits_for_blue; - uint32_t bits_for_alpha; - - int32_t dither_red; - int32_t dither_green; - int32_t dither_blue; - - unsigned int bytes_per_pixel; - unsigned int row_stride; - - ply_frame_buffer_area_t area; - ply_list_t *areas_to_flush; - - void (*flush_area) (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area_to_flush); - - int pause_count; -}; - -static bool ply_frame_buffer_open_device (ply_frame_buffer_t *buffer); -static void ply_frame_buffer_close_device (ply_frame_buffer_t *buffer); -static bool ply_frame_buffer_query_device (ply_frame_buffer_t *buffer); -static bool ply_frame_buffer_map_to_device (ply_frame_buffer_t *buffer); -static inline uint_fast32_t ply_frame_buffer_pixel_value_to_device_pixel_value ( - ply_frame_buffer_t *buffer, - uint32_t pixel_value); - -static inline void ply_frame_buffer_blend_value_at_pixel (ply_frame_buffer_t *buffer, - int x, - int y, - uint32_t pixel_value); - -static void ply_frame_buffer_fill_area_with_pixel_value ( - ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - uint32_t pixel_value); - -static void ply_frame_buffer_add_area_to_flush_area (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area); - -static bool ply_frame_buffer_flush (ply_frame_buffer_t *buffer); - -static void ply_frame_buffer_area_intersect (ply_frame_buffer_area_t *area1, - ply_frame_buffer_area_t *area2, - ply_frame_buffer_area_t *result); - -static bool -ply_frame_buffer_open_device (ply_frame_buffer_t *buffer) -{ - assert (buffer != NULL); - assert (buffer->device_name != NULL); - - buffer->device_fd = open (buffer->device_name, O_RDWR); - - if (buffer->device_fd < 0) - { - return false; - } - - return true; -} - -static void -ply_frame_buffer_close_device (ply_frame_buffer_t *buffer) -{ - assert (buffer != NULL); - - if (buffer->map_address != MAP_FAILED) - { - munmap (buffer->map_address, buffer->size); - buffer->map_address = MAP_FAILED; - } - - if (buffer->device_fd >= 0) - { - close (buffer->device_fd); - buffer->device_fd = -1; - } -} - -static void -flush_area_to_any_device (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area_to_flush) -{ - unsigned long row, column; - char *row_buffer; - size_t bytes_per_row; - unsigned long x1, y1, x2, y2; - - x1 = area_to_flush->x; - y1 = area_to_flush->y; - x2 = x1 + area_to_flush->width; - y2 = y1 + area_to_flush->height; - - bytes_per_row = area_to_flush->width * buffer->bytes_per_pixel; - row_buffer = malloc (buffer->row_stride * buffer->bytes_per_pixel); - for (row = y1; row < y2; row++) - { - unsigned long offset; - - for (column = x1; column < x2; column++) - { - uint32_t pixel_value; - uint_fast32_t device_pixel_value; - - pixel_value = buffer->shadow_buffer[row * buffer->area.width + column]; - - device_pixel_value = - ply_frame_buffer_pixel_value_to_device_pixel_value (buffer, - pixel_value); - - memcpy (row_buffer + column * buffer->bytes_per_pixel, - &device_pixel_value, buffer->bytes_per_pixel); - } - - offset = row * buffer->row_stride * buffer->bytes_per_pixel + x1 * buffer->bytes_per_pixel; - memcpy (buffer->map_address + offset, row_buffer + x1 * buffer->bytes_per_pixel, - area_to_flush->width * buffer->bytes_per_pixel); - } - free (row_buffer); -} - -static void -flush_area_to_xrgb32_device (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area_to_flush) -{ - unsigned long x1, y1, x2, y2, y; - char *dst, *src; - - x1 = area_to_flush->x; - y1 = area_to_flush->y; - x2 = x1 + area_to_flush->width; - y2 = y1 + area_to_flush->height; - - dst = &buffer->map_address[(y1 * buffer->row_stride + x1) * 4]; - src = (char *) &buffer->shadow_buffer[y1 * buffer->area.width + x1]; - - if (area_to_flush->width == buffer->row_stride) - { - memcpy (dst, src, area_to_flush->width * area_to_flush->height * 4); - return; - } - - for (y = y1; y < y2; y++) - { - memcpy (dst, src, area_to_flush->width * 4); - dst += buffer->row_stride * 4; - src += buffer->area.width * 4; - } -} - -static const char const *p_visual(int visual) -{ - static const char const *visuals[] = - { - [FB_VISUAL_MONO01] = "FB_VISUAL_MONO01", - [FB_VISUAL_MONO10] = "FB_VISUAL_MONO10", - [FB_VISUAL_TRUECOLOR] = "FB_VISUAL_TRUECOLOR", - [FB_VISUAL_PSEUDOCOLOR] = "FB_VISUAL_PSEUDOCOLOR", - [FB_VISUAL_DIRECTCOLOR] = "FB_VISUAL_DIRECTCOLOR", - [FB_VISUAL_STATIC_PSEUDOCOLOR] = "FB_VISUAL_STATIC_PSEUDOCOLOR", - NULL - }; - static char unknown[] = "invalid visual: -4294967295"; - - if (visual < FB_VISUAL_MONO01 || visual > FB_VISUAL_STATIC_PSEUDOCOLOR) - { - sprintf(unknown, "invalid visual: %d", visual); - return unknown; - } - - return visuals[visual]; -} - -static bool -ply_frame_buffer_query_device (ply_frame_buffer_t *buffer) -{ - struct fb_var_screeninfo variable_screen_info; - struct fb_fix_screeninfo fixed_screen_info; - - assert (buffer != NULL); - assert (buffer->device_fd >= 0); - - if (ioctl (buffer->device_fd, FBIOGET_VSCREENINFO, &variable_screen_info) < 0) - return false; - - if (ioctl(buffer->device_fd, FBIOGET_FSCREENINFO, &fixed_screen_info) < 0) - return false; - - /* Normally the pixel is divided into channels between the color components. - * Each channel directly maps to a color channel on the hardware. - * - * There are some odd ball modes that use an indexed palette instead. In - * those cases (pseudocolor, direct color, etc), the pixel value is just an - * index into a lookup table of the real color values. - * - * We don't support that. - */ - if (fixed_screen_info.visual != FB_VISUAL_TRUECOLOR) - { - int rc = -1; - int i; - int depths[] = {32, 24, 16, 0}; - - ply_trace("Visual was %s, trying to find usable mode.\n", - p_visual(fixed_screen_info.visual)); - - for (i = 0; depths[i] != 0; i++) - { - variable_screen_info.bits_per_pixel = depths[i]; - variable_screen_info.activate |= FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; - - rc = ioctl(buffer->device_fd, FBIOPUT_VSCREENINFO, &variable_screen_info); - if (rc >= 0) - { - if (ioctl(buffer->device_fd, FBIOGET_FSCREENINFO, &fixed_screen_info) < 0) - return false; - if (fixed_screen_info.visual == FB_VISUAL_TRUECOLOR) - break; - } - } - - if (ioctl(buffer->device_fd, FBIOGET_VSCREENINFO, &variable_screen_info) < 0) - return false; - - if (ioctl(buffer->device_fd, FBIOGET_FSCREENINFO, &fixed_screen_info) < 0) - return false; - } - - if (fixed_screen_info.visual != FB_VISUAL_TRUECOLOR || - variable_screen_info.bits_per_pixel < 16) - { - ply_trace("Visual is %s; not using graphics\n", - p_visual(fixed_screen_info.visual)); - return false; - } - - buffer->area.x = variable_screen_info.xoffset; - buffer->area.y = variable_screen_info.yoffset; - buffer->area.width = variable_screen_info.xres; - buffer->area.height = variable_screen_info.yres; - - buffer->red_bit_position = variable_screen_info.red.offset; - buffer->bits_for_red = variable_screen_info.red.length; - - buffer->green_bit_position = variable_screen_info.green.offset; - buffer->bits_for_green = variable_screen_info.green.length; - - buffer->blue_bit_position = variable_screen_info.blue.offset; - buffer->bits_for_blue = variable_screen_info.blue.length; - - buffer->alpha_bit_position = variable_screen_info.transp.offset; - buffer->bits_for_alpha = variable_screen_info.transp.length; - - buffer->bytes_per_pixel = variable_screen_info.bits_per_pixel >> 3; - buffer->row_stride = fixed_screen_info.line_length / buffer->bytes_per_pixel; - buffer->size = buffer->area.height * buffer->row_stride * buffer->bytes_per_pixel; - - buffer->dither_red = 0; - buffer->dither_green = 0; - buffer->dither_blue = 0; - - if (buffer->bytes_per_pixel == 4 && - buffer->red_bit_position == 16 && buffer->bits_for_red == 8 && - buffer->green_bit_position == 8 && buffer->bits_for_green == 8 && - buffer->blue_bit_position == 0 && buffer->bits_for_blue == 8) - buffer->flush_area = flush_area_to_xrgb32_device; - else - buffer->flush_area = flush_area_to_any_device; - - return true; -} - -static bool -ply_frame_buffer_map_to_device (ply_frame_buffer_t *buffer) -{ - assert (buffer != NULL); - assert (buffer->device_fd >= 0); - assert (buffer->size > 0); - - buffer->map_address = mmap (NULL, buffer->size, PROT_WRITE, - MAP_SHARED, buffer->device_fd, 0); - - return buffer->map_address != MAP_FAILED; -} - -static inline uint_fast32_t -ply_frame_buffer_pixel_value_to_device_pixel_value (ply_frame_buffer_t *buffer, - uint32_t pixel_value) -{ - uint8_t r, g, b, a; - int orig_r, orig_g, orig_b, orig_a; - int i; - - orig_a = pixel_value >> 24; - a = orig_a >> (8 - buffer->bits_for_alpha); - - orig_r = ((pixel_value >> 16) & 0xff) - buffer->dither_red; - r = CLAMP(orig_r, 0, 255) >> (8 - buffer->bits_for_red); - - orig_g = ((pixel_value >> 8) & 0xff) - buffer->dither_green; - g = CLAMP(orig_g, 0, 255) >> (8 - buffer->bits_for_green); - - orig_b = (pixel_value & 0xff) - buffer->dither_blue; - b = CLAMP(orig_b, 0, 255) >> (8 - buffer->bits_for_blue); - - uint8_t new_r = r << (8 - buffer->bits_for_red); - uint8_t new_g = g << (8 - buffer->bits_for_green); - uint8_t new_b = b << (8 - buffer->bits_for_blue); - for (i=buffer->bits_for_red; i<8; i*=2) new_r |= new_r >> i; - for (i=buffer->bits_for_green; i<8; i*=2) new_g |= new_g >> i; - for (i=buffer->bits_for_blue; i<8; i*=2) new_b |= new_b >> i; - - buffer->dither_red = new_r - orig_r; - buffer->dither_green = new_g - orig_g; - buffer->dither_blue = new_b - orig_b; - - - return ((a << buffer->alpha_bit_position) - | (r << buffer->red_bit_position) - | (g << buffer->green_bit_position) - | (b << buffer->blue_bit_position)); -} - -__attribute__((__pure__)) -static inline uint32_t -blend_two_pixel_values (uint32_t pixel_value_1, - uint32_t pixel_value_2) -{ - uint8_t alpha_1, red_1, green_1, blue_1; - uint8_t red_2, green_2, blue_2; - uint_least16_t red, green, blue; - - assert (((uint8_t) (pixel_value_2 >> 24)) == 0xff); - - alpha_1 = (uint8_t) (pixel_value_1 >> 24); - red_1 = (uint8_t) (pixel_value_1 >> 16); - green_1 = (uint8_t) (pixel_value_1 >> 8); - blue_1 = (uint8_t) pixel_value_1; - - red_2 = (uint8_t) (pixel_value_2 >> 16); - green_2 = (uint8_t) (pixel_value_2 >> 8); - blue_2 = (uint8_t) pixel_value_2; - - red = red_1 * 255 + red_2 * (255 - alpha_1); - green = green_1 * 255 + green_2 * (255 - alpha_1); - blue = blue_1 * 255 + blue_2 * (255 - alpha_1); - - red = (uint8_t) ((red + (red >> 8) + 0x80) >> 8); - green = (uint8_t) ((green + (green >> 8) + 0x80) >> 8); - blue = (uint8_t) ((blue + (blue >> 8) + 0x80) >> 8); - - return 0xff000000 | (red << 16) | (green << 8) | blue; -} - -__attribute__((__pure__)) -static inline uint32_t -make_pixel_value_translucent (uint32_t pixel_value, - uint8_t opacity) -{ - uint_least16_t alpha, red, green, blue; - - if (opacity == 255) - return pixel_value; - - alpha = (uint8_t) (pixel_value >> 24); - red = (uint8_t) (pixel_value >> 16); - green = (uint8_t) (pixel_value >> 8); - blue = (uint8_t) pixel_value; - - red *= opacity; - green *= opacity; - blue *= opacity; - alpha *= opacity; - - red = (uint8_t) ((red + (red >> 8) + 0x80) >> 8); - green = (uint8_t) ((green + (green >> 8) + 0x80) >> 8); - blue = (uint8_t) ((blue + (blue >> 8) + 0x80) >> 8); - alpha = (uint8_t) ((alpha + (alpha >> 8) + 0x80) >> 8); - - return (alpha << 24) | (red << 16) | (green << 8) | blue; -} - -static inline void -ply_frame_buffer_blend_value_at_pixel (ply_frame_buffer_t *buffer, - int x, - int y, - uint32_t pixel_value) -{ - uint32_t old_pixel_value; - - if ((pixel_value >> 24) != 0xff) - { - old_pixel_value = buffer->shadow_buffer[y * buffer->area.width + x]; - - pixel_value = blend_two_pixel_values (pixel_value, old_pixel_value); - } - - buffer->shadow_buffer[y * buffer->area.width + x] = pixel_value; -} - -static void -ply_frame_buffer_fill_area_with_pixel_value (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - uint32_t pixel_value) -{ - unsigned long row, column; - ply_frame_buffer_area_t cropped_area; - ply_frame_buffer_area_intersect (area, &buffer->area, &cropped_area); - - 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_frame_buffer_blend_value_at_pixel (buffer, - column, row, - pixel_value); - } - } -} - -static void -integrate_area_with_flush_area (ply_frame_buffer_t *buffer, - ply_list_node_t *node, - ply_frame_buffer_area_t *new_area) -{ - if (new_area->width == 0) return; - if (new_area->height == 0) return; - while (node != NULL) - { - ply_list_node_t *next_node; - ply_frame_buffer_area_t *second_new_area; - ply_frame_buffer_area_t *old_area; - old_area = (ply_frame_buffer_area_t *) ply_list_node_get_data (node); - next_node = ply_list_get_next_node (buffer->areas_to_flush, node); - - /* - Say we have an overlap between rectangle A and rectangle B and C denotes the overlap. - Depending on the type of overlap we can create a non overlapping addition to the set. - - 1:Collision on one side 2:Collision on two sides - Trim one of the rectanges Break into two rectangles - - AAAAA AAAAA AAAAA AAAAA - AAACCBBB AAAAABBB AAAAA AAAAA - AAACCBBB => AAAAABBB AAACCBBB => AAAAAbbb - AAACCBBB AAAAABBB AAACCBBB AAAAAbbb - AAAAA AAAAA BBBBB BBBBB - BBBBB BBBBB - - 3:Collision on opposite sides 4:Fully contained - Break into two rectangles Throw away the rectangle - - AAAAA AAAAA AAAAA AAAAA - BCCCCCB BAAAAAb ACCCA AAAAA - BCCCCCB => BAAAAAb ACCCA => AAAAA - BCCCCCB BAAAAAb ACCCA AAAAA - AAAAA AAAAA AAAAA AAAAA - - */ - enum {H_COLLISION_NONE, H_COLLISION_LEFT, H_COLLISION_RIGHT, H_COLLISION_BOTH, H_COLLISION_CONTAINED} - h_collision = H_COLLISION_NONE; - enum {V_COLLISION_NONE, V_COLLISION_TOP, V_COLLISION_BOTTOM, V_COLLISION_BOTH, V_COLLISION_CONTAINED} - v_collision = V_COLLISION_NONE; - - if (new_area->x >= old_area->x && (new_area->x + new_area->width) <= (old_area->x + old_area->width)) - h_collision = H_COLLISION_CONTAINED; - else - { /* Remember: x+width points to the first pixel outside the rectangle*/ - if (new_area->x < old_area->x && - (new_area->x + (int)new_area->width) > old_area->x) - h_collision = H_COLLISION_LEFT; /* new_area colllided with the left edge of old_area */ - - if (new_area->x < (old_area->x + (int)old_area->width) && - (new_area->x + (int)new_area->width) >= (old_area->x + (int)old_area->width)) - { /* new_area colllided with the right edge of old_area */ - if (h_collision == H_COLLISION_LEFT) - h_collision = H_COLLISION_BOTH; - else - h_collision = H_COLLISION_RIGHT; - } - } - - if (h_collision != H_COLLISION_NONE) - { - if (new_area->y >= old_area->y && (new_area->y + new_area->height) <= (old_area->y + old_area->height)) - v_collision = V_COLLISION_CONTAINED; - else - { - if (new_area->y < old_area->y && - (new_area->y + (int)new_area->height) > old_area->y) - v_collision = V_COLLISION_TOP; - if (new_area->y < (old_area->y + (int)old_area->height) && - (new_area->y + (int)new_area->height) >= (old_area->y + (int)old_area->height)) - { /* new_area colllided with the right edge of old_area */ - if (v_collision == V_COLLISION_TOP) - v_collision = V_COLLISION_BOTH; - else - v_collision = V_COLLISION_BOTTOM; - } - } - } - - switch(v_collision) - { - case V_COLLISION_NONE: - break; - case V_COLLISION_TOP: - { - switch (h_collision) - { - case H_COLLISION_NONE: /* no collision */ - break; - case H_COLLISION_LEFT: /* collision with old top left corner, split new into two */ - { - second_new_area = malloc (sizeof (ply_frame_buffer_area_t)); - second_new_area->x = new_area->x; - second_new_area->y = old_area->y; - second_new_area->width = old_area->x - new_area->x; - second_new_area->height = (new_area->y + new_area->height) - old_area->y; - new_area->height = old_area->y - new_area->y; - - integrate_area_with_flush_area (buffer, node, second_new_area); - integrate_area_with_flush_area (buffer, node, new_area); - return; - } - case H_COLLISION_RIGHT: /* collision with old top right corner, split new into two */ - { - second_new_area = malloc (sizeof (ply_frame_buffer_area_t)); - second_new_area->x = old_area->x + old_area->width; - second_new_area->y = old_area->y; - second_new_area->width = (new_area->x + new_area->width) - (old_area->x + old_area->width); - second_new_area->height = (new_area->y + new_area->height) - old_area->y; - new_area->height = old_area->y - new_area->y; - - integrate_area_with_flush_area (buffer, node, second_new_area); - integrate_area_with_flush_area (buffer, node, new_area); - return; - } - case H_COLLISION_BOTH: /* collision with old top, left and right corners, trim old */ - old_area->height = (old_area->y + old_area->height) - (new_area->y + new_area->height); - old_area->y = new_area->y + new_area->height; - break; - case H_COLLISION_CONTAINED: /* collision with old top edge only, trim new */ - new_area->height = old_area->y - new_area->y; - break; - } - break; - } - case V_COLLISION_BOTTOM: - { - switch (h_collision) - { - case H_COLLISION_NONE: /* no collision */ - break; - case H_COLLISION_LEFT: /* collision with old bottom left corner, split new into two */ - { - second_new_area = malloc (sizeof (ply_frame_buffer_area_t)); - second_new_area->x = new_area->x; - second_new_area->y = new_area->y; - second_new_area->width = old_area->x - new_area->x; - second_new_area->height = (old_area->y + old_area->height) - new_area->y; - - new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height); - new_area->y = old_area->y + old_area->height; - - integrate_area_with_flush_area (buffer, node, second_new_area); - integrate_area_with_flush_area (buffer, node, new_area); - return; - } - case H_COLLISION_RIGHT: /* collision with old bottom right corner, split new into two */ - { - second_new_area = malloc (sizeof (ply_frame_buffer_area_t)); - second_new_area->x = old_area->x + old_area->width; - second_new_area->y = new_area->y; - second_new_area->width = (new_area->x + new_area->width) - (old_area->x + old_area->width); - second_new_area->height = (old_area->y + old_area->height) - new_area->y; - - new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height); - new_area->y = old_area->y + old_area->height; - - integrate_area_with_flush_area (buffer, node, second_new_area); - integrate_area_with_flush_area (buffer, node, new_area); - return; - } - case H_COLLISION_BOTH: /* collision with old bottom, left and right corners, trim old */ - old_area->height = new_area->y - old_area->y; - break; - case H_COLLISION_CONTAINED: /* collision with old botoom edge only, trim new */ - new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height); - new_area->y = old_area->y + old_area->height; - break; - } - break; - } - case V_COLLISION_BOTH: - { - switch (h_collision) - { - case H_COLLISION_NONE: /* no collision */ - break; - case H_COLLISION_LEFT: /* collision with old left, top and bottom corners, trim old */ - old_area->width = (old_area->x + old_area->width) - (new_area->x + new_area->width); - old_area->x = new_area->x + new_area->width; - break; - case H_COLLISION_RIGHT: /* collision with old right, top and bottom corners, trim old */ - old_area->width = new_area->x - old_area->x; - break; - case H_COLLISION_BOTH: /* old fully contained within new, remove old */ - free (old_area); - ply_list_remove_node (buffer->areas_to_flush, node); - break; - case H_COLLISION_CONTAINED: /* collision with old top and bottom edges but not left and right, split new into two */ - { - second_new_area = malloc (sizeof (ply_frame_buffer_area_t)); - second_new_area->x = new_area->x; - second_new_area->y = old_area->y + old_area->height; - second_new_area->width = new_area->width; - second_new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height); - new_area->height = old_area->y - new_area->y; - - integrate_area_with_flush_area (buffer, node, second_new_area); - integrate_area_with_flush_area (buffer, node, new_area); - return; - } - } - break; - } - case V_COLLISION_CONTAINED: - { - switch (h_collision) - { - case H_COLLISION_NONE: /* no collision */ - break; - case H_COLLISION_LEFT: /* collision with old left edge only, trim new */ - new_area->width = old_area->x - new_area->x; - break; - case H_COLLISION_RIGHT: /* collision with old right edge only, trim new */ - new_area->width = (new_area->x + new_area->width) - (old_area->x + old_area->width); - new_area->x = old_area->x + old_area->width; - break; - case H_COLLISION_BOTH: - { /* collision with old left and right edges but not top and botton, split new into two */ - second_new_area = malloc (sizeof (ply_frame_buffer_area_t)); - second_new_area->x = old_area->x + old_area->width; - second_new_area->y = new_area->y; - second_new_area->width = (new_area->x + new_area->width) - (old_area->x + old_area->width); - second_new_area->height = new_area->height; - new_area->width = old_area->x - new_area->x; - - integrate_area_with_flush_area (buffer, node, second_new_area); - integrate_area_with_flush_area (buffer, node, new_area); - return; - } - case H_COLLISION_CONTAINED: /* new fully contained within old, remove new */ - free (new_area); - return; - } - break; - } - } - node = next_node; - } - - ply_list_append_data (buffer->areas_to_flush, new_area); -} - -static void -ply_frame_buffer_add_area_to_flush_area (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area) -{ - ply_frame_buffer_area_t *cropped_area; - - assert (buffer != NULL); - assert (area != NULL); - - cropped_area = malloc (sizeof (ply_frame_buffer_area_t)); - ply_frame_buffer_area_intersect (area, &buffer->area, cropped_area); - - if (cropped_area->width == 0 || cropped_area->height == 0) - { - free (cropped_area); - return; - } - - integrate_area_with_flush_area (buffer, - ply_list_get_first_node (buffer->areas_to_flush), - cropped_area); -} - -static bool -ply_frame_buffer_flush (ply_frame_buffer_t *buffer) -{ - ply_list_node_t *node; - assert (buffer != NULL); - - if (buffer->pause_count > 0) - return true; - - node = ply_list_get_first_node (buffer->areas_to_flush); - while (node != NULL) - { - ply_list_node_t *next_node; - ply_frame_buffer_area_t *area_to_flush; - - area_to_flush = (ply_frame_buffer_area_t *) ply_list_node_get_data (node); - - next_node = ply_list_get_next_node (buffer->areas_to_flush, node); - - (*buffer->flush_area) (buffer, area_to_flush); - - free (area_to_flush); - ply_list_remove_node (buffer->areas_to_flush, node); - - node = next_node; - } - - return true; -} - -ply_frame_buffer_t * -ply_frame_buffer_new (const char *device_name) -{ - ply_frame_buffer_t *buffer; - - buffer = calloc (1, sizeof (ply_frame_buffer_t)); - - if (device_name != NULL) - buffer->device_name = strdup (device_name); - else if (getenv ("FRAMEBUFFER") != NULL) - buffer->device_name = strdup (getenv ("FRAMEBUFFER")); - else - buffer->device_name = - strdup (PLY_FRAME_BUFFER_DEFAULT_FB_DEVICE_NAME); - - buffer->map_address = MAP_FAILED; - buffer->shadow_buffer = NULL; - buffer->areas_to_flush = ply_list_new (); - - buffer->pause_count = 0; - - return buffer; -} - -static void -free_flush_areas (ply_frame_buffer_t *buffer) -{ - ply_list_node_t *node; - - node = ply_list_get_first_node (buffer->areas_to_flush); - while (node != NULL) - { - ply_list_node_t *next_node; - ply_frame_buffer_area_t *area_to_flush; - - area_to_flush = (ply_frame_buffer_area_t *) ply_list_node_get_data (node); - - next_node = ply_list_get_next_node (buffer->areas_to_flush, node); - - free (area_to_flush); - ply_list_remove_node (buffer->areas_to_flush, node); - - node = next_node; - } - - ply_list_free (buffer->areas_to_flush); -} - -void -ply_frame_buffer_free (ply_frame_buffer_t *buffer) -{ - assert (buffer != NULL); - - if (ply_frame_buffer_device_is_open (buffer)) - ply_frame_buffer_close (buffer); - - free_flush_areas (buffer); - - free (buffer->device_name); - free (buffer->shadow_buffer); - free (buffer); -} - -bool -ply_frame_buffer_open (ply_frame_buffer_t *buffer) -{ - bool is_open; - - assert (buffer != NULL); - - is_open = false; - - if (!ply_frame_buffer_open_device (buffer)) - { - goto out; - } - - if (!ply_frame_buffer_query_device (buffer)) - { - goto out; - } - - if (!ply_frame_buffer_map_to_device (buffer)) - { - goto out; - } - - buffer->shadow_buffer = - realloc (buffer->shadow_buffer, 4 * buffer->area.width * buffer->area.height); - memset (buffer->shadow_buffer, 0, 4 * buffer->area.width * buffer->area.height); - ply_frame_buffer_fill_with_color (buffer, NULL, 0.0, 0.0, 0.0, 1.0); - - is_open = true; - -out: - - if (!is_open) - { - int saved_errno; - - saved_errno = errno; - ply_frame_buffer_close_device (buffer); - errno = saved_errno; - } - - return is_open; -} - -void -ply_frame_buffer_pause_updates (ply_frame_buffer_t *buffer) -{ - assert (buffer != NULL); - - buffer->pause_count++; -} - -bool -ply_frame_buffer_unpause_updates (ply_frame_buffer_t *buffer) -{ - assert (buffer != NULL); - - buffer->pause_count--; - return ply_frame_buffer_flush (buffer); -} - -bool -ply_frame_buffer_device_is_open (ply_frame_buffer_t *buffer) -{ - assert (buffer != NULL); - return buffer->device_fd >= 0 && buffer->map_address != MAP_FAILED; -} - -char * -ply_frame_buffer_get_device_name (ply_frame_buffer_t *buffer) -{ - assert (buffer != NULL); - assert (ply_frame_buffer_device_is_open (buffer)); - assert (buffer->device_name != NULL); - - return strdup (buffer->device_name); -} - -void -ply_frame_buffer_set_device_name (ply_frame_buffer_t *buffer, - const char *device_name) -{ - assert (buffer != NULL); - assert (!ply_frame_buffer_device_is_open (buffer)); - assert (device_name != NULL); - assert (buffer->device_name != NULL); - - if (strcmp (buffer->device_name, device_name) != 0) - { - free (buffer->device_name); - buffer->device_name = strdup (device_name); - } -} - -void -ply_frame_buffer_close (ply_frame_buffer_t *buffer) -{ - assert (buffer != NULL); - - assert (ply_frame_buffer_device_is_open (buffer)); - ply_frame_buffer_close_device (buffer); - - buffer->bytes_per_pixel = 0; - buffer->area.x = 0; - buffer->area.y = 0; - buffer->area.width = 0; - buffer->area.height = 0; -} - -void -ply_frame_buffer_get_size (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *size) -{ - assert (buffer != NULL); - assert (ply_frame_buffer_device_is_open (buffer)); - assert (size != NULL); - - *size = buffer->area; -} - -static void -ply_frame_buffer_area_intersect (ply_frame_buffer_area_t *area1, - ply_frame_buffer_area_t *area2, - ply_frame_buffer_area_t *result) -{ - long x1, y1, x2, y2; - long width, height; - - if (area1->width == 0) - { - *result = *area1; - return; - } - - if (area2->width == 0) - { - *result = *area2; - return; - } - - x1 = area1->x + area1->width; - y1 = area1->y + area1->height; - x2 = area2->x + area2->width; - y2 = area2->y + area2->height; - - result->x = MAX(area1->x, area2->x); - result->y = MAX(area1->y, area2->y); - - width = MIN(x1, x2) - result->x; - height = MIN(y1, y2) - result->y; - if (width <= 0 || height <= 0) - { - result->width = 0; - result->height = 0; - } - else - { - result->width = width; - result->height = height; - } -} - -bool -ply_frame_buffer_fill_with_gradient (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - uint32_t start, - uint32_t end) -{ -/* The gradient produced is a linear interpolation of the two passed - * in color stops: start and end. - * - * In order to prevent banding when the color stops are too close - * together, or are stretched over too large an area, we slightly - * perturb the intermediate colors as we generate them. - * - * Before we do this, we store the interpolated color values in a - * fixed point number with lots of fractional bits. This is so - * we don't add noise after the values have been clamped to 8-bits - * - * We add random noise to all of the fractional bits of each color - * channel and also NOISE_BITS worth of noise to the non-fractional - * part of the color. By default NOISE_BITS is 1. - * - * We incorporate the noise by filling the bottom 24 bits of an - * integer with random bits and then shifting the color channels - * to the left such that the top 8 bits of the channel overlap - * the noise by NOISE_BITS. E.g., if NOISE_BITS is 1, then the top - * 7 bits of each channel won't overlap with the noise, and the 8th - * bit + fractional bits will. When the noise and color channel - * are properly aligned, we add them together, drop the precision - * of the resulting channels back to 8 bits and stuff the results - * into a pixel in the frame buffer. - */ -#define NOISE_BITS 1 -/* In the color stops, red is 8 bits starting at position 24 - * (since they're argb32 pixels). - * We want to move those 8 bits such that the bottom NOISE_BITS - * of them overlap the top of the 24 bits of generated noise. - * Of course, green and blue are 8 bits away from red and each - * other, respectively. - */ -#define RED_SHIFT (32 - (24 + NOISE_BITS)) -#define GREEN_SHIFT (RED_SHIFT + 8) -#define BLUE_SHIFT (GREEN_SHIFT + 8) -#define NOISE_MASK (0x00ffffff) - -/* Once, we've lined up the color channel we're interested in with - * the noise, we need to mask out the other channels. - */ -#define COLOR_MASK (0xff << (24 - NOISE_BITS)) - - uint32_t red, green, blue, red_step, green_step, blue_step, t, pixel; - uint32_t x, y; - /* we use a fixed seed so that the dithering doesn't change on repaints - * of the same area. - */ - uint32_t noise = 0x100001; - ply_frame_buffer_area_t cropped_area; - - if (area == NULL) - area = &buffer->area; - - ply_frame_buffer_area_intersect (area, &buffer->area, &cropped_area); - - red = (start << RED_SHIFT) & COLOR_MASK; - green = (start << GREEN_SHIFT) & COLOR_MASK; - blue = (start << BLUE_SHIFT) & COLOR_MASK; - - t = (end << RED_SHIFT) & COLOR_MASK; - red_step = (int32_t) (t - red) / (int32_t) buffer->area.height; - t = (end << GREEN_SHIFT) & COLOR_MASK; - green_step = (int32_t) (t - green) / (int32_t) buffer->area.height; - t = (end << BLUE_SHIFT) & COLOR_MASK; - blue_step = (int32_t) (t - blue) / (int32_t) buffer->area.height; - - -#define RANDOMIZE(num) (num = (num + (num << 1)) & NOISE_MASK) -#define UNROLLED_PIXEL_COUNT 8 - - for (y = buffer->area.y; y < buffer->area.y + buffer->area.height; y++) - { - if (cropped_area.y <= y && y < cropped_area.y + cropped_area.height) - { - if (cropped_area.width < UNROLLED_PIXEL_COUNT) - { - for (x = cropped_area.x; x < cropped_area.x + cropped_area.width; x++) - { - pixel = 0xff000000; - RANDOMIZE(noise); - pixel |= (((red + noise) & COLOR_MASK) >> RED_SHIFT); - RANDOMIZE(noise); - pixel |= (((green + noise) & COLOR_MASK) >> GREEN_SHIFT); - RANDOMIZE(noise); - pixel |= (((blue + noise) & COLOR_MASK) >> BLUE_SHIFT); - - buffer->shadow_buffer[y * buffer->area.width + x] = pixel; - } - } - else - { - uint32_t shaded_set[UNROLLED_PIXEL_COUNT]; - uint32_t *ptr = &buffer->shadow_buffer[y * buffer->area.width + cropped_area.x]; - for (x = 0; x < UNROLLED_PIXEL_COUNT; x++) - { - shaded_set[x] = 0xff000000; - RANDOMIZE(noise); - shaded_set[x] |= (((red + noise) & COLOR_MASK) >> RED_SHIFT); - RANDOMIZE(noise); - shaded_set[x] |= (((green + noise) & COLOR_MASK) >> GREEN_SHIFT); - RANDOMIZE(noise); - shaded_set[x] |= (((blue + noise) & COLOR_MASK) >> BLUE_SHIFT); - } - for (x = cropped_area.width; x >=UNROLLED_PIXEL_COUNT; x-=UNROLLED_PIXEL_COUNT) - { - memcpy((void*)ptr, (void*)shaded_set, UNROLLED_PIXEL_COUNT * sizeof(uint32_t)); - ptr += UNROLLED_PIXEL_COUNT; - } - memcpy((void*)ptr, (void*)shaded_set, x * sizeof(uint32_t)); - - - } - - } - - red += red_step; - green += green_step; - blue += blue_step; - } - - ply_frame_buffer_add_area_to_flush_area (buffer, &cropped_area); - - return ply_frame_buffer_flush (buffer); -} - -bool -ply_frame_buffer_fill_with_color (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - double red, - double green, - double blue, - double alpha) -{ - uint32_t pixel_value; - ply_frame_buffer_area_t cropped_area; - - assert (buffer != NULL); - assert (ply_frame_buffer_device_is_open (buffer)); - - if (area == NULL) - area = &buffer->area; - - ply_frame_buffer_area_intersect (area, &buffer->area, &cropped_area); - - red *= alpha; - green *= alpha; - blue *= alpha; - - pixel_value = PLY_FRAME_BUFFER_COLOR_TO_PIXEL_VALUE (red, green, blue, alpha); - - ply_frame_buffer_fill_area_with_pixel_value (buffer, &cropped_area, pixel_value); - - ply_frame_buffer_add_area_to_flush_area (buffer, &cropped_area); - - return ply_frame_buffer_flush (buffer); -} - -bool -ply_frame_buffer_fill_with_hex_color_at_opacity (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - uint32_t hex_color, - double opacity) -{ - ply_frame_buffer_area_t cropped_area; - uint32_t pixel_value; - double red; - double green; - double blue; - double alpha; - - assert (buffer != NULL); - assert (ply_frame_buffer_device_is_open (buffer)); - - if (area == NULL) - area = &buffer->area; - - ply_frame_buffer_area_intersect (area, &buffer->area, &cropped_area); - - /* if they only gave an rgb hex number, assume an alpha of 0xff - */ - if ((hex_color & 0xff000000) == 0) - hex_color = (hex_color << 8) | 0xff; - - red = ((double) (hex_color & 0xff000000) / 0xff000000); - green = ((double) (hex_color & 0x00ff0000) / 0x00ff0000); - blue = ((double) (hex_color & 0x0000ff00) / 0x0000ff00); - alpha = ((double) (hex_color & 0x000000ff) / 0x000000ff); - - alpha *= opacity; - - red *= alpha; - green *= alpha; - blue *= alpha; - - pixel_value = PLY_FRAME_BUFFER_COLOR_TO_PIXEL_VALUE (red, green, blue, alpha); - - ply_frame_buffer_fill_area_with_pixel_value (buffer, &cropped_area, pixel_value); - - ply_frame_buffer_add_area_to_flush_area (buffer, &cropped_area); - - return ply_frame_buffer_flush (buffer); -} - -bool -ply_frame_buffer_fill_with_hex_color (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - uint32_t hex_color) -{ - return ply_frame_buffer_fill_with_hex_color_at_opacity (buffer, area, hex_color, 1.0); -} - -bool -ply_frame_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - ply_frame_buffer_area_t *clip, - unsigned long x, - unsigned long y, - uint32_t *data, - double opacity) -{ - unsigned long row, column; - uint8_t opacity_as_byte; - ply_frame_buffer_area_t cropped_area; - - assert (buffer != NULL); - assert (ply_frame_buffer_device_is_open (buffer)); - - if (area == NULL) - area = &buffer->area; - - ply_frame_buffer_area_intersect (area, &buffer->area, &cropped_area); - - if (clip) - ply_frame_buffer_area_intersect (&cropped_area, clip, &cropped_area); - - if (cropped_area.width == 0 || cropped_area.height == 0) - return true; - - x += cropped_area.x - area->x; - y += cropped_area.y - area->y; - 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; - - pixel_value = data[area->width * row + column]; - if ((pixel_value >> 24) == 0x00) - continue; - - pixel_value = make_pixel_value_translucent (pixel_value, opacity_as_byte); - ply_frame_buffer_blend_value_at_pixel (buffer, - cropped_area.x + (column - x), - cropped_area.y + (row - y), - pixel_value); - - } - } - - ply_frame_buffer_add_area_to_flush_area (buffer, &cropped_area); - - return ply_frame_buffer_flush (buffer); -} - -bool -ply_frame_buffer_fill_with_argb32_data_at_opacity (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - unsigned long x, - unsigned long y, - uint32_t *data, - double opacity) -{ - return ply_frame_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer, area, NULL, - x, y, data, opacity); -} - -bool -ply_frame_buffer_fill_with_argb32_data (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - unsigned long x, - unsigned long y, - uint32_t *data) -{ - return ply_frame_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer, area, NULL, - x, y, data, 1.0); -} - -bool -ply_frame_buffer_fill_with_argb32_data_with_clip (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - ply_frame_buffer_area_t *clip, - unsigned long x, - unsigned long y, - uint32_t *data) -{ - return ply_frame_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer, area, clip, - x, y, data, 1.0); -} - -const char * -ply_frame_buffer_get_bytes (ply_frame_buffer_t *buffer) -{ - return (char *) buffer->shadow_buffer; -} - -#ifdef PLY_FRAME_BUFFER_ENABLE_TEST - -#include -#include -#include - -static double -get_current_time (void) -{ - const double microseconds_per_second = 1000000.0; - double timestamp; - struct timeval now = { 0L, /* zero-filled */ }; - - gettimeofday (&now, NULL); - timestamp = ((microseconds_per_second * now.tv_sec) + now.tv_usec) / - microseconds_per_second; - - return timestamp; -} - -static void -animate_at_time (ply_frame_buffer_t *buffer, - double time) -{ - unsigned int x, y; - uint32_t *data; - ply_frame_buffer_area_t area; - - ply_frame_buffer_get_size (buffer, &area); - - data = calloc (area.width * area.height, sizeof (uint32_t)); - - for (y = 0; y < area.height; y++) - { - int blue_bit_position; - uint8_t red, green, blue, alpha; - - blue_bit_position = (int) 64 * (.5 * sin (time) + .5) + (255 - 64); - blue = rand () % blue_bit_position; - for (x = 0; x < area.width; x++) - { - alpha = 0xff; - red = (uint8_t) ((y / (area.height * 1.0)) * 255.0); - green = (uint8_t) ((x / (area.width * 1.0)) * 255.0); - - red = green = (red + green + blue) / 3; - - data[y * area.width + x] = (alpha << 24) | (red << 16) | (green << 8) | blue; - } - } - - ply_frame_buffer_fill_with_argb32_data (buffer, NULL, 0, 0, data); -} - -int -main (int argc, - char **argv) -{ - static unsigned int seed = 0; - ply_frame_buffer_t *buffer; - int exit_code; - - exit_code = 0; - - buffer = ply_frame_buffer_new (NULL); - - if (!ply_frame_buffer_open (buffer)) - { - exit_code = errno; - perror ("could not open frame buffer"); - return exit_code; - } - - if (seed == 0) - { - seed = (int) get_current_time (); - srand (seed); - } - - while ("we want to see ad-hoc animations") - { - animate_at_time (buffer, get_current_time ()); - usleep (1000000/30.); - } - - ply_frame_buffer_close (buffer); - ply_frame_buffer_free (buffer); - - return main (argc, argv); -} - -#endif /* PLY_FRAME_BUFFER_ENABLE_TEST */ - -/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/libply/ply-frame-buffer.h b/src/libply/ply-frame-buffer.h deleted file mode 100644 index d30e4ef4..00000000 --- a/src/libply/ply-frame-buffer.h +++ /dev/null @@ -1,112 +0,0 @@ -/* ply-frame-buffer.h - framebuffer abstraction - * - * Copyright (C) 2007 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written By: Ray Strode - */ -#ifndef PLY_FRAME_BUFFER_H -#define PLY_FRAME_BUFFER_H - -#include -#include - -#include "ply-utils.h" - -typedef struct _ply_frame_buffer ply_frame_buffer_t; -typedef struct _ply_frame_buffer_area ply_frame_buffer_area_t; - -struct _ply_frame_buffer_area -{ - long x; - long y; - unsigned long width; - unsigned long height; -}; - -#define PLY_FRAME_BUFFER_COLOR_TO_PIXEL_VALUE(r,g,b,a) \ - (((uint8_t) (CLAMP (a * 255.0, 0.0, 255.0)) << 24) \ - | ((uint8_t) (CLAMP (r * 255.0, 0.0, 255.0)) << 16) \ - | ((uint8_t) (CLAMP (g * 255.0, 0.0, 255.0)) << 8) \ - | ((uint8_t) (CLAMP (b * 255.0, 0.0, 255.0)))) - -#ifndef PLY_HIDE_FUNCTION_DECLARATIONS -ply_frame_buffer_t *ply_frame_buffer_new (const char *device_name); -void ply_frame_buffer_free (ply_frame_buffer_t *buffer); -bool ply_frame_buffer_open (ply_frame_buffer_t *buffer); -void ply_frame_buffer_pause_updates (ply_frame_buffer_t *buffer); -bool ply_frame_buffer_unpause_updates (ply_frame_buffer_t *buffer); -bool ply_frame_buffer_device_is_open (ply_frame_buffer_t *buffer); -char *ply_frame_buffer_get_device_name (ply_frame_buffer_t *buffer); -void ply_frame_buffer_set_device_name (ply_frame_buffer_t *buffer, - const char *device_name); -void ply_frame_buffer_close (ply_frame_buffer_t *buffer); -void ply_frame_buffer_get_size (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *size); -bool ply_frame_buffer_fill_with_color (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - double red, - double green, - double blue, - double alpha); -bool ply_frame_buffer_fill_with_hex_color (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - uint32_t hex_color); - -bool ply_frame_buffer_fill_with_hex_color_at_opacity (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - uint32_t hex_color, - double opacity); - -bool ply_frame_buffer_fill_with_gradient (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - uint32_t start, - uint32_t end); - -bool ply_frame_buffer_fill_with_argb32_data (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - unsigned long x, - unsigned long y, - uint32_t *data); -bool ply_frame_buffer_fill_with_argb32_data_at_opacity (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - unsigned long x, - unsigned long y, - uint32_t *data, - double opacity); - -bool ply_frame_buffer_fill_with_argb32_data_with_clip (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - ply_frame_buffer_area_t *clip, - unsigned long x, - unsigned long y, - uint32_t *data); -bool ply_frame_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_frame_buffer_t *buffer, - ply_frame_buffer_area_t *area, - ply_frame_buffer_area_t *clip, - unsigned long x, - unsigned long y, - uint32_t *data, - double opacity); - -const char *ply_frame_buffer_get_bytes (ply_frame_buffer_t *buffer); - - -#endif - -#endif /* PLY_FRAME_BUFFER_H */ -/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/libply/tests/Makefile.am b/src/libply/tests/Makefile.am index 49ba5760..5707c251 100644 --- a/src/libply/tests/Makefile.am +++ b/src/libply/tests/Makefile.am @@ -5,7 +5,6 @@ INCLUDES = \ TESTS = if ENABLE_TESTS -include $(srcdir)/ply-frame-buffer-test.am include $(srcdir)/ply-terminal-session-test.am include $(srcdir)/ply-logger-test.am include $(srcdir)/ply-array-test.am diff --git a/src/libply/tests/ply-frame-buffer-test.am b/src/libply/tests/ply-frame-buffer-test.am deleted file mode 100644 index 82afe7fd..00000000 --- a/src/libply/tests/ply-frame-buffer-test.am +++ /dev/null @@ -1,14 +0,0 @@ -TESTS += ply-frame-buffer-test - -ply_frame_buffer_test_CFLAGS = $(PLYMOUTH_CFLAGS) -DPLY_FRAME_BUFFER_ENABLE_TEST -ply_frame_buffer_test_LDADD = $(PLYMOUTH_LIBS) -ply_frame_buffer_test_SOURCES = \ - $(srcdir)/../ply-utils.h \ - $(srcdir)/../ply-frame-buffer.h \ - $(srcdir)/../ply-frame-buffer.c \ - $(srcdir)/../ply-list.h \ - $(srcdir)/../ply-list.c \ - $(srcdir)/../ply-logger.h \ - $(srcdir)/../ply-logger.c \ - $(srcdir)/../ply-utils.h \ - $(srcdir)/../ply-utils.c From 4c45ba1df7d99e08d1728b61f1c87775152d0f23 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 17:23:32 -0400 Subject: [PATCH 34/43] [libplybootsplash] Drop window class It's been obsoleted by the display, keyboard, console and terminal classes. --- src/libplybootsplash/Makefile.am | 4 +- src/libplybootsplash/ply-window.c | 1156 ----------------------------- src/libplybootsplash/ply-window.h | 165 ---- src/tests/Makefile.am | 1 - src/tests/ply-window-test.am | 8 - 5 files changed, 1 insertion(+), 1333 deletions(-) delete mode 100644 src/libplybootsplash/ply-window.c delete mode 100644 src/libplybootsplash/ply-window.h delete mode 100644 src/tests/ply-window-test.am diff --git a/src/libplybootsplash/Makefile.am b/src/libplybootsplash/Makefile.am index 19479e21..d2638055 100644 --- a/src/libplybootsplash/Makefile.am +++ b/src/libplybootsplash/Makefile.am @@ -25,8 +25,7 @@ libplybootsplash_HEADERS = \ ply-terminal.h \ ply-text-display.h \ ply-text-progress-bar.h \ - ply-throbber.h \ - ply-window.h + ply-throbber.h libplybootsplash_la_CFLAGS = $(PLYMOUTH_CFLAGS) \ $(IMAGE_CFLAGS) \ @@ -55,7 +54,6 @@ libplybootsplash_la_SOURCES = \ ply-terminal.c \ ply-pixel-buffer.c \ ply-renderer.c \ - ply-window.c \ ply-boot-splash.c MAINTAINERCLEANFILES = Makefile.in diff --git a/src/libplybootsplash/ply-window.c b/src/libplybootsplash/ply-window.c deleted file mode 100644 index 27328930..00000000 --- a/src/libplybootsplash/ply-window.c +++ /dev/null @@ -1,1156 +0,0 @@ -/* ply-window.h - APIs for putting up a window screen - * - * Copyright (C) 2007 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: Ray Strode - */ -#include "config.h" -#include "ply-window.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "ply-buffer.h" -#include "ply-event-loop.h" -#include "ply-frame-buffer.h" -#include "ply-list.h" -#include "ply-logger.h" -#include "ply-utils.h" - -#define KEY_CTRL_L ('\100' ^'L') -#define KEY_CTRL_P ('\100' ^'P') -#define KEY_CTRL_T ('\100' ^'T') -#define KEY_CTRL_U ('\100' ^'U') -#define KEY_CTRL_W ('\100' ^'W') -#define KEY_CTRL_V ('\100' ^'V') -#define KEY_ESCAPE ('\100' ^'[') -#define KEY_RETURN '\r' -#define KEY_BACKSPACE '\177' - -#ifndef CLEAR_SCREEN_SEQUENCE -#define CLEAR_SCREEN_SEQUENCE "\033[2J" -#endif - -#ifndef CLEAR_LINE_SEQUENCE -#define CLEAR_LINE_SEQUENCE "\033[2K\r\n" -#endif - -#ifndef BACKSPACE -#define BACKSPACE "\b\033[0K" -#endif - -#ifndef MOVE_CURSOR_SEQUENCE -#define MOVE_CURSOR_SEQUENCE "\033[%d;%df" -#endif - -#ifndef HIDE_CURSOR_SEQUENCE -#define HIDE_CURSOR_SEQUENCE "\033[?25l" -#endif - -#ifndef SHOW_CURSOR_SEQUENCE -#define SHOW_CURSOR_SEQUENCE "\033[?25h" -#endif - -#ifndef COLOR_SEQUENCE_FORMAT -#define COLOR_SEQUENCE_FORMAT "\033[%dm" -#endif - -#ifndef FOREGROUND_COLOR_BASE -#define FOREGROUND_COLOR_BASE 30 -#endif - -#ifndef BACKGROUND_COLOR_BASE -#define BACKGROUND_COLOR_BASE 40 -#endif - -#ifndef TEXT_PALETTE_SIZE -#define TEXT_PALETTE_SIZE 48 -#endif - -typedef void (* ply_window_handler_t) (void *); - -typedef struct -{ - ply_window_handler_t *function; - void *user_data; -} ply_window_closure_t; - -struct _ply_window -{ - ply_event_loop_t *loop; - ply_buffer_t *keyboard_input_buffer; - ply_buffer_t *line_buffer; - - struct termios original_term_attributes; - - ply_frame_buffer_t *frame_buffer; - - char *tty_name; - int tty_fd; - int vt_number; - - ply_fd_watch_t *tty_fd_watch; - ply_window_mode_t mode; - ply_window_color_t foreground_color; - ply_window_color_t background_color; - - uint8_t original_color_palette[TEXT_PALETTE_SIZE]; - uint8_t color_palette[TEXT_PALETTE_SIZE]; - - int number_of_text_rows; - int number_of_text_columns; - - uint32_t should_force_text_mode : 1; - uint32_t original_term_attributes_saved : 1; - uint32_t supports_text_color : 1; - uint32_t is_open : 1; - - ply_list_t *keyboard_input_handler_list; - ply_list_t *backspace_handler_list; - ply_list_t *escape_handler_list; - ply_list_t *enter_handler_list; - - ply_window_draw_handler_t draw_handler; - void *draw_handler_user_data; - - ply_window_erase_handler_t erase_handler; - void *erase_handler_user_data; -}; - -static bool ply_window_open_tty (ply_window_t *window); - -ply_window_t * -ply_window_new (const char *tty_name) -{ - ply_window_t *window; - - window = calloc (1, sizeof (ply_window_t)); - window->keyboard_input_buffer = ply_buffer_new (); - window->line_buffer = ply_buffer_new (); - window->frame_buffer = ply_frame_buffer_new (NULL); - window->keyboard_input_handler_list = ply_list_new(); - window->backspace_handler_list = ply_list_new(); - window->escape_handler_list = ply_list_new(); - window->enter_handler_list = ply_list_new(); - - window->loop = NULL; - if (tty_name != NULL) - { - if (strncmp (tty_name, "/dev/", strlen ("/dev/")) == 0) - window->tty_name = strdup (tty_name); - else - asprintf (&window->tty_name, "/dev/%s", tty_name); - } - window->tty_fd = -1; - - return window; -} - -static void -ply_window_look_up_color_palette (ply_window_t *window) -{ - if (ioctl (window->tty_fd, GIO_CMAP, window->color_palette) < 0) - window->supports_text_color = false; - else - window->supports_text_color = true; -} - -static bool -ply_window_change_color_palette (ply_window_t *window) -{ - if (!window->supports_text_color) - return true; - - if (ioctl (window->tty_fd, PIO_CMAP, window->color_palette) < 0) - return false; - - return true; -} - -static void -ply_window_save_color_palette (ply_window_t *window) -{ - if (!window->supports_text_color) - return; - - memcpy (window->original_color_palette, window->color_palette, - TEXT_PALETTE_SIZE); -} - -static void -ply_window_restore_color_palette (ply_window_t *window) -{ - if (!window->supports_text_color) - return; - - memcpy (window->color_palette, window->original_color_palette, - TEXT_PALETTE_SIZE); - - ply_window_change_color_palette (window); -} - -void -ply_window_reset_colors (ply_window_t *window) -{ - assert (window != NULL); - - ply_window_restore_color_palette (window); -} - -static void -process_backspace (ply_window_t *window) -{ - size_t bytes_to_remove; - ssize_t previous_character_size; - const char *bytes; - size_t size; - ply_list_node_t *node; - - bytes = ply_buffer_get_bytes (window->line_buffer); - size = ply_buffer_get_size (window->line_buffer); - - bytes_to_remove = MIN(size, PLY_UTF8_CHARACTER_SIZE_MAX); - while ((previous_character_size = ply_utf8_character_get_size (bytes + size - bytes_to_remove, bytes_to_remove)) < (ssize_t) bytes_to_remove) - { - if (previous_character_size > 0) - bytes_to_remove -= previous_character_size; - else - bytes_to_remove--; - } - - if (bytes_to_remove <= size) - { - ply_buffer_remove_bytes_at_end (window->line_buffer, bytes_to_remove); - } - - for (node = ply_list_get_first_node(window->backspace_handler_list); - node; node = ply_list_get_next_node(window->backspace_handler_list, node)) - { - ply_window_closure_t *closure = ply_list_node_get_data (node); - ply_window_backspace_handler_t backspace_handler = - (ply_window_backspace_handler_t) closure->function; - backspace_handler (closure->user_data); - } -} - -static void -process_line_erase (ply_window_t *window) -{ - size_t size; - - while ((size = ply_buffer_get_size (window->line_buffer)) > 0) - process_backspace (window); -} - -static void -process_keyboard_input (ply_window_t *window, - const char *keyboard_input, - size_t character_size) -{ - wchar_t key; - ply_list_node_t *node; - - if ((ssize_t) mbrtowc (&key, keyboard_input, character_size, NULL) > 0) - { - switch (key) - { - - case KEY_CTRL_L: - if (ply_frame_buffer_device_is_open (window->frame_buffer)) - { - ply_frame_buffer_area_t area; - - ply_trace ("redrawing screen"); - - ply_frame_buffer_get_size (window->frame_buffer, &area); - ply_window_draw_area (window, area.x, area.y, - area.width, area.height); - } - return; - - case KEY_CTRL_P: - ply_trace ("restore text palette to original value!"); - ply_window_restore_color_palette (window); - return; - - case KEY_CTRL_T: - ply_trace ("toggle text mode!"); - window->should_force_text_mode = !window->should_force_text_mode; - ply_window_set_mode (window, window->mode); - ply_trace ("text mode toggled!"); - return; - - case KEY_CTRL_U: - case KEY_CTRL_W: - ply_trace ("erase line!"); - process_line_erase (window); - return; - - case KEY_CTRL_V: - ply_trace ("toggle verbose mode!"); - ply_toggle_tracing (); - ply_trace ("verbose mode toggled!"); - return; - - case KEY_ESCAPE: - ply_trace ("escape key!"); - for (node = ply_list_get_first_node(window->escape_handler_list); - node; node = ply_list_get_next_node(window->escape_handler_list, node)) - { - ply_window_closure_t *closure = ply_list_node_get_data (node); - ply_window_escape_handler_t escape_handler = (ply_window_escape_handler_t) closure->function; - escape_handler (closure->user_data); - } - - ply_trace ("end escape key handler"); - return; - - case KEY_BACKSPACE: - ply_trace ("backspace key!"); - process_backspace (window); - return; - - case KEY_RETURN: - ply_trace ("return key!"); - - for (node = ply_list_get_first_node(window->enter_handler_list); - node; node = ply_list_get_next_node(window->enter_handler_list, node)) - { - ply_window_closure_t *closure = ply_list_node_get_data (node); - ply_window_enter_handler_t enter_handler = (ply_window_enter_handler_t) closure->function; - enter_handler (closure->user_data, ply_buffer_get_bytes (window->line_buffer)); - } - ply_buffer_clear (window->line_buffer); - return; - - default: - ply_buffer_append_bytes (window->line_buffer, - keyboard_input, character_size); - break; - } - } - for (node = ply_list_get_first_node(window->keyboard_input_handler_list); - node; node = ply_list_get_next_node(window->keyboard_input_handler_list, node)) - { - ply_window_closure_t *closure = ply_list_node_get_data (node); - ply_window_keyboard_input_handler_t keyboard_input_handler = - (ply_window_keyboard_input_handler_t) closure->function; - - keyboard_input_handler (closure->user_data, - keyboard_input, character_size); - } -} - -static void -check_buffer_for_key_events (ply_window_t *window) -{ - const char *bytes; - size_t size, i; - - bytes = ply_buffer_get_bytes (window->keyboard_input_buffer); - size = ply_buffer_get_size (window->keyboard_input_buffer); - - i = 0; - while (i < size) - { - ssize_t character_size; - char *keyboard_input; - - character_size = (ssize_t) ply_utf8_character_get_size (bytes + i, size - i); - - if (character_size < 0) - break; - - /* If we're at a NUL character walk through it - */ - if (character_size == 0) - { - i++; - continue; - } - - keyboard_input = strndup (bytes + i, character_size); - - process_keyboard_input (window, keyboard_input, character_size); - - free (keyboard_input); - - i += character_size; - } - - if (i > 0) - ply_buffer_remove_bytes (window->keyboard_input_buffer, i); -} - -static void -on_key_event (ply_window_t *window) -{ - ply_buffer_append_from_fd (window->keyboard_input_buffer, window->tty_fd); - - check_buffer_for_key_events (window); -} - -static void -on_tty_disconnected (ply_window_t *window) -{ - ply_trace ("tty disconnected (fd %d)", window->tty_fd); - window->tty_fd_watch = NULL; - window->tty_fd = -1; - - if (window->tty_name != NULL) - { - ply_trace ("trying to reopen window '%s'", window->tty_name); - ply_window_open_tty (window); - } -} - -static bool -ply_window_set_unbuffered_input (ply_window_t *window) -{ - struct termios term_attributes; - - tcgetattr (window->tty_fd, &term_attributes); - - if (!window->original_term_attributes_saved) - { - window->original_term_attributes = term_attributes; - window->original_term_attributes_saved = true; - } - - cfmakeraw (&term_attributes); - - /* Make \n return go to the beginning of the next line */ - term_attributes.c_oflag |= ONLCR; - - if (tcsetattr (window->tty_fd, TCSAFLUSH, &term_attributes) != 0) - return false; - - return true; -} - -static bool -ply_window_set_buffered_input (ply_window_t *window) -{ - struct termios term_attributes; - - tcgetattr (window->tty_fd, &term_attributes); - - /* If someone already messed with the terminal settings, - * and they seem good enough, bail - */ - if (term_attributes.c_lflag & ICANON) - return true; - - /* If we don't know the original term attributes, or they were originally sucky, - * then invent some that are probably good enough. - */ - if (!window->original_term_attributes_saved || !(window->original_term_attributes.c_lflag & ICANON)) - { - term_attributes.c_iflag |= IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON; - term_attributes.c_oflag |= OPOST; - term_attributes.c_lflag |= ECHO | ECHONL | ICANON | ISIG | IEXTEN; - - if (tcsetattr (window->tty_fd, TCSAFLUSH, &term_attributes) != 0) - return false; - - return true; - } - - if (tcsetattr (window->tty_fd, TCSAFLUSH, &window->original_term_attributes) != 0) - return false; - - return true; -} - -static int -get_active_vt (void) -{ - int console_fd; - struct vt_stat console_state = { 0 }; - - console_fd = open ("/dev/tty0", O_RDONLY | O_NOCTTY); - - if (console_fd < 0) - goto out; - - if (ioctl (console_fd, VT_GETSTATE, &console_state) < 0) - goto out; - -out: - if (console_fd >= 0) - close (console_fd); - - return console_state.v_active; -} - -static bool -ply_window_look_up_geometry (ply_window_t *window) -{ - struct winsize window_size; - - ply_trace ("looking up window text geometry"); - - if (ioctl (window->tty_fd, TIOCGWINSZ, &window_size) < 0) - { - ply_trace ("could not read window text geometry: %m"); - window->number_of_text_columns = 80; - window->number_of_text_rows = 24; - return false; - } - - window->number_of_text_rows = window_size.ws_row; - window->number_of_text_columns = window_size.ws_col; - - ply_trace ("window is now %dx%d text cells", - window->number_of_text_columns, - window->number_of_text_rows); - - return true; -} - -static bool -ply_window_open_tty (ply_window_t *window) -{ - assert (window != NULL); - assert (window->tty_name != NULL); - assert (window->tty_fd < 0); - assert (window->tty_fd_watch == NULL); - - window->tty_fd = open (window->tty_name, O_RDWR | O_NOCTTY); - - if (window->tty_fd < 0) - return false; - - if (window->loop != NULL) - window->tty_fd_watch = ply_event_loop_watch_fd (window->loop, window->tty_fd, - PLY_EVENT_LOOP_FD_STATUS_HAS_DATA, - (ply_event_handler_t) on_key_event, - (ply_event_handler_t) on_tty_disconnected, - window); - - return true; -} - -bool -ply_window_open (ply_window_t *window) -{ - assert (window != NULL); - - if (window->tty_name == NULL) - { - char tty_name[512] = ""; - - window->vt_number = get_active_vt (); - - if (readlink ("/proc/self/fd/0", tty_name, sizeof (tty_name) - 1) < 0) - { - ply_trace ("could not read tty name of fd 0"); - return false; - } - - window->tty_name = strdup (tty_name); - } - - ply_trace ("trying to open window '%s'", window->tty_name); - - if (!ply_window_open_tty (window)) - { - ply_trace ("could not open %s : %m", window->tty_name); - return false; - } - - if (!ply_window_set_unbuffered_input (window)) - ply_trace ("window '%s' will be line buffered", window->tty_name); - - ply_window_set_mode (window, PLY_WINDOW_MODE_TEXT); - - ply_window_look_up_geometry (window); - - ply_window_look_up_color_palette (window); - ply_window_save_color_palette (window); - - ply_event_loop_watch_signal (window->loop, - SIGWINCH, - (ply_event_handler_t) - ply_window_look_up_geometry, - window); - - /* We try to open the frame buffer, but it may fail. splash plugins can check - * to see if it's open and react accordingly - */ - ply_frame_buffer_open (window->frame_buffer); - - window->is_open = true; - - return true; -} - -bool -ply_window_is_open (ply_window_t *window) -{ - return window->is_open; -} - -void -ply_window_close (ply_window_t *window) -{ - window->is_open = false; - - ply_trace ("restoring color palette"); - ply_window_restore_color_palette (window); - - if (ply_frame_buffer_device_is_open (window->frame_buffer)) - { - ply_trace ("closing frame buffer"); - ply_frame_buffer_close (window->frame_buffer); - } - - if (window->tty_fd_watch != NULL) - { - ply_trace ("stop watching tty fd"); - ply_event_loop_stop_watching_fd (window->loop, window->tty_fd_watch); - window->tty_fd_watch = NULL; - } - - if (window->loop != NULL) - { - ply_trace ("stop watching SIGWINCH signal"); - ply_event_loop_stop_watching_signal (window->loop, SIGWINCH); - } - - ply_trace ("setting buffered input"); - ply_window_set_buffered_input (window); - - close (window->tty_fd); - window->tty_fd = -1; -} - -bool -ply_window_set_mode (ply_window_t *window, - ply_window_mode_t mode) -{ - assert (window != NULL); - assert (mode == PLY_WINDOW_MODE_TEXT || mode == PLY_WINDOW_MODE_GRAPHICS); - - switch (mode) - { - case PLY_WINDOW_MODE_TEXT: - if (ioctl (window->tty_fd, KDSETMODE, KD_TEXT) < 0) - return false; - break; - - case PLY_WINDOW_MODE_GRAPHICS: - if (!ply_frame_buffer_device_is_open (window->frame_buffer) - && !ply_frame_buffer_open (window->frame_buffer)) - return false; - - if (ioctl (window->tty_fd, KDSETMODE, - window->should_force_text_mode? KD_TEXT : KD_GRAPHICS) < 0) - return false; - break; - } - ply_window_set_unbuffered_input (window); - - window->mode = mode; - return true; -} - -int -ply_window_get_tty_fd (ply_window_t *window) -{ - return window->tty_fd; -} - -int -ply_window_get_number_of_text_rows (ply_window_t *window) -{ - return window->number_of_text_rows; -} - -int -ply_window_get_number_of_text_columns (ply_window_t *window) -{ - return window->number_of_text_columns; -} - -void -ply_window_set_text_cursor_position (ply_window_t *window, - int column, - int row) -{ - char *sequence; - column = MAX(column, 0); - row = MAX(row, 0); - sequence = NULL; - asprintf (&sequence, MOVE_CURSOR_SEQUENCE, row, column); - write (window->tty_fd, sequence, strlen (sequence)); - free (sequence); -} - -void -ply_window_clear_screen (ply_window_t *window) -{ - if (ply_is_tracing ()) - return; - - if (ply_frame_buffer_device_is_open (window->frame_buffer)) - ply_frame_buffer_fill_with_color (window->frame_buffer, NULL, 0.0, 0.0, 0.0, 1.0); - - write (window->tty_fd, CLEAR_SCREEN_SEQUENCE, strlen (CLEAR_SCREEN_SEQUENCE)); - - ply_window_set_text_cursor_position (window, 0, 0); -} - -void -ply_window_clear_text_line (ply_window_t *window) -{ - write (window->tty_fd, CLEAR_LINE_SEQUENCE, strlen (CLEAR_LINE_SEQUENCE)); -} - -void -ply_window_clear_text_character (ply_window_t *window) -{ - write (window->tty_fd, BACKSPACE, strlen (BACKSPACE)); -} - -void -ply_window_set_background_color (ply_window_t *window, - ply_window_color_t color) -{ - char *sequence; - - sequence = NULL; - asprintf (&sequence, COLOR_SEQUENCE_FORMAT, - BACKGROUND_COLOR_BASE + color); - write (window->tty_fd, sequence, strlen (sequence)); - free (sequence); - - window->background_color = color; -} - -void -ply_window_set_foreground_color (ply_window_t *window, - ply_window_color_t color) -{ - char *sequence; - - sequence = NULL; - asprintf (&sequence, COLOR_SEQUENCE_FORMAT, - FOREGROUND_COLOR_BASE + color); - write (window->tty_fd, sequence, strlen (sequence)); - free (sequence); - - window->foreground_color = color; -} - -ply_window_color_t -ply_window_get_background_color (ply_window_t *window) -{ - return window->background_color; -} - -ply_window_color_t -ply_window_get_foreground_color (ply_window_t *window) -{ - return window->foreground_color; -} - -void -ply_window_draw_area (ply_window_t *window, - int x, - int y, - int width, - int height) -{ - if (window->draw_handler != NULL) - window->draw_handler (window->draw_handler_user_data, - x, y, width, height); -} - -void -ply_window_erase_area (ply_window_t *window, - int x, - int y, - int width, - int height) -{ - if (window->erase_handler != NULL) - window->erase_handler (window->erase_handler_user_data, - x, y, width, height); -} - -uint32_t -ply_window_get_color_hex_value (ply_window_t *window, - ply_window_color_t color) -{ - uint8_t red, green, blue; - uint32_t hex_value; - - assert (window != NULL); - assert (color <= PLY_WINDOW_COLOR_WHITE); - - red = (uint8_t) *(window->color_palette + 3 * color); - green = (uint8_t) *(window->color_palette + 3 * color + 1); - blue = (uint8_t) *(window->color_palette + 3 * color + 2); - - hex_value = red << 16 | green << 8 | blue; - - return hex_value; -} - -void -ply_window_set_color_hex_value (ply_window_t *window, - ply_window_color_t color, - uint32_t hex_value) -{ - uint8_t red, green, blue; - - assert (window != NULL); - assert (color <= PLY_WINDOW_COLOR_WHITE); - - red = (uint8_t) ((hex_value >> 16) & 0xff); - green = (uint8_t) ((hex_value >> 8) & 0xff); - blue = (uint8_t) (hex_value & 0xff); - - *(window->color_palette + 3 * color) = red; - *(window->color_palette + 3 * color + 1) = green; - *(window->color_palette + 3 * color + 2) = blue; - - ply_window_change_color_palette (window); -} - -void -ply_window_hide_text_cursor (ply_window_t *window) -{ - write (window->tty_fd, HIDE_CURSOR_SEQUENCE, strlen (HIDE_CURSOR_SEQUENCE)); -} - -void -ply_window_show_text_cursor (ply_window_t *window) -{ - write (window->tty_fd, SHOW_CURSOR_SEQUENCE, strlen (SHOW_CURSOR_SEQUENCE)); -} - -bool -ply_window_supports_text_color (ply_window_t *window) -{ - return window->supports_text_color; -} - -static void -ply_window_detach_from_event_loop (ply_window_t *window) -{ - assert (window != NULL); - window->loop = NULL; - window->tty_fd_watch = NULL; -} - -void -ply_window_free (ply_window_t *window) -{ - if (window == NULL) - return; - free(window->tty_name); - - if (window->loop != NULL) - ply_event_loop_stop_watching_for_exit (window->loop, - (ply_event_loop_exit_handler_t) - ply_window_detach_from_event_loop, - window); - - ply_window_close (window); - - ply_buffer_free (window->keyboard_input_buffer); - ply_buffer_free (window->line_buffer); - - ply_frame_buffer_free (window->frame_buffer); - - free (window); -} - -static ply_window_closure_t * -ply_window_closure_new(void* function, void* user_data) -{ - ply_window_closure_t *closure = calloc (1, sizeof (ply_window_closure_t)); - closure->function = function; - closure->user_data = user_data; - return closure; -} - - -static void -ply_window_closure_free(ply_window_closure_t* closure) -{ - free(closure); -} - -void -ply_window_add_keyboard_input_handler (ply_window_t *window, - ply_window_keyboard_input_handler_t input_handler, - void *user_data) -{ - assert (window != NULL); - ply_window_closure_t *closure = ply_window_closure_new(input_handler, user_data); - ply_list_append_data (window->keyboard_input_handler_list, closure); -} - - -void -ply_window_remove_keyboard_input_handler (ply_window_t *window, - ply_window_keyboard_input_handler_t input_handler) -{ - ply_list_node_t *node; - assert (window != NULL); - for (node = ply_list_get_first_node(window->keyboard_input_handler_list); - node; node = ply_list_get_next_node(window->keyboard_input_handler_list, node)) - { - ply_window_closure_t *closure = ply_list_node_get_data (node); - if ((ply_window_keyboard_input_handler_t) closure->function == input_handler) - { - ply_window_closure_free(closure); - ply_list_remove_node (window->keyboard_input_handler_list, node); - return; - } - } -} - -void -ply_window_add_backspace_handler (ply_window_t *window, - ply_window_backspace_handler_t backspace_handler, - void *user_data) -{ - assert (window != NULL); - ply_window_closure_t *closure = ply_window_closure_new(backspace_handler, user_data); - ply_list_append_data (window->backspace_handler_list, closure); -} - - -void -ply_window_remove_backspace_handler (ply_window_t *window, - ply_window_backspace_handler_t backspace_handler) -{ - ply_list_node_t *node; - assert (window != NULL); - for (node = ply_list_get_first_node(window->backspace_handler_list); - node; node = ply_list_get_next_node(window->backspace_handler_list, node)) - { - ply_window_closure_t *closure = ply_list_node_get_data (node); - if ((ply_window_backspace_handler_t) closure->function == backspace_handler) - { - ply_window_closure_free(closure); - ply_list_remove_node (window->backspace_handler_list, node); - return; - } - } -} - -void -ply_window_add_escape_handler (ply_window_t *window, - ply_window_escape_handler_t escape_handler, - void *user_data) -{ - assert (window != NULL); - ply_window_closure_t *closure = ply_window_closure_new(escape_handler, user_data); - ply_list_append_data (window->escape_handler_list, closure); -} - - -void -ply_window_remove_escape_handler (ply_window_t *window, - ply_window_escape_handler_t escape_handler) -{ - assert (window != NULL); - ply_list_node_t *node; - assert (window != NULL); - for (node = ply_list_get_first_node(window->escape_handler_list); - node; node = ply_list_get_next_node(window->escape_handler_list, node)) - { - ply_window_closure_t *closure = ply_list_node_get_data (node); - if ((ply_window_escape_handler_t) closure->function == escape_handler) - { - ply_window_closure_free(closure); - ply_list_remove_node (window->escape_handler_list, node); - return; - } - } -} - -void -ply_window_add_enter_handler (ply_window_t *window, - ply_window_enter_handler_t enter_handler, - void *user_data) -{ - assert (window != NULL); - ply_window_closure_t *closure = ply_window_closure_new(enter_handler, user_data); - ply_list_append_data (window->enter_handler_list, closure); -} - - -void -ply_window_remove_enter_handler (ply_window_t *window, - ply_window_enter_handler_t enter_handler) -{ - assert (window != NULL); - ply_list_node_t *node; - assert (window != NULL); - for (node = ply_list_get_first_node(window->enter_handler_list); - node; node = ply_list_get_next_node(window->enter_handler_list, node)) - { - ply_window_closure_t *closure = ply_list_node_get_data (node); - if ((ply_window_enter_handler_t) closure->function == enter_handler) - { - ply_window_closure_free(closure); - ply_list_remove_node (window->enter_handler_list, node); - return; - } - } -} - -void -ply_window_set_draw_handler (ply_window_t *window, - ply_window_draw_handler_t draw_handler, - void *user_data) -{ - assert (window != NULL); - - window->draw_handler = draw_handler; - window->draw_handler_user_data = user_data; -} - -void -ply_window_set_erase_handler (ply_window_t *window, - ply_window_erase_handler_t erase_handler, - void *user_data) -{ - assert (window != NULL); - - window->erase_handler = erase_handler; - window->erase_handler_user_data = user_data; -} - -void -ply_window_attach_to_event_loop (ply_window_t *window, - ply_event_loop_t *loop) -{ - assert (window != NULL); - assert (loop != NULL); - assert (window->loop == NULL); - - window->loop = loop; - - ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) - ply_window_detach_from_event_loop, - window); -} - -ply_frame_buffer_t * -ply_window_get_frame_buffer (ply_window_t *window) -{ - return window->frame_buffer; -} - -#ifdef PLY_WINDOW_ENABLE_TEST - -#include - -#include "ply-event-loop.h" -#include "ply-window.h" - -static void -on_timeout (ply_window_t *window, - ply_event_loop_t *loop) -{ - ply_event_loop_exit (loop, 0); -} - -static void -on_keypress (ply_window_t *window, - const char *keyboard_input) -{ - printf ("key '%c' (0x%x) was pressed\n", - keyboard_input[0], (unsigned int) keyboard_input[0]); -} - -int -main (int argc, - char **argv) -{ - ply_event_loop_t *loop; - ply_window_t *window; - int exit_code; - const char *tty_name; - - exit_code = 0; - - loop = ply_event_loop_new (); - - if (argc > 1) - tty_name = argv[1]; - else - tty_name = "/dev/tty1"; - - window = ply_window_new (tty_name); - ply_window_attach_to_event_loop (window, loop); - ply_window_add_keyboard_input_handler (window, - (ply_window_keyboard_input_handler_t) - on_keypress, window); - - if (!ply_window_open (window)) - { - ply_save_errno (); - perror ("could not open window"); - ply_restore_errno (); - return errno; - } - - if (!ply_window_set_mode (window, PLY_WINDOW_MODE_TEXT)) - { - ply_save_errno (); - perror ("could not set window for graphics mode"); - ply_restore_errno (); - } - - ply_event_loop_watch_for_timeout (loop, - 15.0, - (ply_event_loop_timeout_handler_t) - on_timeout, - window); - exit_code = ply_event_loop_run (loop); - - ply_window_close (window); - ply_window_free (window); - - return exit_code; -} - -#endif /* PLY_WINDOW_ENABLE_TEST */ -/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/libplybootsplash/ply-window.h b/src/libplybootsplash/ply-window.h deleted file mode 100644 index 9b8fee79..00000000 --- a/src/libplybootsplash/ply-window.h +++ /dev/null @@ -1,165 +0,0 @@ -/* ply-window.h - APIs for putting up a splash screen - * - * Copyright (C) 2008 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written By: Ray Strode - */ -#ifndef PLY_WINDOW_H -#define PLY_WINDOW_H - -#include -#include -#include - -#include "ply-buffer.h" -#include "ply-event-loop.h" -#include "ply-frame-buffer.h" - -typedef struct _ply_window ply_window_t; - -typedef void (* ply_window_keyboard_input_handler_t) (void *user_data, - const char *keyboard_input, - size_t character_size); - -typedef void (* ply_window_backspace_handler_t) (void *user_data); -typedef void (* ply_window_escape_handler_t) (void *user_data); -typedef void (* ply_window_enter_handler_t) (void *user_data, - const char *line); - -typedef void (* ply_window_draw_handler_t) (void *user_data, - int x, - int y, - int width, - int height); -typedef void (* ply_window_erase_handler_t) (void *user_data, - int x, - int y, - int width, - int height); - -typedef enum -{ - PLY_WINDOW_MODE_TEXT, - PLY_WINDOW_MODE_GRAPHICS -} ply_window_mode_t; - -typedef enum -{ - PLY_WINDOW_COLOR_BLACK = 0, - PLY_WINDOW_COLOR_RED, - PLY_WINDOW_COLOR_GREEN, - PLY_WINDOW_COLOR_BROWN, - PLY_WINDOW_COLOR_BLUE, - PLY_WINDOW_COLOR_MAGENTA, - PLY_WINDOW_COLOR_CYAN, - PLY_WINDOW_COLOR_WHITE, - PLY_WINDOW_COLOR_DEFAULT = PLY_WINDOW_COLOR_WHITE + 2 -} ply_window_color_t; - -#ifndef PLY_HIDE_FUNCTION_DECLARATIONS -ply_window_t *ply_window_new (const char *name); -void ply_window_free (ply_window_t *window); - -void ply_window_add_keyboard_input_handler (ply_window_t *window, - ply_window_keyboard_input_handler_t input_handler, - void *user_data); -void ply_window_remove_keyboard_input_handler (ply_window_t *window, - ply_window_keyboard_input_handler_t input_handler); -void ply_window_add_backspace_handler (ply_window_t *window, - ply_window_backspace_handler_t backspace_handler, - void *user_data); -void ply_window_remove_backspace_handler (ply_window_t *window, - ply_window_backspace_handler_t backspace_handler); -void ply_window_add_escape_handler (ply_window_t *window, - ply_window_escape_handler_t escape_handler, - void *user_data); -void ply_window_remove_escape_handler (ply_window_t *window, - ply_window_escape_handler_t escape_handler); -void ply_window_add_enter_handler (ply_window_t *window, - ply_window_enter_handler_t enter_handler, - void *user_data); -void ply_window_remove_enter_handler (ply_window_t *window, - ply_window_enter_handler_t enter_handler); -void ply_window_add_draw_handler (ply_window_t *window, - ply_window_draw_handler_t draw_handler, - void *user_data); -void ply_window_remove_draw_handler (ply_window_t *window, - ply_window_draw_handler_t draw_handler); -void ply_window_add_erase_handler (ply_window_t *window, - ply_window_erase_handler_t erase_handler, - void *user_data); -void ply_window_remove_erase_handler (ply_window_t *window, - ply_window_erase_handler_t erase_handler); - -bool ply_window_open (ply_window_t *window); -bool ply_window_is_open (ply_window_t *window); -void ply_window_close (ply_window_t *window); -bool ply_window_set_mode (ply_window_t *window, - ply_window_mode_t mode); -int ply_window_get_tty_fd (ply_window_t *window); -int ply_window_get_number_of_text_rows (ply_window_t *window); -int ply_window_get_number_of_text_columns (ply_window_t *window); -void ply_window_set_text_cursor_position (ply_window_t *window, - int column, - int row); -void ply_window_hide_text_cursor (ply_window_t *window); -void ply_window_show_text_cursor (ply_window_t *window); -void ply_window_clear_screen (ply_window_t *window); -void ply_window_clear_text_line (ply_window_t *window); -void ply_window_clear_text_character (ply_window_t *window); -bool ply_window_supports_text_color (ply_window_t *window); -void ply_window_set_background_color (ply_window_t *window, - ply_window_color_t color); -void ply_window_set_foreground_color (ply_window_t *window, - ply_window_color_t color); -ply_window_color_t ply_window_get_background_color (ply_window_t *window); -ply_window_color_t ply_window_get_foreground_color (ply_window_t *window); - -void ply_window_draw_area (ply_window_t *window, - int x, - int y, - int width, - int height); - -void ply_window_erase_area (ply_window_t *window, - int x, - int y, - int width, - int height); - -uint32_t ply_window_get_color_hex_value (ply_window_t *window, - ply_window_color_t color); -void ply_window_set_color_hex_value (ply_window_t *window, - ply_window_color_t color, - uint32_t hex_value); -void ply_window_reset_colors (ply_window_t *window); - -void ply_window_set_draw_handler (ply_window_t *window, - ply_window_draw_handler_t draw_handler, - void *user_data); -void ply_window_set_erase_handler (ply_window_t *window, - ply_window_erase_handler_t erase_handler, - void *user_data); -void ply_window_attach_to_event_loop (ply_window_t *window, - ply_event_loop_t *loop); -ply_frame_buffer_t *ply_window_get_frame_buffer (ply_window_t *window); - -#endif - -#endif /* PLY_WINDOW_H */ -/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index e0c4242d..bd4e4760 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -9,7 +9,6 @@ TESTS = if ENABLE_TESTS include $(srcdir)/ply-boot-server-test.am include $(srcdir)/ply-boot-splash-test.am -include $(srcdir)/ply-window-test.am endif noinst_PROGRAMS = $(TESTS) diff --git a/src/tests/ply-window-test.am b/src/tests/ply-window-test.am deleted file mode 100644 index 2a4090f5..00000000 --- a/src/tests/ply-window-test.am +++ /dev/null @@ -1,8 +0,0 @@ -TESTS += ply-window-test - -ply_window_test_CFLAGS = $(PLYMOUTH_CFLAGS) -DPLY_WINDOW_ENABLE_TEST -ply_window_test_LDADD = $(PLYMOUTH_LIBS) ../libply/libply.la - -ply_window_test_SOURCES = \ - $(srcdir)/../libplybootsplash/ply-window.h \ - $(srcdir)/../libplybootsplash/ply-window.c From 069839a58b971bce8e3904b1c1237bf78e37318f Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 21 Sep 2009 13:49:43 -0400 Subject: [PATCH 35/43] [utils] Add ply_round_to_multiple macro We'll need something like this for rowstride calculation --- src/libply/ply-utils.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libply/ply-utils.h b/src/libply/ply-utils.h index 592a8e4e..5e41f841 100644 --- a/src/libply/ply-utils.h +++ b/src/libply/ply-utils.h @@ -46,6 +46,9 @@ typedef void (* ply_module_function_t) (void); typedef intptr_t ply_daemon_handle_t; #ifndef PLY_HIDE_FUNCTION_DECLARATIONS + +#define ply_round_to_multiple(n, m) (((n) + (((m) - 1))) & ~((m) - 1)) + bool ply_open_unidirectional_pipe (int *sender_fd, int *receiver_fd); int ply_connect_to_unix_socket (const char *path, From 920051bc55de0a70439afa70e8a7d030caf4b387 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 16 Sep 2009 18:27:53 -0400 Subject: [PATCH 36/43] [drm] Add start of a drm plugin This commit adds most of the non-driver specific bits necessary for backing a renderer plugin. Subsequent commits will add the driver specific bits. --- configure.ac | 5 + scripts/plymouth-populate-initrd.in | 1 + src/libplybootsplash/ply-renderer.c | 1 + src/plugins/renderers/Makefile.am | 2 +- src/plugins/renderers/drm/Makefile.am | 21 + src/plugins/renderers/drm/plugin.c | 1049 +++++++++++++++++ .../renderers/drm/ply-renderer-driver.h | 67 ++ 7 files changed, 1145 insertions(+), 1 deletion(-) create mode 100644 src/plugins/renderers/drm/Makefile.am create mode 100644 src/plugins/renderers/drm/plugin.c create mode 100644 src/plugins/renderers/drm/ply-renderer-driver.h diff --git a/configure.ac b/configure.ac index df076e2c..0758dcad 100644 --- a/configure.ac +++ b/configure.ac @@ -56,6 +56,10 @@ PKG_CHECK_MODULES(GTK, [gtk+-2.0 >= 2.12.0 ]) AC_SUBST(GTK_CFLAGS) AC_SUBST(GTK_LIBS) +PKG_CHECK_MODULES(DRM, [libdrm]) +AC_SUBST(DRM_CFLAGS) +AC_SUBST(DRM_LIBS) + AC_ARG_ENABLE(tracing, AS_HELP_STRING([--enable-tracing],[enable verbose tracing code]),enable_tracing=$enableval,enable_tracing=yes) if test x$enable_tracing = xyes; then @@ -211,6 +215,7 @@ AC_OUTPUT([Makefile src/plugins/Makefile src/plugins/renderers/Makefile src/plugins/renderers/frame-buffer/Makefile + src/plugins/renderers/drm/Makefile src/plugins/splash/Makefile src/plugins/splash/throbgress/Makefile src/plugins/splash/fade-throbber/Makefile diff --git a/scripts/plymouth-populate-initrd.in b/scripts/plymouth-populate-initrd.in index 42b119c3..14eb6fc7 100755 --- a/scripts/plymouth-populate-initrd.in +++ b/scripts/plymouth-populate-initrd.in @@ -93,6 +93,7 @@ fi inst ${PLYMOUTH_PLUGIN_PATH}/${PLYMOUTH_MODULE_NAME}.so $INITRDDIR +inst ${PLYMOUTH_PLUGIN_PATH}/renderers/drm.so $INITRDDIR inst ${PLYMOUTH_PLUGIN_PATH}/renderers/frame-buffer.so $INITRDDIR if [ -d ${DATADIR}/plymouth/themes/${PLYMOUTH_THEME_NAME} ]; then diff --git a/src/libplybootsplash/ply-renderer.c b/src/libplybootsplash/ply-renderer.c index 9320030f..5410feb8 100644 --- a/src/libplybootsplash/ply-renderer.c +++ b/src/libplybootsplash/ply-renderer.c @@ -220,6 +220,7 @@ ply_renderer_open (ply_renderer_t *renderer) */ const char *known_plugins[] = { + PLYMOUTH_PLUGIN_PATH "renderers/drm.so", PLYMOUTH_PLUGIN_PATH "renderers/frame-buffer.so", NULL }; diff --git a/src/plugins/renderers/Makefile.am b/src/plugins/renderers/Makefile.am index 2a9e8a0c..2fadbf40 100644 --- a/src/plugins/renderers/Makefile.am +++ b/src/plugins/renderers/Makefile.am @@ -1,2 +1,2 @@ -SUBDIRS = frame-buffer +SUBDIRS = frame-buffer drm MAINTAINERCLEANFILES = Makefile.in diff --git a/src/plugins/renderers/drm/Makefile.am b/src/plugins/renderers/drm/Makefile.am new file mode 100644 index 00000000..328b881a --- /dev/null +++ b/src/plugins/renderers/drm/Makefile.am @@ -0,0 +1,21 @@ +INCLUDES = -I$(top_srcdir) \ + -I$(srcdir)/../../../libply \ + -I$(srcdir)/../../../libplybootsplash \ + -I$(srcdir)/../../.. \ + -I$(srcdir)/../.. \ + -I$(srcdir)/.. \ + -I$(srcdir) + +plugindir = $(libdir)/plymouth/renderers +plugin_LTLIBRARIES = drm.la + +drm_la_CFLAGS = $(PLYMOUTH_CFLAGS) $(DRM_CFLAGS) + +drm_la_LDFLAGS = -module -avoid-version -export-dynamic +drm_la_LIBADD = $(PLYMOUTH_LIBS) $(DRM_LIBS) \ + ../../../libply/libply.la \ + ../../../libplybootsplash/libplybootsplash.la +drm_la_SOURCES = $(srcdir)/plugin.c \ + $(srcdir)/ply-renderer-driver.h + +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c new file mode 100644 index 00000000..67a6bea2 --- /dev/null +++ b/src/plugins/renderers/drm/plugin.c @@ -0,0 +1,1049 @@ +/* plugin.c - drm backend renderer plugin + * + * Copyright (C) 2006-2009 Red Hat, Inc. + * 2008 Charlie Brej + * + * 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: Charlie Brej + * Kristian Høgsberg + * Peter Jones + * Ray Strode + */ +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ply-buffer.h" +#include "ply-event-loop.h" +#include "ply-list.h" +#include "ply-logger.h" +#include "ply-rectangle.h" +#include "ply-region.h" +#include "ply-terminal.h" + +#include "ply-renderer.h" +#include "ply-renderer-plugin.h" +#include "ply-renderer-driver.h" + +#define BYTES_PER_PIXEL (4) + +struct _ply_renderer_head +{ + ply_renderer_backend_t *backend; + ply_pixel_buffer_t *pixel_buffer; + ply_rectangle_t area; + + unsigned long row_stride; + + drmModeConnector *connector; + drmModeModeInfo *mode; + + uint32_t controller_id; + uint32_t encoder_id; + uint32_t console_buffer_id; + uint32_t scan_out_buffer_id; +}; + +struct _ply_renderer_input_source +{ + ply_fd_watch_t *terminal_input_watch; + + ply_buffer_t *key_buffer; + + ply_renderer_input_source_handler_t handler; + void *user_data; +}; + +struct _ply_renderer_backend +{ + ply_event_loop_t *loop; + ply_console_t *console; + ply_terminal_t *terminal; + + ply_renderer_driver_interface_t *driver_interface; + ply_renderer_driver_t *driver; + + int device_fd; + char *device_name; + drmModeRes *resources; + + ply_renderer_input_source_t input_source; + ply_list_t *heads; + + int32_t dither_red; + int32_t dither_green; + int32_t dither_blue; +}; + +ply_renderer_plugin_interface_t *ply_renderer_backend_get_interface (void); +static void ply_renderer_head_redraw (ply_renderer_backend_t *backend, + ply_renderer_head_t *head); + +static ply_renderer_head_t * +ply_renderer_head_new (ply_renderer_backend_t *backend, + drmModeConnector *connector, + uint32_t encoder_id, + uint32_t controller_id, + uint32_t console_buffer_id, + drmModeModeInfo *mode) +{ + ply_renderer_head_t *head; + + head = calloc (1, sizeof (ply_renderer_head_t)); + + head->backend = backend; + head->connector = connector; + head->encoder_id = encoder_id; + head->controller_id = controller_id; + head->console_buffer_id = console_buffer_id; + head->mode = mode; + + head->area.x = 0; + head->area.y = 0; + head->area.width = mode->hdisplay; + head->area.height = mode->vdisplay; + + head->pixel_buffer = ply_pixel_buffer_new (head->area.width, head->area.height); + + ply_pixel_buffer_fill_with_color (head->pixel_buffer, NULL, + 0.0, 0.0, 0.0, 1.0); + + return head; +} + +static void +ply_renderer_head_free (ply_renderer_head_t *head) +{ + ply_pixel_buffer_free (head->pixel_buffer); + drmModeFreeConnector (head->connector); + free (head); +} + +static bool +ply_renderer_head_set_scan_out_buffer (ply_renderer_backend_t *backend, + ply_renderer_head_t *head, + uint32_t buffer_id) +{ + + /* Tell the controller to use the allocated scan out buffer + */ + if (drmModeSetCrtc (backend->device_fd, head->controller_id, buffer_id, + 0, 0, &head->connector->connector_id, 1, head->mode) < 0) + return false; + + return true; +} + +static bool +ply_renderer_head_map (ply_renderer_backend_t *backend, + ply_renderer_head_t *head) +{ + assert (backend != NULL); + assert (backend->device_fd >= 0); + assert (backend->driver_interface != NULL); + assert (backend->driver != NULL); + + assert (head != NULL); + + head->scan_out_buffer_id = + backend->driver_interface->create_buffer (backend->driver, + head->area.width, head->area.height, + &head->row_stride); + + if (head->scan_out_buffer_id == 0) + return false; + + 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); + head->scan_out_buffer_id = 0; + return false; + } + + /* FIXME: Maybe we should blit the fbcon contents instead of the (blank) + * shadow buffer? + */ + ply_renderer_head_redraw (backend, head); + + if (!ply_renderer_head_set_scan_out_buffer (backend, head, + head->scan_out_buffer_id)) + { + backend->driver_interface->destroy_buffer (backend->driver, + head->scan_out_buffer_id); + head->scan_out_buffer_id = 0; + return false; + } + + return true; +} + +static void +ply_renderer_head_unmap (ply_renderer_backend_t *backend, + ply_renderer_head_t *head) +{ + backend->driver_interface->unmap_buffer (backend->driver, + head->scan_out_buffer_id); + + backend->driver_interface->destroy_buffer (backend->driver, + head->scan_out_buffer_id); + head->scan_out_buffer_id = 0; +} + +static void +flush_area (const char *src, + unsigned long src_row_stride, + char *dst, + unsigned long dst_row_stride, + ply_rectangle_t *area_to_flush) +{ + unsigned long x1, y1, x2, y2, y; + + x1 = area_to_flush->x; + y1 = area_to_flush->y; + x2 = x1 + area_to_flush->width; + y2 = y1 + area_to_flush->height; + + if (area_to_flush->width * 4 == src_row_stride && + area_to_flush->width * 4 == dst_row_stride) + { + memcpy (dst, src, area_to_flush->width * area_to_flush->height * 4); + return; + } + + for (y = y1; y < y2; y++) + { + memcpy (dst, src, area_to_flush->width * 4); + dst += dst_row_stride; + src += src_row_stride; + } +} + +static void +ply_renderer_head_flush_area (ply_renderer_head_t *head, + ply_rectangle_t *area_to_flush, + char *map_address) +{ + uint32_t *shadow_buffer; + char *dst, *src; + + shadow_buffer = ply_pixel_buffer_get_argb32_data (head->pixel_buffer); + + dst = &map_address[area_to_flush->y * head->row_stride + area_to_flush->x * BYTES_PER_PIXEL]; + src = (char *) &shadow_buffer[area_to_flush->y * head->area.width + area_to_flush->x]; + + flush_area (src, head->area.width * 4, dst, head->row_stride, area_to_flush); +} + +static void +free_heads (ply_renderer_backend_t *backend) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (backend->heads); + while (node != NULL) + { + ply_list_node_t *next_node; + ply_renderer_head_t *head; + + head = (ply_renderer_head_t *) ply_list_node_get_data (node); + next_node = ply_list_get_next_node (backend->heads, node); + + ply_renderer_head_free (head); + ply_list_remove_node (backend->heads, node); + + node = next_node; + } +} + +static ply_renderer_backend_t * +create_backend (const char *device_name, + ply_terminal_t *terminal, + ply_console_t *console) +{ + ply_renderer_backend_t *backend; + + backend = calloc (1, sizeof (ply_renderer_backend_t)); + + if (device_name != NULL) + backend->device_name = strdup (device_name); + else + backend->device_name = strdup ("/dev/dri/card0"); + + backend->device_fd = -1; + + backend->loop = ply_event_loop_get_default (); + backend->heads = ply_list_new (); + backend->input_source.key_buffer = ply_buffer_new (); + backend->console = console; + backend->terminal = terminal; + + return backend; +} + +static void +destroy_backend (ply_renderer_backend_t *backend) +{ + free_heads (backend); + ply_list_free (backend->heads); + + free (backend->device_name); + + free (backend); +} + +static char * +find_driver_for_device (const char *device_name) +{ + char *driver; + int major_number, minor_number; + struct stat file_attributes; + char *device_path; + char device_link_path[PATH_MAX + 1] = ""; + + if (stat (device_name, &file_attributes) < 0) + return NULL; + + if (!S_ISCHR (file_attributes.st_mode)) + return NULL; + + major_number = major (file_attributes.st_rdev); + minor_number = minor (file_attributes.st_rdev); + + asprintf (&device_path, "/sys/dev/char/%d:%d/device/driver", + major_number, minor_number); + + if (readlink (device_path, device_link_path, sizeof (device_link_path) - 1) < 0) + { + free (device_path); + return NULL; + } + free (device_path); + + driver = strrchr (device_link_path, '/'); + + if (driver == NULL) + return NULL; + + return strdup (driver + strlen ("/")); +} + +static void +on_active_vt_changed (ply_renderer_backend_t *backend) +{ + ply_list_node_t *node; + + if (ply_console_get_active_vt (backend->console) != + ply_terminal_get_vt_number (backend->terminal)) + return; + + node = ply_list_get_first_node (backend->heads); + while (node != NULL) + { + ply_list_node_t *next_node; + ply_renderer_head_t *head; + + head = (ply_renderer_head_t *) ply_list_node_get_data (node); + next_node = ply_list_get_next_node (backend->heads, node); + + if (head->scan_out_buffer_id != 0) + ply_renderer_head_set_scan_out_buffer (backend, head, + head->scan_out_buffer_id); + + node = next_node; + } +} + +static bool +load_driver (ply_renderer_backend_t *backend) +{ + char *driver_name; + int device_fd; + + driver_name = find_driver_for_device (backend->device_name); + device_fd = drmOpen (driver_name, NULL); + + if (device_fd < 0) + { + free (driver_name); + return false; + } + +#if 0 + Something like... + if (strcmp (driver_name, "i915") == 0) + { + backend->driver_interface = ply_renderer_i915_driver_get_interface (); + } +#endif + free (driver_name); + + 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; + + return true; +} + +static void +unload_driver (ply_renderer_backend_t *backend) +{ + if (backend->driver == NULL) + return; + + assert (backend->driver_interface != NULL); + + backend->driver_interface->destroy_driver (backend->driver); + backend->driver = NULL; + + backend->driver_interface = NULL; + + if (backend->device_fd >= 0) + { + drmClose (backend->device_fd); + backend->device_fd = -1; + } +} + +static bool +open_device (ply_renderer_backend_t *backend) +{ + assert (backend != NULL); + assert (backend->device_name != NULL); + + if (!load_driver (backend)) + return false; + + ply_console_watch_for_active_vt_change (backend->console, + (ply_console_active_vt_changed_handler_t) + on_active_vt_changed, + backend); + + return true; +} + +static void +close_device (ply_renderer_backend_t *backend) +{ + ply_terminal_close (backend->terminal); + free_heads (backend); + + ply_console_stop_watching_for_active_vt_change (backend->console, + (ply_console_active_vt_changed_handler_t) + on_active_vt_changed, + backend); + + unload_driver (backend); +} + +static drmModeModeInfo * +get_active_mode_for_connector (ply_renderer_backend_t *backend, + drmModeConnector *connector) +{ + return &connector->modes[0]; +} + +static bool +controller_is_available (ply_renderer_backend_t *backend, + uint32_t controller_id) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (backend->heads); + while (node != NULL) + { + ply_list_node_t *next_node; + ply_renderer_head_t *head; + + head = (ply_renderer_head_t *) ply_list_node_get_data (node); + next_node = ply_list_get_next_node (backend->heads, node); + + if (head->controller_id == controller_id) + return false; + + node = next_node; + } + + return true; +} + +static uint32_t +find_controller_for_encoder (ply_renderer_backend_t *backend, + drmModeEncoder *encoder) +{ + int i; + uint32_t possible_crtcs; + + /* Monitor is already lit. We'll use the same controller. + */ + if (encoder->crtc_id != 0) + return encoder->crtc_id; + + /* Monitor cable is plugged in, but the monitor isn't lit + * yet. Let's pick an available controller and light it up + * ourselves. + */ + for (i = 0, + possible_crtcs = encoder->possible_crtcs; + possible_crtcs != 0x0; + i++, possible_crtcs >>= 1) + { + /* controller isn't compatible with encoder + */ + if ((possible_crtcs & 0x1) == 0) + continue; + + /* controller is already being used + */ + if (!controller_is_available (backend, backend->resources->crtcs[i])) + continue; + + assert (i < backend->resources->count_crtcs); + return backend->resources->crtcs[i]; + } + + return 0; +} + +static bool +encoder_is_available (ply_renderer_backend_t *backend, + uint32_t encoder_id) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (backend->heads); + while (node != NULL) + { + ply_list_node_t *next_node; + ply_renderer_head_t *head; + + head = (ply_renderer_head_t *) ply_list_node_get_data (node); + next_node = ply_list_get_next_node (backend->heads, node); + + if (head->encoder_id == encoder_id) + return false; + + node = next_node; + } + + return true; +} + +static drmModeEncoder * +find_unused_encoder_for_connector (ply_renderer_backend_t *backend, + drmModeConnector *connector) +{ + int i; + drmModeEncoder *encoder; + + for (i = 0; i < connector->count_encoders; i++) + { + encoder = drmModeGetEncoder (backend->device_fd, + connector->encoders[i]); + + if (encoder == NULL) + continue; + + if (encoder_is_available (backend, encoder->encoder_id)) + return encoder; + + drmModeFreeEncoder (encoder); + } + + return NULL; +} + +static drmModeEncoder * +find_encoder_for_connector (ply_renderer_backend_t *backend, + drmModeConnector *connector) +{ + int i; + drmModeEncoder *encoder; + + assert (backend != NULL); + + for (i = 0; i < connector->count_encoders; i++) + { + encoder = drmModeGetEncoder (backend->device_fd, + connector->encoders[i]); + + if (encoder == NULL) + continue; + + if (encoder->encoder_id == connector->encoder_id) + return encoder; + + drmModeFreeEncoder (encoder); + } + + /* No encoder yet, pick one + */ + return find_unused_encoder_for_connector (backend, connector); +} + +static uint32_t +get_console_buffer_id (ply_renderer_backend_t *backend, + uint32_t controller_id) +{ + drmModeCrtc *controller; + uint32_t console_buffer_id; + + console_buffer_id = 0; + controller = drmModeGetCrtc (backend->device_fd, controller_id); + + if (controller == NULL) + return 0; + + console_buffer_id = controller->buffer_id; + + drmModeFreeCrtc (controller); + + return console_buffer_id; +} + +static bool +create_heads_for_active_connectors (ply_renderer_backend_t *backend) +{ + int i; + drmModeConnector *connector; + + for (i = 0; i < backend->resources->count_connectors; i++) + { + ply_renderer_head_t *head; + drmModeEncoder *encoder; + uint32_t controller_id; + uint32_t encoder_id; + uint32_t console_buffer_id; + drmModeModeInfo *mode; + + connector = drmModeGetConnector (backend->device_fd, + backend->resources->connectors[i]); + + if (connector == NULL) + continue; + + if (connector->connection != DRM_MODE_CONNECTED) + { + drmModeFreeConnector (connector); + continue; + } + + if (connector->count_modes <= 0) + { + drmModeFreeConnector (connector); + continue; + } + + encoder = find_encoder_for_connector (backend, connector); + + if (encoder == NULL) + { + drmModeFreeConnector (connector); + continue; + } + + encoder_id = encoder->encoder_id; + controller_id = find_controller_for_encoder (backend, encoder); + drmModeFreeEncoder (encoder); + + if (controller_id == 0) + { + drmModeFreeConnector (connector); + continue; + } + + mode = get_active_mode_for_connector (backend, connector); + + console_buffer_id = get_console_buffer_id (backend, controller_id); + + head = ply_renderer_head_new (backend, connector, encoder_id, + controller_id, console_buffer_id, + mode); + + ply_list_append_data (backend->heads, head); + } + + return ply_list_get_length (backend->heads) > 0; +} + +static bool +query_device (ply_renderer_backend_t *backend) +{ + assert (backend != NULL); + assert (backend->device_fd >= 0); + + backend->resources = drmModeGetResources (backend->device_fd); + + if (backend->resources == NULL) + { + ply_trace ("Could not get card resources"); + return false; + } + + if (!create_heads_for_active_connectors (backend)) + { + ply_trace ("Could not initialize heads"); + return false; + } + + return true; +} + +static bool +map_to_device (ply_renderer_backend_t *backend) +{ + ply_list_node_t *node; + bool head_mapped; + + head_mapped = false; + node = ply_list_get_first_node (backend->heads); + while (node != NULL) + { + ply_list_node_t *next_node; + ply_renderer_head_t *head; + + head = (ply_renderer_head_t *) ply_list_node_get_data (node); + next_node = ply_list_get_next_node (backend->heads, node); + + if (ply_renderer_head_map (backend, head)) + head_mapped = true; + + node = next_node; + } + + 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)) + 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; + } + 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); + } + + 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_renderer_head_set_scan_out_buffer (backend, + head, 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) + { + ply_list_node_t *next_node; + ply_renderer_head_t *head; + + head = (ply_renderer_head_t *) ply_list_node_get_data (node); + next_node = ply_list_get_next_node (backend->heads, node); + + ply_renderer_head_set_scan_out_buffer_to_console (backend, head, + should_set_to_black); + + ply_renderer_head_unmap (backend, head); + + node = next_node; + } +} + +static void +reset_scan_out_buffer_if_needed (ply_renderer_backend_t *backend, + ply_renderer_head_t *head) +{ + drmModeCrtc *controller; + + if (ply_console_get_active_vt (backend->console) != + ply_terminal_get_vt_number (backend->terminal)) + return; + + controller = drmModeGetCrtc (backend->device_fd, head->controller_id); + + if (controller == NULL) + return; + + if (controller->buffer_id != head->scan_out_buffer_id) + { + ply_trace ("Something stole the monitor"); + ply_renderer_head_set_scan_out_buffer (backend, head, + head->scan_out_buffer_id); + } + + drmModeFreeCrtc (controller); +} + +static void +flush_head (ply_renderer_backend_t *backend, + ply_renderer_head_t *head) +{ + ply_region_t *updated_region; + ply_list_t *areas_to_flush; + ply_list_node_t *node; + ply_pixel_buffer_t *pixel_buffer; + char *map_address; + + assert (backend != NULL); + + ply_console_set_mode (backend->console, PLY_CONSOLE_MODE_GRAPHICS); + pixel_buffer = head->pixel_buffer; + updated_region = ply_pixel_buffer_get_updated_areas (pixel_buffer); + areas_to_flush = ply_region_get_rectangle_list (updated_region); + + map_address = + backend->driver_interface->begin_flush (backend->driver, + head->scan_out_buffer_id); + + node = ply_list_get_first_node (areas_to_flush); + while (node != NULL) + { + ply_list_node_t *next_node; + ply_rectangle_t *area_to_flush; + + area_to_flush = (ply_rectangle_t *) ply_list_node_get_data (node); + + next_node = ply_list_get_next_node (areas_to_flush, node); + + reset_scan_out_buffer_if_needed (backend, head); + ply_renderer_head_flush_area (head, area_to_flush, map_address); + + node = next_node; + } + + backend->driver_interface->end_flush (backend->driver, + head->scan_out_buffer_id); + + ply_region_clear (updated_region); +} + +static void +ply_renderer_head_redraw (ply_renderer_backend_t *backend, + ply_renderer_head_t *head) +{ + ply_region_t *region; + + region = ply_pixel_buffer_get_updated_areas (head->pixel_buffer); + + ply_region_add_rectangle (region, &head->area); + + flush_head (backend, head); +} + +static ply_list_t * +get_heads (ply_renderer_backend_t *backend) +{ + return backend->heads; +} + +static ply_pixel_buffer_t * +get_buffer_for_head (ply_renderer_backend_t *backend, + ply_renderer_head_t *head) +{ + + if (head->backend != backend) + return NULL; + + return head->pixel_buffer; +} + +static bool +has_input_source (ply_renderer_backend_t *backend, + ply_renderer_input_source_t *input_source) +{ + return input_source == &backend->input_source; +} + +static ply_renderer_input_source_t * +get_input_source (ply_renderer_backend_t *backend) +{ + return &backend->input_source; +} + +static void +on_key_event (ply_renderer_input_source_t *input_source, + int terminal_fd) +{ + ply_buffer_append_from_fd (input_source->key_buffer, + terminal_fd); + + if (input_source->handler != NULL) + input_source->handler (input_source->user_data, input_source->key_buffer, input_source); + +} + +static bool +open_input_source (ply_renderer_backend_t *backend, + ply_renderer_input_source_t *input_source) +{ + int terminal_fd; + + assert (backend != NULL); + assert (has_input_source (backend, input_source)); + + terminal_fd = ply_terminal_get_fd (backend->terminal); + + input_source->terminal_input_watch = ply_event_loop_watch_fd (backend->loop, terminal_fd, PLY_EVENT_LOOP_FD_STATUS_HAS_DATA, + (ply_event_handler_t) on_key_event, + NULL, input_source); + return true; +} + +static void +set_handler_for_input_source (ply_renderer_backend_t *backend, + ply_renderer_input_source_t *input_source, + ply_renderer_input_source_handler_t handler, + void *user_data) +{ + assert (backend != NULL); + assert (has_input_source (backend, input_source)); + + input_source->handler = handler; + input_source->user_data = user_data; +} + +static void +close_input_source (ply_renderer_backend_t *backend, + ply_renderer_input_source_t *input_source) +{ + assert (backend != NULL); + assert (has_input_source (backend, input_source)); + + ply_event_loop_stop_watching_fd (backend->loop, input_source->terminal_input_watch); + input_source->terminal_input_watch = NULL; +} + +ply_renderer_plugin_interface_t * +ply_renderer_backend_get_interface (void) +{ + static ply_renderer_plugin_interface_t plugin_interface = + { + .create_backend = create_backend, + .destroy_backend = destroy_backend, + .open_device = open_device, + .close_device = close_device, + .query_device = query_device, + .map_to_device = map_to_device, + .unmap_from_device = unmap_from_device, + .flush_head = flush_head, + .get_heads = get_heads, + .get_buffer_for_head = get_buffer_for_head, + .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 + }; + + return &plugin_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-driver.h b/src/plugins/renderers/drm/ply-renderer-driver.h new file mode 100644 index 00000000..a0d6044a --- /dev/null +++ b/src/plugins/renderers/drm/ply-renderer-driver.h @@ -0,0 +1,67 @@ +/* ply-renderer-driver.h + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode + */ +#ifndef PLY_RENDERER_DRIVER_H +#define PLY_RENDERER_DRIVER_H + +#include +#include + +#include "ply-list.h" +#include "ply-rectangle.h" +#include "ply-utils.h" + +typedef struct _ply_renderer_driver ply_renderer_driver_t; + +typedef struct +{ + ply_renderer_driver_t * (* create_driver) (int device_fd); + + void (* destroy_driver) (ply_renderer_driver_t *driver); + + uint32_t (* create_buffer) (ply_renderer_driver_t *driver, + unsigned long width, + unsigned long height, + unsigned long *row_stride); + bool (* fetch_buffer) (ply_renderer_driver_t *driver, + uint32_t buffer_id, + unsigned long *width, + unsigned long *height, + unsigned long *row_stride); + + bool (* map_buffer) (ply_renderer_driver_t *driver, + uint32_t buffer_id); + + void (* unmap_buffer) (ply_renderer_driver_t *driver, + uint32_t buffer_id); + + char * (* begin_flush) (ply_renderer_driver_t *driver, + uint32_t buffer_id); + void (* end_flush) (ply_renderer_driver_t *driver, + uint32_t buffer_id); + + void (* destroy_buffer) (ply_renderer_driver_t *driver, + uint32_t buffer_id); + +} ply_renderer_driver_interface_t; + +#endif /* PLY_RENDERER_DRIVER_H */ +/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ From f2048af97dcc862dbbb587a0cc2546ddbdbd2b0c Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 21 Sep 2009 18:03:52 -0400 Subject: [PATCH 37/43] [drm] Add initial support for intel cards --- configure.ac | 2 +- src/plugins/renderers/drm/Makefile.am | 4 +- src/plugins/renderers/drm/plugin.c | 4 +- .../renderers/drm/ply-renderer-i915-driver.c | 360 ++++++++++++++++++ .../renderers/drm/ply-renderer-i915-driver.h | 32 ++ 5 files changed, 397 insertions(+), 5 deletions(-) create mode 100644 src/plugins/renderers/drm/ply-renderer-i915-driver.c create mode 100644 src/plugins/renderers/drm/ply-renderer-i915-driver.h diff --git a/configure.ac b/configure.ac index 0758dcad..9e92eaa6 100644 --- a/configure.ac +++ b/configure.ac @@ -56,7 +56,7 @@ PKG_CHECK_MODULES(GTK, [gtk+-2.0 >= 2.12.0 ]) AC_SUBST(GTK_CFLAGS) AC_SUBST(GTK_LIBS) -PKG_CHECK_MODULES(DRM, [libdrm]) +PKG_CHECK_MODULES(DRM, [libdrm libdrm_intel]) AC_SUBST(DRM_CFLAGS) AC_SUBST(DRM_LIBS) diff --git a/src/plugins/renderers/drm/Makefile.am b/src/plugins/renderers/drm/Makefile.am index 328b881a..a9ea2f93 100644 --- a/src/plugins/renderers/drm/Makefile.am +++ b/src/plugins/renderers/drm/Makefile.am @@ -16,6 +16,8 @@ drm_la_LIBADD = $(PLYMOUTH_LIBS) $(DRM_LIBS) \ ../../../libply/libply.la \ ../../../libplybootsplash/libplybootsplash.la drm_la_SOURCES = $(srcdir)/plugin.c \ - $(srcdir)/ply-renderer-driver.h + $(srcdir)/ply-renderer-driver.h \ + $(srcdir)/ply-renderer-i915-driver.h \ + $(srcdir)/ply-renderer-i915-driver.c MAINTAINERCLEANFILES = Makefile.in diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c index 67a6bea2..dd0a55a0 100644 --- a/src/plugins/renderers/drm/plugin.c +++ b/src/plugins/renderers/drm/plugin.c @@ -57,6 +57,7 @@ #include "ply-renderer.h" #include "ply-renderer-plugin.h" #include "ply-renderer-driver.h" +#include "ply-renderer-i915-driver.h" #define BYTES_PER_PIXEL (4) @@ -403,13 +404,10 @@ load_driver (ply_renderer_backend_t *backend) return false; } -#if 0 - Something like... if (strcmp (driver_name, "i915") == 0) { backend->driver_interface = ply_renderer_i915_driver_get_interface (); } -#endif free (driver_name); if (backend->driver_interface == NULL) diff --git a/src/plugins/renderers/drm/ply-renderer-i915-driver.c b/src/plugins/renderers/drm/ply-renderer-i915-driver.c new file mode 100644 index 00000000..b32e21ec --- /dev/null +++ b/src/plugins/renderers/drm/ply-renderer-i915-driver.c @@ -0,0 +1,360 @@ +/* ply-renderer-i915-driver.c - interface to i915 drm driver + * + * 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 + */ +#include "config.h" + +#include "ply-renderer-i915-driver.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ply-hashtable.h" +#include "ply-logger.h" +#include "ply-renderer-driver.h" + +typedef struct _ply_renderer_buffer ply_renderer_buffer_t; + +struct _ply_renderer_buffer +{ + drm_intel_bo *object; + uint32_t id; + unsigned long width; + unsigned long height; + unsigned long row_stride; +}; + +struct _ply_renderer_driver +{ + int device_fd; + drm_intel_bufmgr *manager; + + ply_hashtable_t *buffers; +}; + +static ply_renderer_driver_t * +create_driver (int device_fd) +{ + ply_renderer_driver_t *driver; + int page_size; + + driver = calloc (1, sizeof (ply_renderer_driver_t)); + driver->device_fd = device_fd; + + page_size = (int) sysconf (_SC_PAGE_SIZE); + + driver->manager = drm_intel_bufmgr_gem_init (driver->device_fd, page_size); + if (driver->manager == NULL) + { + free (driver); + return NULL; + } + + 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); + + drm_intel_bufmgr_destroy (driver->manager); + free (driver); +} + +static ply_renderer_buffer_t * +ply_renderer_buffer_new (ply_renderer_driver_t *driver, + drm_intel_bo *buffer_object, + uint32_t id, + unsigned long width, + unsigned long height, + unsigned long row_stride) +{ + ply_renderer_buffer_t *buffer; + + buffer = calloc (1, sizeof (ply_renderer_buffer_t)); + buffer->object = buffer_object; + buffer->id = id; + buffer->width = width; + buffer->height = height; + buffer->row_stride = row_stride; + + return buffer; +} + +static drm_intel_bo * +create_intel_bo_from_handle (ply_renderer_driver_t *driver, + uint32_t handle) +{ + struct drm_gem_flink flink_request; + char *name; + drm_intel_bo *buffer_object; + + /* FIXME: This can't be the right way to do this. + * + * 1) It requires skirting around the API and using ioctls + * 2) It requires taking a local handle, turning it into a + * a global handle ("name"), just so we can use an api that + * will open the global name and grab the local handle from it. + */ + + memset (&flink_request, 0, sizeof (struct drm_gem_flink)); + flink_request.handle = handle; + + if (ioctl (driver->device_fd, DRM_IOCTL_GEM_FLINK, &flink_request) < 0) + return NULL; + + asprintf (&name, "buffer %u", handle); + + buffer_object = drm_intel_bo_gem_create_from_name (driver->manager, + name, flink_request.name); + free (name); + + return buffer_object; +} + +static ply_renderer_buffer_t * +ply_renderer_buffer_new_from_id (ply_renderer_driver_t *driver, + uint32_t buffer_id) +{ + ply_renderer_buffer_t *buffer; + drmModeFB *fb; + drm_intel_bo *buffer_object; + + fb = drmModeGetFB (driver->device_fd, buffer_id); + + if (fb == NULL) + return NULL; + + buffer_object = create_intel_bo_from_handle (driver, fb->handle); + + if (buffer_object == NULL) + { + drmModeFreeFB (fb); + return NULL; + } + + buffer = ply_renderer_buffer_new (driver, buffer_object, buffer_id, + fb->width, fb->height, fb->pitch); + drmModeFreeFB (fb); + + return buffer; +} + +static ply_renderer_buffer_t * +get_buffer_from_id (ply_renderer_driver_t *driver, + uint32_t buffer_id) +{ + static ply_renderer_buffer_t *buffer; + + buffer = ply_hashtable_lookup (driver->buffers, + (void *) (uintptr_t) buffer_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) + { + buffer = ply_renderer_buffer_new_from_id (driver, buffer_id); + + if (buffer == NULL) + return false; + + ply_hashtable_insert (driver->buffers, + (void *) (uintptr_t) buffer_id, + buffer); + } + + if (width != NULL) + *width = buffer->width; + + if (height != NULL) + *height = buffer->height; + + if (row_stride != NULL) + *row_stride = 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) +{ + drm_intel_bo *buffer_object; + ply_renderer_buffer_t *buffer; + uint32_t buffer_id; + + *row_stride = ply_round_to_multiple (width * 4, 256); + + buffer_object = drm_intel_bo_alloc (driver->manager, + "frame buffer", + height * *row_stride, 0); + + if (buffer_object == NULL) + { + ply_trace ("Could not allocate GEM object for frame buffer: %m"); + return 0; + } + + if (drmModeAddFB (driver->device_fd, width, height, + 24, 32, *row_stride, buffer_object->handle, + &buffer_id) != 0) + { + ply_trace ("Could not set up GEM object as frame buffer: %m"); + drm_intel_bo_unreference (buffer_object); + return 0; + } + + buffer = ply_renderer_buffer_new (driver, + buffer_object, buffer_id, + width, height, *row_stride); + 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); + drm_intel_gem_bo_map_gtt (buffer->object); + + return true; +} + +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); + drm_intel_gem_bo_unmap_gtt (buffer->object); +} + +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->object->virtual; +} + +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); +} + +static void +destroy_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); + + drmModeRmFB (driver->device_fd, buffer->id); + + drm_intel_bo_unreference (buffer->object); + + ply_hashtable_remove (driver->buffers, + (void *) (uintptr_t) buffer_id); + free (buffer); +} + +ply_renderer_driver_interface_t * +ply_renderer_i915_driver_get_interface (void) +{ + 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, + }; + + 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-i915-driver.h b/src/plugins/renderers/drm/ply-renderer-i915-driver.h new file mode 100644 index 00000000..dcc983ce --- /dev/null +++ b/src/plugins/renderers/drm/ply-renderer-i915-driver.h @@ -0,0 +1,32 @@ +/* ply-renderer-i915-driver.h + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode + */ +#ifndef PLY_RENDERER_I915_DRIVER_H +#define PLY_RENDERER_I915_DRIVER_H + +#include "ply-renderer-driver.h" + +#ifndef PLY_HIDE_FUNCTION_DECLARATIONS +ply_renderer_driver_interface_t *ply_renderer_i915_driver_get_interface (void); +#endif + +#endif /* PLY_RENDERER_I915_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 */ From 70b9868a62e7406f72c5777fb38f1c4ef7c98b59 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Sun, 20 Sep 2009 00:09:37 -0400 Subject: [PATCH 38/43] [drm] Add initial support for radeon cards --- configure.ac | 2 +- src/plugins/renderers/drm/Makefile.am | 4 +- src/plugins/renderers/drm/plugin.c | 5 + .../drm/ply-renderer-radeon-driver.c | 354 ++++++++++++++++++ .../drm/ply-renderer-radeon-driver.h | 32 ++ 5 files changed, 395 insertions(+), 2 deletions(-) create mode 100644 src/plugins/renderers/drm/ply-renderer-radeon-driver.c create mode 100644 src/plugins/renderers/drm/ply-renderer-radeon-driver.h diff --git a/configure.ac b/configure.ac index 9e92eaa6..5dee12a9 100644 --- a/configure.ac +++ b/configure.ac @@ -56,7 +56,7 @@ PKG_CHECK_MODULES(GTK, [gtk+-2.0 >= 2.12.0 ]) AC_SUBST(GTK_CFLAGS) AC_SUBST(GTK_LIBS) -PKG_CHECK_MODULES(DRM, [libdrm libdrm_intel]) +PKG_CHECK_MODULES(DRM, [libdrm libdrm_intel libdrm_radeon]) AC_SUBST(DRM_CFLAGS) AC_SUBST(DRM_LIBS) diff --git a/src/plugins/renderers/drm/Makefile.am b/src/plugins/renderers/drm/Makefile.am index a9ea2f93..29bc6427 100644 --- a/src/plugins/renderers/drm/Makefile.am +++ b/src/plugins/renderers/drm/Makefile.am @@ -18,6 +18,8 @@ drm_la_LIBADD = $(PLYMOUTH_LIBS) $(DRM_LIBS) \ drm_la_SOURCES = $(srcdir)/plugin.c \ $(srcdir)/ply-renderer-driver.h \ $(srcdir)/ply-renderer-i915-driver.h \ - $(srcdir)/ply-renderer-i915-driver.c + $(srcdir)/ply-renderer-i915-driver.c \ + $(srcdir)/ply-renderer-radeon-driver.h \ + $(srcdir)/ply-renderer-radeon-driver.c MAINTAINERCLEANFILES = Makefile.in diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c index dd0a55a0..0be43f0b 100644 --- a/src/plugins/renderers/drm/plugin.c +++ b/src/plugins/renderers/drm/plugin.c @@ -58,6 +58,7 @@ #include "ply-renderer-plugin.h" #include "ply-renderer-driver.h" #include "ply-renderer-i915-driver.h" +#include "ply-renderer-radeon-driver.h" #define BYTES_PER_PIXEL (4) @@ -408,6 +409,10 @@ load_driver (ply_renderer_backend_t *backend) { backend->driver_interface = ply_renderer_i915_driver_get_interface (); } + else if (strcmp (driver_name, "radeon") == 0) + { + backend->driver_interface = ply_renderer_radeon_driver_get_interface (); + } free (driver_name); if (backend->driver_interface == NULL) diff --git a/src/plugins/renderers/drm/ply-renderer-radeon-driver.c b/src/plugins/renderers/drm/ply-renderer-radeon-driver.c new file mode 100644 index 00000000..be11dbf8 --- /dev/null +++ b/src/plugins/renderers/drm/ply-renderer-radeon-driver.c @@ -0,0 +1,354 @@ +/* ply-renderer-radeon-driver.c - interface to radeon drm driver + * + * 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 + */ +#include "config.h" + +#include "ply-renderer-radeon-driver.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ply-hashtable.h" +#include "ply-logger.h" +#include "ply-renderer-driver.h" + +typedef struct _ply_renderer_buffer ply_renderer_buffer_t; + +struct _ply_renderer_buffer +{ + struct radeon_bo *object; + uint32_t id; + unsigned long width; + unsigned long height; + unsigned long row_stride; +}; + +struct _ply_renderer_driver +{ + int device_fd; + struct radeon_bo_manager *manager; + + ply_hashtable_t *buffers; +}; + +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->manager = radeon_bo_manager_gem_ctor (driver->device_fd); + if (driver->manager == NULL) + { + free (driver); + return NULL; + } + + 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); + + radeon_bo_manager_gem_dtor (driver->manager); + free (driver); +} + +static ply_renderer_buffer_t * +ply_renderer_buffer_new (ply_renderer_driver_t *driver, + struct radeon_bo *buffer_object, + uint32_t id, + unsigned long width, + unsigned long height, + unsigned long row_stride) +{ + ply_renderer_buffer_t *buffer; + + buffer = calloc (1, sizeof (ply_renderer_buffer_t)); + buffer->object = buffer_object; + buffer->id = id; + buffer->width = width; + buffer->height = height; + buffer->row_stride = row_stride; + + return 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 struct radeon_bo * +create_radeon_bo_from_handle (ply_renderer_driver_t *driver, + uint32_t handle) +{ + struct drm_gem_flink flink_request; + struct radeon_bo *buffer_object; + + /* FIXME: This can't be the right way to do this. + * + * 1) It requires skirting around the API and using ioctls + * 2) It requires taking a local handle, turning it into a + * a global handle ("name"), just so we can use an api that + * will open the global name and grab the local handle from it. + */ + + memset (&flink_request, 0, sizeof (struct drm_gem_flink)); + flink_request.handle = handle; + + if (ioctl (driver->device_fd, DRM_IOCTL_GEM_FLINK, &flink_request) < 0) + return NULL; + + buffer_object = radeon_bo_open (driver->manager, flink_request.name, + 0, 0, RADEON_GEM_DOMAIN_GTT, 0); + + return buffer_object; +} + +static ply_renderer_buffer_t * +ply_renderer_buffer_new_from_id (ply_renderer_driver_t *driver, + uint32_t buffer_id) +{ + ply_renderer_buffer_t *buffer; + drmModeFB *fb; + struct radeon_bo *buffer_object; + + fb = drmModeGetFB (driver->device_fd, buffer_id); + + if (fb == NULL) + return NULL; + + buffer_object = create_radeon_bo_from_handle (driver, fb->handle); + + if (buffer_object == NULL) + { + drmModeFreeFB (fb); + return NULL; + } + + buffer = ply_renderer_buffer_new (driver, buffer_object, buffer_id, + fb->width, fb->height, fb->pitch); + drmModeFreeFB (fb); + + 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) + { + buffer = ply_renderer_buffer_new_from_id (driver, buffer_id); + + if (buffer == NULL) + return false; + + ply_hashtable_insert (driver->buffers, + (void *) (uintptr_t) buffer_id, + buffer); + } + + if (width != NULL) + *width = buffer->width; + + if (height != NULL) + *height = buffer->height; + + if (row_stride != NULL) + *row_stride = 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) +{ + struct radeon_bo *buffer_object; + ply_renderer_buffer_t *buffer; + uint32_t buffer_id; + + *row_stride = ply_round_to_multiple (width * 4, 256); + + buffer_object = radeon_bo_open (driver->manager, 0, + height * *row_stride, + 0, RADEON_GEM_DOMAIN_GTT, 0); + + if (buffer_object == NULL) + { + ply_trace ("Could not allocate GEM object for frame buffer: %m"); + return 0; + } + + if (drmModeAddFB (driver->device_fd, width, height, + 24, 32, *row_stride, buffer_object->handle, + &buffer_id) != 0) + { + ply_trace ("Could not set up GEM object as frame buffer: %m"); + radeon_bo_unref (buffer_object); + return 0; + } + + buffer = ply_renderer_buffer_new (driver, + buffer_object, buffer_id, + width, height, *row_stride); + 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 radeon_bo_map (buffer->object, true) == 0; +} + +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); + + radeon_bo_unmap (buffer->object); +} + +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->object->ptr; +} + +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); +} + +static void +destroy_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); + + drmModeRmFB (driver->device_fd, buffer->id); + + radeon_bo_unref (buffer->object); + + ply_hashtable_remove (driver->buffers, + (void *) (uintptr_t) buffer_id); + free (buffer); +} + +ply_renderer_driver_interface_t * +ply_renderer_radeon_driver_get_interface (void) +{ + 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, + }; + + 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-radeon-driver.h b/src/plugins/renderers/drm/ply-renderer-radeon-driver.h new file mode 100644 index 00000000..dcec1b1b --- /dev/null +++ b/src/plugins/renderers/drm/ply-renderer-radeon-driver.h @@ -0,0 +1,32 @@ +/* ply-renderer-radeon-driver.h + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode + */ +#ifndef PLY_RENDERER_RADEON_DRIVER_H +#define PLY_RENDERER_RADEON_DRIVER_H + +#include "ply-renderer-driver.h" + +#ifndef PLY_HIDE_FUNCTION_DECLARATIONS +ply_renderer_driver_interface_t *ply_renderer_radeon_driver_get_interface (void); +#endif + +#endif /* PLY_RENDERER_RADEON_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 */ From fe6ee7723abe5d0706e3f2563f99cb8b96ac5ccf Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Sun, 20 Sep 2009 00:09:37 -0400 Subject: [PATCH 39/43] [drm] Add initial support for nvidia cards --- configure.ac | 2 +- src/plugins/renderers/drm/Makefile.am | 4 +- src/plugins/renderers/drm/plugin.c | 5 + .../drm/ply-renderer-nouveau-driver.c | 332 ++++++++++++++++++ .../drm/ply-renderer-nouveau-driver.h | 32 ++ 5 files changed, 373 insertions(+), 2 deletions(-) create mode 100644 src/plugins/renderers/drm/ply-renderer-nouveau-driver.c create mode 100644 src/plugins/renderers/drm/ply-renderer-nouveau-driver.h diff --git a/configure.ac b/configure.ac index 5dee12a9..c98a65b9 100644 --- a/configure.ac +++ b/configure.ac @@ -56,7 +56,7 @@ PKG_CHECK_MODULES(GTK, [gtk+-2.0 >= 2.12.0 ]) AC_SUBST(GTK_CFLAGS) AC_SUBST(GTK_LIBS) -PKG_CHECK_MODULES(DRM, [libdrm libdrm_intel libdrm_radeon]) +PKG_CHECK_MODULES(DRM, [libdrm libdrm_intel libdrm_radeon libdrm_nouveau]) AC_SUBST(DRM_CFLAGS) AC_SUBST(DRM_LIBS) diff --git a/src/plugins/renderers/drm/Makefile.am b/src/plugins/renderers/drm/Makefile.am index 29bc6427..da757c59 100644 --- a/src/plugins/renderers/drm/Makefile.am +++ b/src/plugins/renderers/drm/Makefile.am @@ -20,6 +20,8 @@ drm_la_SOURCES = $(srcdir)/plugin.c \ $(srcdir)/ply-renderer-i915-driver.h \ $(srcdir)/ply-renderer-i915-driver.c \ $(srcdir)/ply-renderer-radeon-driver.h \ - $(srcdir)/ply-renderer-radeon-driver.c + $(srcdir)/ply-renderer-radeon-driver.c \ + $(srcdir)/ply-renderer-nouveau-driver.h \ + $(srcdir)/ply-renderer-nouveau-driver.c MAINTAINERCLEANFILES = Makefile.in diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c index 0be43f0b..239f8aee 100644 --- a/src/plugins/renderers/drm/plugin.c +++ b/src/plugins/renderers/drm/plugin.c @@ -59,6 +59,7 @@ #include "ply-renderer-driver.h" #include "ply-renderer-i915-driver.h" #include "ply-renderer-radeon-driver.h" +#include "ply-renderer-nouveau-driver.h" #define BYTES_PER_PIXEL (4) @@ -413,6 +414,10 @@ load_driver (ply_renderer_backend_t *backend) { backend->driver_interface = ply_renderer_radeon_driver_get_interface (); } + else if (strcmp (driver_name, "nouveau") == 0) + { + backend->driver_interface = ply_renderer_nouveau_driver_get_interface (); + } free (driver_name); if (backend->driver_interface == NULL) diff --git a/src/plugins/renderers/drm/ply-renderer-nouveau-driver.c b/src/plugins/renderers/drm/ply-renderer-nouveau-driver.c new file mode 100644 index 00000000..a94b0f4b --- /dev/null +++ b/src/plugins/renderers/drm/ply-renderer-nouveau-driver.c @@ -0,0 +1,332 @@ +/* ply-renderer-nouveau-driver.c - interface to nouveau drm driver + * + * 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 + */ +#include "config.h" + +#include "ply-renderer-nouveau-driver.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ply-hashtable.h" +#include "ply-logger.h" +#include "ply-renderer-driver.h" + +typedef struct _ply_renderer_buffer ply_renderer_buffer_t; + +struct _ply_renderer_buffer +{ + struct nouveau_bo *object; + uint32_t id; + unsigned long width; + unsigned long height; + unsigned long row_stride; +}; + +struct _ply_renderer_driver +{ + int device_fd; + struct nouveau_device *device; + + ply_hashtable_t *buffers; +}; + +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; + + if (nouveau_device_open_existing (&driver->device, true, + driver->device_fd, 0) < 0) + { + free (driver); + return NULL; + } + + 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); + + nouveau_device_close (&driver->device); + free (driver); +} + +static ply_renderer_buffer_t * +ply_renderer_buffer_new (ply_renderer_driver_t *driver, + struct nouveau_bo *buffer_object, + uint32_t id, + unsigned long width, + unsigned long height, + unsigned long row_stride) +{ + ply_renderer_buffer_t *buffer; + + buffer = calloc (1, sizeof (ply_renderer_buffer_t)); + buffer->object = buffer_object; + buffer->id = id; + buffer->width = width; + buffer->height = height; + buffer->row_stride = row_stride; + + return buffer; +} + +static ply_renderer_buffer_t * +ply_renderer_buffer_new_from_id (ply_renderer_driver_t *driver, + uint32_t buffer_id) +{ + ply_renderer_buffer_t *buffer; + drmModeFB *fb; + struct nouveau_bo *buffer_object; + + fb = drmModeGetFB (driver->device_fd, buffer_id); + + if (fb == NULL) + return NULL; + + if (nouveau_bo_wrap (driver->device, + fb->handle, &buffer_object) < 0) + { + drmModeFreeFB (fb); + return NULL; + } + + buffer = ply_renderer_buffer_new (driver, buffer_object, buffer_id, + fb->width, fb->height, fb->pitch); + drmModeFreeFB (fb); + + return 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) + { + buffer = ply_renderer_buffer_new_from_id (driver, buffer_id); + + if (buffer == NULL) + return false; + + ply_hashtable_insert (driver->buffers, + (void *) (uintptr_t) buffer_id, + buffer); + } + + if (width != NULL) + *width = buffer->width; + + if (height != NULL) + *height = buffer->height; + + if (row_stride != NULL) + *row_stride = 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) +{ + struct nouveau_bo *buffer_object; + ply_renderer_buffer_t *buffer; + uint32_t buffer_id; + + *row_stride = ply_round_to_multiple (width * 4, 256); + + buffer_object = NULL; + if (nouveau_bo_new (driver->device, + NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, 0, + height * *row_stride, &buffer_object) < 0) + { + ply_trace ("Could not allocate GEM object for frame buffer: %m"); + return 0; + } + + /* The map here forces the buffer object to be instantiated + * immediately (it's normally instantiated lazily when needed + * by other nouveau_bo api) + */ + nouveau_bo_map (buffer_object, NOUVEAU_BO_WR); + if (drmModeAddFB (driver->device_fd, width, height, + 24, 32, *row_stride, buffer_object->handle, + &buffer_id) != 0) + { + nouveau_bo_unmap (buffer_object); + ply_trace ("Could not set up GEM object as frame buffer: %m"); + nouveau_bo_ref (NULL, &buffer_object); + return 0; + } + nouveau_bo_unmap (buffer_object); + + buffer = ply_renderer_buffer_new (driver, + buffer_object, buffer_id, + width, height, *row_stride); + 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 nouveau_bo_map (buffer->object, NOUVEAU_BO_WR) == 0; +} + +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); + + nouveau_bo_unmap (buffer->object); +} + +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->object->map; +} + +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); +} + +static void +destroy_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); + + drmModeRmFB (driver->device_fd, buffer->id); + + nouveau_bo_ref (NULL, &buffer->object); + + ply_hashtable_remove (driver->buffers, + (void *) (uintptr_t) buffer_id); + free (buffer); +} + +ply_renderer_driver_interface_t * +ply_renderer_nouveau_driver_get_interface (void) +{ + 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, + }; + + 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-nouveau-driver.h b/src/plugins/renderers/drm/ply-renderer-nouveau-driver.h new file mode 100644 index 00000000..1baed4a8 --- /dev/null +++ b/src/plugins/renderers/drm/ply-renderer-nouveau-driver.h @@ -0,0 +1,32 @@ +/* ply-renderer-nouveau-driver.h + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode + */ +#ifndef PLY_RENDERER_NOUVEAU_DRIVER_H +#define PLY_RENDERER_NOUVEAU_DRIVER_H + +#include "ply-renderer-driver.h" + +#ifndef PLY_HIDE_FUNCTION_DECLARATIONS +ply_renderer_driver_interface_t *ply_renderer_nouveau_driver_get_interface (void); +#endif + +#endif /* PLY_RENDERER_NOUVEAU_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 */ From 0b763c61b4a4d92539724bd83ab37efc2c7feeca Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 28 Sep 2009 17:27:56 -0400 Subject: [PATCH 40/43] [drm] Force fb backend if 1 head and ttm driver Drivers backed by TTM memory manager don't support mapping the kernel backed framebuffer console, so can't be used for doing a smooth transition (unless you use /dev/fb). In single head configurations, there isn't a big advantage to using libdrm anyway, so we bail for TTM drivers. --- src/plugins/renderers/drm/plugin.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c index 239f8aee..9047d79e 100644 --- a/src/plugins/renderers/drm/plugin.c +++ b/src/plugins/renderers/drm/plugin.c @@ -98,6 +98,7 @@ struct _ply_renderer_backend ply_renderer_driver_interface_t *driver_interface; ply_renderer_driver_t *driver; + uint32_t driver_supports_mapping_console; int device_fd; char *device_name; @@ -409,14 +410,17 @@ load_driver (ply_renderer_backend_t *backend) if (strcmp (driver_name, "i915") == 0) { backend->driver_interface = ply_renderer_i915_driver_get_interface (); + backend->driver_supports_mapping_console = true; } else if (strcmp (driver_name, "radeon") == 0) { backend->driver_interface = ply_renderer_radeon_driver_get_interface (); + backend->driver_supports_mapping_console = false; } else if (strcmp (driver_name, "nouveau") == 0) { backend->driver_interface = ply_renderer_nouveau_driver_get_interface (); + backend->driver_supports_mapping_console = false; } free (driver_name); @@ -717,6 +721,20 @@ create_heads_for_active_connectors (ply_renderer_backend_t *backend) ply_list_append_data (backend->heads, head); } + /* 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. + * + * 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) + { + free_heads (backend); + return false; + } + return ply_list_get_length (backend->heads) > 0; } From 1b10da8890ea0252d52b6ce7a6d38a928dfd77bd Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 23 Sep 2009 17:38:05 -0400 Subject: [PATCH 41/43] [animation] Use default event loop --- src/libplybootsplash/ply-animation.c | 4 +--- src/libplybootsplash/ply-animation.h | 1 - src/plugins/splash/two-step/plugin.c | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/libplybootsplash/ply-animation.c b/src/libplybootsplash/ply-animation.c index 9bd2b147..170b44ca 100644 --- a/src/libplybootsplash/ply-animation.c +++ b/src/libplybootsplash/ply-animation.c @@ -294,16 +294,14 @@ ply_animation_load (ply_animation_t *animation) bool ply_animation_start (ply_animation_t *animation, - ply_event_loop_t *loop, ply_pixel_display_t *display, ply_trigger_t *stop_trigger, long x, long y) { assert (animation != NULL); - assert (animation->loop == NULL); - animation->loop = loop; + animation->loop = ply_event_loop_get_default (); animation->display = display; animation->stop_trigger = stop_trigger; animation->is_stopped = false; diff --git a/src/libplybootsplash/ply-animation.h b/src/libplybootsplash/ply-animation.h index 7a0bdf33..7b905472 100644 --- a/src/libplybootsplash/ply-animation.h +++ b/src/libplybootsplash/ply-animation.h @@ -39,7 +39,6 @@ void ply_animation_free (ply_animation_t *animation); bool ply_animation_load (ply_animation_t *animation); bool ply_animation_start (ply_animation_t *animation, - ply_event_loop_t *loop, ply_pixel_display_t *display, ply_trigger_t *stop_trigger, long x, diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c index d52a8e4b..435031e2 100644 --- a/src/plugins/splash/two-step/plugin.c +++ b/src/plugins/splash/two-step/plugin.c @@ -290,7 +290,6 @@ view_start_end_animation (view_t *view, y = plugin->animation_vertical_alignment * screen_height - height / 2.0; ply_animation_start (view->end_animation, - plugin->loop, view->display, trigger, x, y); } From 1cf529bd9b3c83a2e9f6a0e919941d7b93b0fc43 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 23 Sep 2009 17:38:54 -0400 Subject: [PATCH 42/43] [animation] Make ply_animation_start idempotent --- src/libplybootsplash/ply-animation.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libplybootsplash/ply-animation.c b/src/libplybootsplash/ply-animation.c index 170b44ca..1fee4b9c 100644 --- a/src/libplybootsplash/ply-animation.c +++ b/src/libplybootsplash/ply-animation.c @@ -301,6 +301,9 @@ ply_animation_start (ply_animation_t *animation, { assert (animation != NULL); + if (!animation->is_stopped) + return true; + animation->loop = ply_event_loop_get_default (); animation->display = display; animation->stop_trigger = stop_trigger; From 6ceccc7ce8a0ff0ae6efdd75b23670f77860af9b Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 25 Sep 2009 16:39:27 -0400 Subject: [PATCH 43/43] [throbber] Properly finish animation before stopping I can't say I have any idea what I was trying to do before but it's clearly bogus. --- src/libplybootsplash/ply-throbber.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/libplybootsplash/ply-throbber.c b/src/libplybootsplash/ply-throbber.c index 3e463d36..9131e715 100644 --- a/src/libplybootsplash/ply-throbber.c +++ b/src/libplybootsplash/ply-throbber.c @@ -68,7 +68,7 @@ struct _ply_throbber long x, y; long width, height; - double start_time, previous_time, now; + double start_time, now; int frame_number; uint32_t is_stopped : 1; @@ -145,9 +145,8 @@ animate_at_time (ply_throbber_t *throbber, if (throbber->stop_trigger != NULL) { - if ((time - throbber->previous_time) >= 2 * M_PI) - throbber->frame_number = number_of_frames - 1; - should_continue = false; + if (throbber->frame_number == number_of_frames - 1) + should_continue = false; } frames = (ply_image_t * const *) ply_array_get_elements (throbber->frames); @@ -169,7 +168,6 @@ on_timeout (ply_throbber_t *throbber) { double sleep_time; bool should_continue; - throbber->previous_time = throbber->now; throbber->now = ply_get_timestamp (); #ifdef REAL_TIME_ANIMATION