summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2009-09-28 18:03:11 -0400
committerRay Strode <rstrode@redhat.com>2009-09-28 18:03:11 -0400
commit3fe3aabc7b1a5752daf8c99aff236cfbcddc75e7 (patch)
tree8a584d2672698a971c5f89e28264fd500297a063
parenta8f0572cb279ae2252cec169522a3e3e5b22f105 (diff)
parent6ceccc7ce8a0ff0ae6efdd75b23670f77860af9b (diff)
[branch-merge] Support multi-head renderering
This merges the "seat-rework" branch to master. Instead of talking to /dev/fb, we now use libdrm to set up the drawing area. This gives us the functionality we need for querying the user's monitor layout. There are cases where /dev/fb works when the new interfaces don't. For those cases we fall back to /dev/fb.
-rw-r--r--configure.ac7
-rwxr-xr-xscripts/plymouth-populate-initrd.in3
-rw-r--r--src/libply/Makefile.am8
-rw-r--r--src/libply/ply-event-loop.c11
-rw-r--r--src/libply/ply-event-loop.h1
-rw-r--r--src/libply/ply-frame-buffer.c1422
-rw-r--r--src/libply/ply-frame-buffer.h112
-rw-r--r--src/libply/ply-rectangle.c294
-rw-r--r--src/libply/ply-rectangle.h105
-rw-r--r--src/libply/ply-region.c390
-rw-r--r--src/libply/ply-region.h (renamed from src/libply/ply-terminal.h)34
-rw-r--r--src/libply/ply-terminal-session.c71
-rw-r--r--src/libply/ply-terminal.c201
-rw-r--r--src/libply/ply-trigger.c15
-rw-r--r--src/libply/ply-trigger.h1
-rw-r--r--src/libply/ply-utils.c21
-rw-r--r--src/libply/ply-utils.h5
-rw-r--r--src/libply/tests/Makefile.am2
-rw-r--r--src/libply/tests/ply-frame-buffer-test.am14
-rw-r--r--src/libply/tests/ply-terminal-session-test.am2
-rw-r--r--src/libply/tests/ply-terminal-test.am14
-rw-r--r--src/libplybootsplash/Makefile.am19
-rw-r--r--src/libplybootsplash/ply-animation.c71
-rw-r--r--src/libplybootsplash/ply-animation.h13
-rw-r--r--src/libplybootsplash/ply-boot-splash-plugin.h21
-rw-r--r--src/libplybootsplash/ply-boot-splash.c243
-rw-r--r--src/libplybootsplash/ply-boot-splash.h24
-rw-r--r--src/libplybootsplash/ply-console.c406
-rw-r--r--src/libplybootsplash/ply-console.h70
-rw-r--r--src/libplybootsplash/ply-entry.c67
-rw-r--r--src/libplybootsplash/ply-entry.h13
-rw-r--r--src/libplybootsplash/ply-image.c146
-rw-r--r--src/libplybootsplash/ply-keyboard.c583
-rw-r--r--src/libplybootsplash/ply-keyboard.h78
-rw-r--r--src/libplybootsplash/ply-label-plugin.h16
-rw-r--r--src/libplybootsplash/ply-label.c26
-rw-r--r--src/libplybootsplash/ply-label.h17
-rw-r--r--src/libplybootsplash/ply-pixel-buffer.c602
-rw-r--r--src/libplybootsplash/ply-pixel-buffer.h103
-rw-r--r--src/libplybootsplash/ply-pixel-display.c175
-rw-r--r--src/libplybootsplash/ply-pixel-display.h68
-rw-r--r--src/libplybootsplash/ply-progress-animation.c164
-rw-r--r--src/libplybootsplash/ply-progress-animation.h11
-rw-r--r--src/libplybootsplash/ply-progress-bar.c84
-rw-r--r--src/libplybootsplash/ply-progress-bar.h12
-rw-r--r--src/libplybootsplash/ply-renderer-plugin.h71
-rw-r--r--src/libplybootsplash/ply-renderer.c355
-rw-r--r--src/libplybootsplash/ply-renderer.h70
-rw-r--r--src/libplybootsplash/ply-terminal.c513
-rw-r--r--src/libplybootsplash/ply-terminal.h82
-rw-r--r--src/libplybootsplash/ply-text-display.c343
-rw-r--r--src/libplybootsplash/ply-text-display.h91
-rw-r--r--src/libplybootsplash/ply-text-progress-bar.c65
-rw-r--r--src/libplybootsplash/ply-text-progress-bar.h4
-rw-r--r--src/libplybootsplash/ply-throbber.c102
-rw-r--r--src/libplybootsplash/ply-throbber.h19
-rw-r--r--src/libplybootsplash/ply-window.c1156
-rw-r--r--src/libplybootsplash/ply-window.h165
-rw-r--r--src/main.c349
-rw-r--r--src/plugins/Makefile.am2
-rw-r--r--src/plugins/controls/label/plugin.c201
-rw-r--r--src/plugins/renderers/Makefile.am2
-rw-r--r--src/plugins/renderers/drm/Makefile.am27
-rw-r--r--src/plugins/renderers/drm/plugin.c1075
-rw-r--r--src/plugins/renderers/drm/ply-renderer-driver.h67
-rw-r--r--src/plugins/renderers/drm/ply-renderer-i915-driver.c360
-rw-r--r--src/plugins/renderers/drm/ply-renderer-i915-driver.h32
-rw-r--r--src/plugins/renderers/drm/ply-renderer-nouveau-driver.c332
-rw-r--r--src/plugins/renderers/drm/ply-renderer-nouveau-driver.h32
-rw-r--r--src/plugins/renderers/drm/ply-renderer-radeon-driver.c354
-rw-r--r--src/plugins/renderers/drm/ply-renderer-radeon-driver.h32
-rw-r--r--src/plugins/renderers/frame-buffer/Makefile.am20
-rw-r--r--src/plugins/renderers/frame-buffer/plugin.c667
-rw-r--r--src/plugins/splash/details/plugin.c314
-rw-r--r--src/plugins/splash/fade-throbber/plugin.c844
-rw-r--r--src/plugins/splash/script/plugin.c520
-rw-r--r--src/plugins/splash/script/script-lib-sprite.c66
-rw-r--r--src/plugins/splash/script/script-lib-sprite.h13
-rw-r--r--src/plugins/splash/space-flares/plugin.c916
-rw-r--r--src/plugins/splash/text/plugin.c637
-rw-r--r--src/plugins/splash/throbgress/plugin.c746
-rw-r--r--src/plugins/splash/two-step/plugin.c828
-rw-r--r--src/tests/Makefile.am1
-rw-r--r--src/tests/ply-boot-splash-test.am16
-rw-r--r--src/tests/ply-window-test.am8
85 files changed, 11782 insertions, 5480 deletions
diff --git a/configure.ac b/configure.ac
index af507ffd..c98a65b9 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 libdrm_intel libdrm_radeon libdrm_nouveau])
+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
@@ -209,6 +213,9 @@ 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/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 dcf2b427..14eb6fc7 100755
--- a/scripts/plymouth-populate-initrd.in
+++ b/scripts/plymouth-populate-initrd.in
@@ -93,6 +93,9 @@ 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
for x in ${DATADIR}/plymouth/themes/${PLYMOUTH_THEME_NAME}/* ; do
[ ! -f "$x" ] && break
diff --git a/src/libply/Makefile.am b/src/libply/Makefile.am
index e0cb84de..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 \
@@ -23,7 +22,8 @@ libply_HEADERS = \
ply-logger.h \
ply-key-file.h \
ply-progress.h \
- ply-terminal.h \
+ ply-rectangle.h \
+ ply-region.h \
ply-terminal-session.h \
ply-trigger.h \
ply-utils.h
@@ -36,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 \
@@ -45,7 +44,8 @@ libply_la_SOURCES = ply-event-loop.c \
ply-logger.c \
ply-key-file.c \
ply-progress.c \
- ply-terminal.c \
+ ply-rectangle.c \
+ ply-region.c \
ply-terminal-session.c \
ply-trigger.c \
ply-utils.c
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/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 <cbrej@cs.man.ac.uk>
- *
- * 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 <cbrej@cs.man.ac.uk>
- * Kristian Høgsberg <krh@redhat.com>
- * Ray Strode <rstrode@redhat.com>
- */
-#include "config.h"
-#include "ply-list.h"
-#include "ply-frame-buffer.h"
-#include "ply-logger.h"
-
-#include <arpa/inet.h>
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <values.h>
-#include <unistd.h>
-
-#include <linux/fb.h>
-
-#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 <math.h>
-#include <stdio.h>
-#include <sys/time.h>
-
-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 <rstrode@redhat.com>
- */
-#ifndef PLY_FRAME_BUFFER_H
-#define PLY_FRAME_BUFFER_H
-
-#include <stdbool.h>
-#include <stdint.h>
-
-#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/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 <cbrej@cs.man.ac.uk>
+ *
+ * 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 <cbrej@cs.man.ac.uk>
+ * Ray Strode <rstrode@redhat.com>
+ */
+#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 <rstrode@redhat.com>
+ */
+#ifndef PLY_RECTANGLE_H
+#define PLY_RECTANGLE_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#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: */
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 <cbrej@cs.man.ac.uk>
+ *
+ * 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 <cbrej@cs.man.ac.uk>
+ * Ray Strode <rstrode@redhat.com>
+ */
+#include "config.h"
+#include "ply-region.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#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-terminal.h b/src/libply/ply-region.h
index df5af542..ee6e992f 100644
--- a/src/libply/ply-terminal.h
+++ b/src/libply/ply-region.h
@@ -1,6 +1,6 @@
-/* ply-terminal.h - psuedoterminal abstraction
+/* ply-region.h
*
- * Copyright (C) 2007 Red Hat, Inc.
+ * 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
@@ -19,25 +19,29 @@
*
* Written By: Ray Strode <rstrode@redhat.com>
*/
-#ifndef PLY_TERMINAL_H
-#define PLY_TERMINAL_H
+#ifndef PLY_REGION_H
+#define PLY_REGION_H
#include <stdbool.h>
#include <stdint.h>
-#include <unistd.h>
-typedef struct _ply_terminal ply_terminal_t;
+#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_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);
+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_TERMINAL_H */
+#endif /* PLY_REGION_H */
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
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 <krh@redhat.com>
- * Ray Strode <rstrode@redhat.com>
- */
-#include "config.h"
-#include "ply-terminal.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#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 <stdio.h>
-
-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-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;
}
@@ -132,12 +134,25 @@ 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)
{
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
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..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,
@@ -104,8 +107,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 */
diff --git a/src/libply/tests/Makefile.am b/src/libply/tests/Makefile.am
index 9ef83381..5707c251 100644
--- a/src/libply/tests/Makefile.am
+++ b/src/libply/tests/Makefile.am
@@ -5,8 +5,6 @@ INCLUDES = \
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-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
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
diff --git a/src/libplybootsplash/Makefile.am b/src/libplybootsplash/Makefile.am
index 508a212c..d2638055 100644
--- a/src/libplybootsplash/Makefile.am
+++ b/src/libplybootsplash/Makefile.am
@@ -10,15 +10,22 @@ 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 \
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 \
+ ply-renderer-plugin.h \
+ 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) \
@@ -32,15 +39,21 @@ 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 \
ply-label.c \
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 \
- ply-window.c \
+ ply-terminal.c \
+ ply-pixel-buffer.c \
+ ply-renderer.c \
ply-boot-splash.c
MAINTAINERCLEANFILES = Makefile.in
diff --git a/src/libplybootsplash/ply-animation.c b/src/libplybootsplash/ply-animation.c
index 7d2c481d..1fee4b9c 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 <linux/kd.h>
@@ -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++;
@@ -313,19 +294,19 @@ 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)
{
assert (animation != NULL);
- assert (animation->loop == NULL);
- animation->loop = loop;
- animation->window = window;
+ if (!animation->is_stopped)
+ return true;
+
+ animation->loop = ply_event_loop_get_default ();
+ 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 +326,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 +335,8 @@ ply_animation_stop_now (ply_animation_t *animation)
on_timeout, animation);
animation->loop = NULL;
}
+
+ animation->display = NULL;
}
void
@@ -376,6 +357,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..7b905472 100644
--- a/src/libplybootsplash/ply-animation.h
+++ b/src/libplybootsplash/ply-animation.h
@@ -27,9 +27,8 @@
#include <unistd.h>
#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;
@@ -40,14 +39,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
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 <wchar.h>
#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;
}
+static void
+refresh_displays (ply_boot_splash_t *splash)
+{
+ 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_set_keyboard (ply_boot_splash_t *splash,
+ ply_keyboard_t *keyboard)
+{
+ 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_window (ply_boot_splash_t *splash,
- ply_window_t *window)
+ply_boot_splash_add_text_display (ply_boot_splash_t *splash,
+ ply_text_display_t *display)
{
- splash->plugin_interface->add_window (splash->plugin, window);
+ 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_window (ply_boot_splash_t *splash,
- ply_window_t *window)
+ply_boot_splash_remove_text_display (ply_boot_splash_t *splash,
+ ply_text_display_t *display)
{
- splash->plugin_interface->remove_window (splash->plugin, window);
+ 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);
+ console = ply_console_new ();
+
+ if (!ply_console_open (console))
+ {
+ perror ("could not open console");
+ return errno;
+ }
+
+ 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);
- ply_window_attach_to_event_loop (state.window, state.loop);
- if (!ply_window_open (state.window))
+ if (!ply_renderer_open (renderer))
{
- perror ("could not open terminal");
+ perror ("could not open renderer /dev/fb");
+ ply_renderer_free (renderer);
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);
+ 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 <unistd.h>
#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/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 <rstrode@redhat.com>
+ */
+#include "config.h"
+#include "ply-console.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <termios.h>
+#include <unistd.h>
+#include <wchar.h>
+
+#include <linux/kd.h>
+#include <linux/major.h>
+#include <linux/vt.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
+
+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 <rstrode@redhat.com>
+ */
+#ifndef PLY_CONSOLE_H
+#define PLY_CONSOLE_H
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+
+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 */
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 <linux/kd.h>
@@ -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->is_hidden = true;
+ ply_entry_draw (entry);
- entry->frame_buffer = NULL;
- entry->window = NULL;
+ entry->display = NULL;
entry->loop = NULL;
-
- entry->is_hidden = true;
}
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 <unistd.h>
#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);
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 <math.h>
-#include <signal.h>
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <values.h>
-
-#include <linux/kd.h>
-
-#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: */
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 <rstrode@redhat.com>
+ */
+#include "config.h"
+#include "ply-keyboard.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <wchar.h>
+
+#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 <rstrode@redhat.com>
+ */
+#ifndef PLY_KEYBOARD_H
+#define PLY_KEYBOARD_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#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 */
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 <unistd.h>
#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;
+}
+
+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);
+ 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 <unistd.h>
#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/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 <cbrej@cs.man.ac.uk>
+ *
+ * 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 <cbrej@cs.man.ac.uk>
+ * Kristian Høgsberg <krh@redhat.com>
+ * Ray Strode <rstrode@redhat.com>
+ */
+#include "config.h"
+#include "ply-list.h"
+#include "ply-pixel-buffer.h"
+#include "ply-logger.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+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 <rstrode@redhat.com>
+ */
+#ifndef PLY_PIXEL_BUFFER_H
+#define PLY_PIXEL_BUFFER_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#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: */
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 <rstrode@redhat.com>
+ */
+#include "config.h"
+#include "ply-pixel-display.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <termios.h>
+#include <unistd.h>
+
+#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 <rstrode@redhat.com>
+ */
+#ifndef PLY_PIXEL_DISPLAY_H
+#define PLY_PIXEL_DISPLAY_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#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 */
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 <linux/kd.h>
@@ -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
{
+ ply_rectangle_t fill_area;
+
+ previous_frame_data = ply_image_get_data (frames[frame_number - 1]);
if (progress_animation->transition == PLY_PROGRESS_ANIMATION_TRANSITION_FADE_OVER)
- fade_out_opacity = 1.0;
+ {
+ 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]);
- 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);
+ {
+ 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;
+ progress_animation->is_hidden = true;
if (progress_animation->frame_area.width > 0)
- draw_background (progress_animation);
-
- progress_animation->frame_buffer = NULL;
- progress_animation->window = NULL;
+ {
+ 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->is_hidden = true;
+ 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 <stdint.h>
#include <unistd.h>
-#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);
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 <linux/kd.h>
#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;
@@ -97,54 +94,67 @@ ply_progress_bar_free (ply_progress_bar_t *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 (ply_progress_bar_t *progress_bar)
+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;
- 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,
+ 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 */
- ply_frame_buffer_unpause_updates (progress_bar->frame_buffer);
}
void
-ply_progress_bar_show (ply_progress_bar_t *progress_bar,
- ply_window_t *window,
- long x,
- long y)
+ply_progress_bar_draw (ply_progress_bar_t *progress_bar)
+{
+ if (progress_bar->is_hidden)
+ return;
+
+ ply_progress_bar_update_area (progress_bar, progress_bar->area.x, progress_bar->area.y);
+ 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_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 <unistd.h>
#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);
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 <rstrode@redhat.com>
+ */
+#ifndef PLY_RENDERER_PLUGIN_H
+#define PLY_RENDERER_PLUGIN_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#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..5410feb8
--- /dev/null
+++ b/src/libplybootsplash/ply-renderer.c
@@ -0,0 +1,355 @@
+/* ply-renderer.c - renderer abstraction
+ *
+ * Copyright (C) 2006, 2007, 2008, 2009 Red Hat, Inc.
+ * 2008 Charlie Brej <cbrej@cs.man.ac.uk>
+ *
+ * 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 <cbrej@cs.man.ac.uk>
+ * Kristian Høgsberg <krh@redhat.com>
+ * Ray Strode <rstrode@redhat.com>
+ */
+#include "config.h"
+#include "ply-renderer.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#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_terminal_t *terminal;
+ 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/drm.so",
+ 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 <rstrode@redhat.com>
+ */
+#ifndef PLY_RENDERER_H
+#define PLY_RENDERER_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#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/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 <rstrode@redhat.com>
+ */
+#include "config.h"
+#include "ply-terminal.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <termios.h>
+#include <unistd.h>
+#include <wchar.h>
+
+#include <linux/kd.h>
+#include <linux/major.h>
+#include <linux/vt.h>
+
+#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 <rstrode@redhat.com>
+ */
+#ifndef PLY_TERMINAL_H
+#define PLY_TERMINAL_H
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#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 */
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 <rstrode@redhat.com>
+ */
+#include "config.h"
+#include "ply-text-display.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <wchar.h>
+
+#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 <rstrode@redhat.com>
+ */
+#ifndef PLY_TEXT_DISPLAY_H
+#define PLY_TEXT_DISPLAY_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#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 */
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 <unistd.h>
#include <wchar.h>
+#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 <linux/kd.h>
@@ -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 <unistd.h>
#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,
diff --git a/src/libplybootsplash/ply-throbber.c b/src/libplybootsplash/ply-throbber.c
index 7c2d3327..9131e715 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 <linux/kd.h>
@@ -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;
+ double start_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,24 @@ 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;
- should_continue = false;
+ if (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;
}
@@ -186,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
@@ -204,9 +185,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 +291,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 +320,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 +334,7 @@ ply_throbber_stop_now (ply_throbber_t *throbber)
on_timeout, throbber);
throbber->loop = NULL;
}
+ throbber->display = NULL;
}
void
@@ -379,6 +357,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 <unistd.h>
#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
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 <rstrode@redhat.com>
- */
-#include "config.h"
-#include "ply-window.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <termios.h>
-#include <unistd.h>
-#include <wchar.h>
-
-#include <linux/kd.h>
-#include <linux/vt.h>
-
-#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 <stdio.h>
-
-#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 <rstrode@redhat.com>
- */
-#ifndef PLY_WINDOW_H
-#define PLY_WINDOW_H
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <unistd.h>
-
-#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/main.c b/src/main.c
index a77c45b6..d79b816e 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);
@@ -461,47 +468,6 @@ on_error (state_t *state)
}
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)
{
ply_trace ("checking if plymouth should be running");
@@ -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;
-
- next_node = ply_list_get_next_node (state->windows, node);
+ ply_pixel_display_t *display;
- window = ply_list_node_get_data (node);
+ next_node = ply_list_get_next_node (state->pixel_displays, node);
+ display = ply_list_node_get_data (node);
+ ply_pixel_display_free (display);
- 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_window = has_open_window (state);
+ has_display = ply_list_get_length (state->pixel_displays) > 0 ||
+ ply_list_get_length (state->text_displays) > 0;
- 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,166 @@ 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)
+{
+ state->keyboard = keyboard;
+
+ 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_window_t *window;
+ ply_terminal_t *terminal;
+ ply_text_display_t *display;
+ ply_keyboard_t *keyboard;
- ply_trace ("creating window on %s", tty_name != NULL? tty_name : "active vt");
- window = ply_window_new (tty_name);
+ ply_trace ("adding display and keyboard for %s", tty_name);
- ply_window_attach_to_event_loop (window, state->loop);
+ terminal = ply_terminal_new (tty_name);
- return window;
+ if (!ply_terminal_open (terminal))
+ {
+ ply_trace ("could not open terminal '%s': %m", tty_name);
+ ply_terminal_free (terminal);
+ 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);
+
+ 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;
+ }
+
+ 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))
+ {
+ 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 +1064,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 +1083,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 +1268,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 +1303,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 +1340,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 +1348,27 @@ 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";
- ply_switch_to_vt (63);
+ state->default_tty = "tty63";
}
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;
}
@@ -1359,7 +1436,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,
@@ -1515,7 +1592,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;
@@ -1526,9 +1602,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)
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
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 <cairo.h>
#include <pango/pangocairo.h>
-#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;
+
+ 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;
+}
- return (long) ((double) height / PANGO_SCALE)+1;
+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)
+size_control (ply_label_plugin_control_t *label)
{
- ply_window_erase_area (label->window,
- label->area.x, label->area.y,
- label->area.width, label->area.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_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)
+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;
- ply_frame_buffer_pause_updates (label->frame_buffer);
- erase_label_area (label);
- cairo_move_to (label->cairo_context,
+ 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->is_hidden = true;
+ ply_pixel_display_draw_area (label->display,
+ label->area.x, label->area.y,
+ label->area.width, label->area.height);
- label->frame_buffer = NULL;
- label->window = NULL;
+ label->display = NULL;
label->loop = NULL;
-
- label->is_hidden = true;
}
bool
diff --git a/src/plugins/renderers/Makefile.am b/src/plugins/renderers/Makefile.am
new file mode 100644
index 00000000..2fadbf40
--- /dev/null
+++ b/src/plugins/renderers/Makefile.am
@@ -0,0 +1,2 @@
+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..da757c59
--- /dev/null
+++ b/src/plugins/renderers/drm/Makefile.am
@@ -0,0 +1,27 @@
+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 \
+ $(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-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
new file mode 100644
index 00000000..9047d79e
--- /dev/null
+++ b/src/plugins/renderers/drm/plugin.c
@@ -0,0 +1,1075 @@
+/* plugin.c - drm backend renderer plugin
+ *
+ * Copyright (C) 2006-2009 Red Hat, Inc.
+ * 2008 Charlie Brej <cbrej@cs.man.ac.uk>
+ *
+ * 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 <cbrej@cs.man.ac.uk>
+ * Kristian Høgsberg <krh@redhat.com>
+ * Peter Jones <pjones@redhat.com>
+ * Ray Strode <rstrode@redhat.com>
+ */
+#include "config.h"
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <values.h>
+#include <unistd.h>
+
+#include <drm/drm.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#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"
+#include "ply-renderer-i915-driver.h"
+#include "ply-renderer-radeon-driver.h"
+#include "ply-renderer-nouveau-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;
+ uint32_t driver_supports_mapping_console;
+
+ 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 (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);
+
+ 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);
+ }
+
+ /* 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;
+}
+
+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 <rstrode@redhat.com>
+ */
+#ifndef PLY_RENDERER_DRIVER_H
+#define PLY_RENDERER_DRIVER_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "ply-list.h"
+#include "ply-rectangle.h"
+#include "ply-utils.h"
+
+typedef struct _ply_renderer_driver ply_renderer_driver_t;
+
+typedef struct
+{
+ ply_renderer_driver_t * (* create_driver) (int device_fd);
+
+ void (* destroy_driver) (ply_renderer_driver_t *driver);
+
+ uint32_t (* create_buffer) (ply_renderer_driver_t *driver,
+ unsigned long width,
+ unsigned long height,
+ unsigned long *row_stride);
+ bool (* fetch_buffer) (ply_renderer_driver_t *driver,
+ uint32_t buffer_id,
+ unsigned long *width,
+ unsigned long *height,
+ unsigned long *row_stride);
+
+ bool (* map_buffer) (ply_renderer_driver_t *driver,
+ uint32_t buffer_id);
+
+ void (* unmap_buffer) (ply_renderer_driver_t *driver,
+ uint32_t buffer_id);
+
+ char * (* begin_flush) (ply_renderer_driver_t *driver,
+ uint32_t buffer_id);
+ void (* end_flush) (ply_renderer_driver_t *driver,
+ uint32_t buffer_id);
+
+ void (* destroy_buffer) (ply_renderer_driver_t *driver,
+ uint32_t buffer_id);
+
+} ply_renderer_driver_interface_t;
+
+#endif /* PLY_RENDERER_DRIVER_H */
+/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
diff --git a/src/plugins/renderers/drm/ply-renderer-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 <rstrode@redhat.com>
+ */
+#include "config.h"
+
+#include "ply-renderer-i915-driver.h"
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <values.h>
+#include <unistd.h>
+
+#include <drm/drm.h>
+#include <drm/i915_drm.h>
+#include <intel_bufmgr.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include "ply-hashtable.h"
+#include "ply-logger.h"
+#include "ply-renderer-driver.h"
+
+typedef struct _ply_renderer_buffer ply_renderer_buffer_t;
+
+struct _ply_renderer_buffer
+{
+ 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 <rstrode@redhat.com>
+ */
+#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 */
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 <rstrode@redhat.com>
+ */
+#include "config.h"
+
+#include "ply-renderer-nouveau-driver.h"
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <values.h>
+#include <unistd.h>
+
+#include <drm/drm.h>
+#include <drm/nouveau_drm.h>
+#include <drm/nouveau_drmif.h>
+#include <nouveau/nouveau_bo.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include "ply-hashtable.h"
+#include "ply-logger.h"
+#include "ply-renderer-driver.h"
+
+typedef struct _ply_renderer_buffer ply_renderer_buffer_t;
+
+struct _ply_renderer_buffer
+{
+ 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 <rstrode@redhat.com>
+ */
+#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 */
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 <rstrode@redhat.com>
+ */
+#include "config.h"
+
+#include "ply-renderer-radeon-driver.h"
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <values.h>
+#include <unistd.h>
+
+#include <drm/drm.h>
+#include <drm/radeon_drm.h>
+#include <drm/radeon_bo.h>
+#include <drm/radeon_bo_gem.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include "ply-hashtable.h"
+#include "ply-logger.h"
+#include "ply-renderer-driver.h"
+
+typedef struct _ply_renderer_buffer ply_renderer_buffer_t;
+
+struct _ply_renderer_buffer
+{
+ 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 <rstrode@redhat.com>
+ */
+#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 */
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 <cbrej@cs.man.ac.uk>
+ *
+ * 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 <cbrej@cs.man.ac.uk>
+ * Kristian Høgsberg <krh@redhat.com>
+ * Peter Jones <pjones@redhat.com>
+ * Ray Strode <rstrode@redhat.com>
+ */
+#include "config.h"
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <values.h>
+#include <unistd.h>
+
+#include <linux/fb.h>
+
+#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 */
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 <linux/kd.h>
@@ -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)
-{
- int fd;
- size_t size;
-
- ply_window_set_mode (window, PLY_WINDOW_MODE_TEXT);
-
- 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)
+static void
+add_text_display (ply_boot_splash_plugin_t *plugin,
+ ply_text_display_t *display)
{
-}
+ view_t *view;
-void
-on_backspace (ply_boot_splash_plugin_t *plugin)
-{
-}
+ view = view_new (plugin, display);
-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);
-
- 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);
-}
+ view = ply_list_node_get_data (node);
+ next_node = ply_list_get_next_node (plugin->views, node);
-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);
+ if (view->display == display)
+ {
+ ply_list_remove_node (plugin->views, node);
+ return;
+ }
+
+ 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));
+ write_on_views (plugin,
+ prompt,
+ 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; i<bullets; i++)
- for_each_window (plugin,
- (ply_boot_splash_plugin_window_handler_t)
- write_text_on_window,
- (void *) "*",
- (void *) strlen ("*"));
+ write_on_views (plugin,
+ "Password",
+ strlen ("Password"));
+
+ write_on_views (plugin, ":", strlen (":"));
+
+ for (i = 0; i < bullets; i++)
+ write_on_views (plugin, "*", strlen ("*"));
}
static void
@@ -362,37 +331,18 @@ display_question (ply_boot_splash_plugin_t *plugin,
const char *entry_text)
{
if (plugin->state != 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,
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 <linux/kd.h>
@@ -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,100 +415,95 @@ 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)
-{
- 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);
-}
-
-static void
-animate_at_time (ply_boot_splash_plugin_t *plugin,
- double time)
+view_animate_at_time (view_t *view,
+ double time)
{
+ ply_boot_splash_plugin_t *plugin;
ply_list_node_t *node;
- ply_frame_buffer_area_t logo_area, star_area;
+ double logo_opacity;
uint32_t *logo_data, *star_data;
- long width, height;
- static double last_opacity = 0.0;
- double opacity = 0.0;
+ long logo_x, logo_y;
+ long logo_width, logo_height;
+ unsigned long screen_width, screen_height;
+ unsigned long star_width, star_height;
- ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS);
+ plugin = view->plugin;
- 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_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);
- 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;
+
+ 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_area.width = ply_image_get_width (plugin->star_image);
- star_area.height = ply_image_get_height (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 (plugin->stars);
+ 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 (plugin->stars, 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);
+ next_node = ply_list_get_next_node (view->stars, node);
- draw_background (plugin, &star_area);
- ply_frame_buffer_fill_with_argb32_data_at_opacity (plugin->frame_buffer,
- &star_area, 0, 0,
- star_data, opacity);
+ 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;
}
- opacity = .5 * sin ((time / 5) * (2 * M_PI)) + .8;
- opacity = CLAMP (opacity, 0, 1.0);
+ 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)
- opacity = 1.0;
+ 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);
+}
- if (fabs (opacity - last_opacity) <= DBL_MIN)
+static void
+animate_at_time (ply_boot_splash_plugin_t *plugin,
+ double time)
+{
+ ply_list_node_t *node;
+
+ node = ply_list_get_first_node (plugin->views);
+ while (node != NULL)
{
- ply_frame_buffer_unpause_updates (plugin->frame_buffer);
- return;
- }
+ ply_list_node_t *next_node;
+ view_t *view;
- last_opacity = opacity;
+ view = ply_list_node_get_data (node);
+ next_node = ply_list_get_next_node (plugin->views, node);
- 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);
+ view_animate_at_time (view, time);
+
+ node = next_node;
+ }
}
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);
@@ -351,37 +580,40 @@ start_animation (ply_boot_splash_plugin_t *plugin)
}
static void
-stop_animation (ply_boot_splash_plugin_t *plugin)
+start_animation (ply_boot_splash_plugin_t *plugin)
{
- int i;
-
- assert (plugin != NULL);
- assert (plugin->loop != NULL);
+ ply_list_node_t *node;
- if (!plugin->is_animating)
+ if (plugin->is_animating)
return;
- plugin->is_animating = false;
-
- 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;
- ply_frame_buffer_fill_with_hex_color (plugin->frame_buffer, NULL,
- PLYMOUTH_BACKGROUND_COLOR);
+ view = ply_list_node_get_data (node);
+ next_node = ply_list_get_next_node (plugin->views, node);
- 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);
+ view_start_animation (view);
+
+ node = next_node;
}
- ply_frame_buffer_fill_with_color (plugin->frame_buffer, NULL,
- 0.0, 0.0, 0.0, 1.0);
+ plugin->is_animating = true;
+}
+
+static void
+stop_animation (ply_boot_splash_plugin_t *plugin)
+{
+ assert (plugin != NULL);
+ assert (plugin->loop != NULL);
+
+ if (!plugin->is_animating)
+ return;
+
+ plugin->is_animating = false;
if (plugin->loop != NULL)
{
@@ -389,6 +621,7 @@ stop_animation (ply_boot_splash_plugin_t *plugin)
(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;
+
+ plugin = view->plugin;
+
+ 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);
}
-void
-on_backspace (ply_boot_splash_plugin_t *plugin)
+static void
+draw_normal_view (view_t *view,
+ ply_pixel_buffer_t *pixel_buffer,
+ int x,
+ int y,
+ int width,
+ int height)
{
+ 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;
+
+ plugin = view->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);
}
-void
-on_enter (ply_boot_splash_plugin_t *plugin,
- const char *text)
+static void
+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;
+
+ 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);
}
-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;
+
+ plugin = view->plugin;
area.x = x;
area.y = y;
area.width = width;
area.height = height;
- draw_background (plugin, &area);
+ draw_background (view, pixel_buffer, x, y, width, height);
+
+ if (!plugin->is_animating)
+ return;
if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
- animate_at_time (plugin, plugin->now);
+ draw_normal_view (view, pixel_buffer, x, y, width, height);
else
- ply_entry_draw (plugin->entry);
+ draw_prompt_view (view, pixel_buffer, x, y, width, height);
}
-void
-on_erase (ply_boot_splash_plugin_t *plugin,
- int x,
- int y,
- int width,
- int height)
+static void
+add_pixel_display (ply_boot_splash_plugin_t *plugin,
+ ply_pixel_display_t *display)
{
- ply_frame_buffer_area_t area;
+ view_t *view;
- area.x = x;
- area.y = y;
- area.width = width;
- area.height = height;
+ view = view_new (plugin, display);
- ply_frame_buffer_fill_with_gradient (plugin->frame_buffer, &area,
- PLYMOUTH_BACKGROUND_START_COLOR,
- PLYMOUTH_BACKGROUND_END_COLOR);
+ 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_handlers (ply_boot_splash_plugin_t *plugin)
+remove_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);
-
- ply_window_set_draw_handler (plugin->window,
- (ply_window_draw_handler_t)
- on_draw, plugin);
+ ply_list_node_t *node;
- ply_window_set_erase_handler (plugin->window,
- (ply_window_erase_handler_t)
- on_erase, plugin);
-}
+ node = ply_list_get_first_node (plugin->views);
+ while (node != NULL)
+ {
+ view_t *view;
+ ply_list_node_t *next_node;
-static void
-remove_handlers (ply_boot_splash_plugin_t *plugin)
-{
+ view = ply_list_node_get_data (node);
+ next_node = ply_list_get_next_node (plugin->views, 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);
-}
+ if (view->display == display)
+ {
-static void
-add_window (ply_boot_splash_plugin_t *plugin,
- ply_window_t *window)
-{
- plugin->window = window;
-}
+ ply_pixel_display_set_draw_handler (view->display, NULL, NULL);
+ view_free (view);
+ ply_list_remove_node (plugin->views, node);
+ return;
+ }
-static void
-remove_window (ply_boot_splash_plugin_t *plugin,
- ply_window_t *window)
-{
- plugin->window = NULL;
+ 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);
+
+ plugin = view->plugin;
- ply_frame_buffer_get_size (plugin->frame_buffer, &area);
+ 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);
}
+}
+
+static void
+show_password_prompt (ply_boot_splash_plugin_t *plugin,
+ const char *text,
+ int number_of_bullets)
+{
+ 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;
- plugin->frame_buffer = NULL;
+ view = ply_list_node_get_data (node);
+ next_node = ply_list_get_next_node (plugin->views, node);
- ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT);
+ view_show_prompt (view, text);
+ ply_entry_set_bullet_count (view->entry, number_of_bullets);
+
+ node = next_node;
+ }
}
static void
-show_password_entry (ply_boot_splash_plugin_t *plugin)
+show_prompt (ply_boot_splash_plugin_t *plugin,
+ const char *prompt,
+ const char *entry_text)
{
- 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;
-
- assert (plugin != NULL);
+ ply_list_node_t *node;
- 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, prompt);
+ ply_entry_set_text (view->entry, entry_text);
- 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;
+ node = next_node;
+ }
+}
- x = area.width / 2.0 - (lock_area.width + entry_width) / 2.0 + lock_area.width;
- y = area.height / 2.0 - entry_height / 2.0;
+static void
+hide_prompt (ply_boot_splash_plugin_t *plugin)
+{
+ ply_list_node_t *node;
- 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);
- }
- else
+ 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_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,
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
+typedef struct
+{
+ ply_boot_splash_plugin_t *plugin;
+ ply_pixel_display_t *display;
+
+ script_state_t *script_state;
+ 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_frame_buffer_t *frame_buffer;
- ply_window_t *window;
+ ply_list_t *views;
char *script_filename;
char *image_dir;
- 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;
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);
-}
-
-static void
-on_backspace (ply_boot_splash_plugin_t *plugin)
-{}
+ /* 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);
-static void
-on_enter (ply_boot_splash_plugin_t *plugin,
- const char *text)
-{}
+ script_lib_plymouth_on_keyboard_input (view->script_state,
+ view->script_plymouth_lib,
+ keyboard_string);
+ }
+}
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)
-{}
+{
+ script_lib_sprite_draw_area (view->script_sprite_lib,
+ pixel_buffer,
+ x, y, width, height);
+}
static void
-on_erase (ply_boot_splash_plugin_t *plugin,
- int x,
- int y,
- int width,
- int height)
-{}
+set_keyboard (ply_boot_splash_plugin_t *plugin,
+ ply_keyboard_t *keyboard)
+{
-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);
+ ply_keyboard_add_input_handler (keyboard,
+ (ply_keyboard_input_handler_t)
+ on_keyboard_input, plugin);
}
static void
-remove_handlers (ply_boot_splash_plugin_t *plugin)
+unset_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_remove_input_handler (keyboard,
+ (ply_keyboard_input_handler_t)
+ on_keyboard_input);
}
static void
-add_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 = window;
+ 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_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 = NULL;
+ 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 */
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 <linux/kd.h>
#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; i<star_bg->star_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,28 +1190,27 @@ 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);
@@ -962,6 +1218,21 @@ start_animation (ply_boot_splash_plugin_t *plugin)
}
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)
{
ply_list_node_t *node;
@@ -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,58 +1419,55 @@ 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);
-
- 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);
-}
+ view_t *view;
-static void
-remove_handlers (ply_boot_splash_plugin_t *plugin)
-{
+ view = view_new (plugin, display);
- 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);
-}
+ ply_pixel_display_set_draw_handler (view->display,
+ (ply_pixel_display_draw_handler_t)
+ on_draw, view);
-static void
-add_window (ply_boot_splash_plugin_t *plugin,
- ply_window_t *window)
-{
- plugin->window = window;
+ ply_list_append_data (plugin->views, view);
}
static void
-remove_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 = NULL;
+ 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;
+ }
}
+
void highlight_image (ply_image_t *highlighted_image, ply_image_t *orig_image, int distance)
{
int x, y;
@@ -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; i<star_bg->star_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; i<star_bg->star_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; x<COMET_SIZE; x++) satellite_move (plugin, sprite, 0);
}
#endif
@@ -1354,18 +1630,18 @@ setup_scene (ply_boot_splash_plugin_t *plugin)
progress->image = 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;
-
- uint32_t *box_data, *lock_data;
-
- assert (plugin != NULL);
+ ply_list_node_t *node;
- 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);
+ node = next_node;
+ }
+}
- ply_entry_show (plugin->entry, plugin->loop, plugin->window, x, y);
+static void
+show_prompt (ply_boot_splash_plugin_t *plugin,
+ const char *prompt,
+ const char *entry_text)
+{
+ ply_list_node_t *node;
- 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);
- }
- else
+ 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;
}
-
}
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,
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 <linux/kd.h>
#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;
}
@@ -102,6 +337,31 @@ detach_from_event_loop (ply_boot_splash_plugin_t *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)
{
ply_trace ("destroying 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;
+
+ node = ply_list_get_first_node (plugin->views);
+ while (node != NULL)
+ {
+ ply_list_node_t *next_node;
+ view_t *view;
- window_width = ply_window_get_number_of_text_columns (plugin->window);
- window_height = ply_window_get_number_of_text_rows (plugin->window);
+ view = ply_list_node_get_data (node);
+ next_node = ply_list_get_next_node (plugin->views, node);
- 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_show_message (view);
- write (STDOUT_FILENO, plugin->message, strlen (plugin->message));
+ 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;
+
+ 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);
- ply_text_progress_bar_hide (plugin->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;
-static void
-add_handlers (ply_boot_splash_plugin_t *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);
+ 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
-remove_handlers (ply_boot_splash_plugin_t *plugin)
+remove_text_display (ply_boot_splash_plugin_t *plugin,
+ ply_text_display_t *display)
{
+ ply_list_node_t *node;
- 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);
-static void
-add_window (ply_boot_splash_plugin_t *plugin,
- ply_window_t *window)
-{
- plugin->window = window;
-}
+ 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
-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
@@ -362,39 +648,75 @@ display_message (ply_boot_splash_plugin_t *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);
-
- 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);
+ pause_views (plugin);
+ if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
+ stop_animation (plugin);
+
+ 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,35 +724,20 @@ 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);
-
- 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);
-}
+ pause_views (plugin);
+ if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
+ stop_animation (plugin);
+
+ 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,
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 <linux/kd.h>
-
#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;
+
+ area.x = x;
+ area.y = y;
+ area.width = width;
+ area.height = height;
- ply_window_erase_area (plugin->window, area->x, area->y,
- area->width, area->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;
-
- 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,
+ 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_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;
- ply_frame_buffer_fill_with_hex_color (plugin->frame_buffer, NULL,
- PLYMOUTH_BACKGROUND_COLOR);
+ view = ply_list_node_get_data (node);
+ next_node = ply_list_get_next_node (plugin->views, node);
- 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_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_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;
+
+ draw_background (view, pixel_buffer, x, y, width, height);
- if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY ||
+ 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)
+static void
+add_pixel_display (ply_boot_splash_plugin_t *plugin,
+ ply_pixel_display_t *display)
{
- ply_frame_buffer_area_t area;
+ view_t *view;
- area.x = x;
- area.y = y;
- area.width = width;
- area.height = height;
+ view = view_new (plugin, display);
- ply_frame_buffer_fill_with_gradient (plugin->frame_buffer, &area,
- PLYMOUTH_BACKGROUND_START_COLOR,
- PLYMOUTH_BACKGROUND_END_COLOR);
+ 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_handlers (ply_boot_splash_plugin_t *plugin)
+remove_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);
+ ply_list_node_t *node;
- 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);
-}
+ node = ply_list_get_first_node (plugin->views);
+ while (node != NULL)
+ {
+ view_t *view;
+ ply_list_node_t *next_node;
-static void
-remove_handlers (ply_boot_splash_plugin_t *plugin)
-{
+ view = ply_list_node_get_data (node);
+ next_node = ply_list_get_next_node (plugin->views, 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);
-}
+ if (view->display == display)
+ {
-static void
-add_window (ply_boot_splash_plugin_t *plugin,
- ply_window_t *window)
-{
- plugin->window = window;
-}
+ ply_pixel_display_set_draw_handler (view->display, NULL, NULL);
+ view_free (view);
+ ply_list_remove_node (plugin->views, node);
+ return;
+ }
-static void
-remove_window (ply_boot_splash_plugin_t *plugin,
- ply_window_t *window)
-{
- plugin->window = NULL;
+ 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_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;
+ ply_list_node_t *next_node;
+ view_t *view;
- plugin->lock_area.width = ply_image_get_width (plugin->lock_image);
- plugin->lock_area.height = ply_image_get_height (plugin->lock_image);
+ 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);
- 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);
+ node = next_node;
+ }
+}
- ply_entry_show (plugin->entry, plugin->loop, plugin->window, x, y);
+static void
+show_prompt (ply_boot_splash_plugin_t *plugin,
+ const char *prompt,
+ const char *entry_text)
+{
+ ply_list_node_t *node;
- 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);
- }
- else
- {
- ply_entry_draw (plugin->entry);
- }
- if (prompt != NULL)
+ node = ply_list_get_first_node (plugin->views);
+ while (node != 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;
}
-
}
static void
@@ -586,14 +796,37 @@ become_idle (ply_boot_splash_plugin_t *plugin,
}
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,
diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c
index 7b70202b..435031e2 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,286 @@ 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,
+ 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 +421,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 +437,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 +475,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 +527,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;
- ply_window_erase_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);
-static void
-begin_animation (ply_boot_splash_plugin_t *plugin,
- ply_trigger_t *trigger)
-{
- 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);
+ ply_progress_animation_hide (view->progress_animation);
+ ply_trigger_ignore_next_pull (trigger);
+ view_start_end_animation (view, trigger);
+
+ node = next_node;
+ }
+ ply_trigger_pull (trigger, NULL);
}
static void
-start_animation (ply_boot_splash_plugin_t *plugin)
+start_progress_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;
- 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);
- 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);
+ view_start_progress_animation (view);
- plugin->is_animating = true;
+ node = next_node;
+ }
- ply_window_draw_area (plugin->window, 0, 0, area.width, area.height);
+ plugin->is_animating = true;
}
static void
stop_animation (ply_boot_splash_plugin_t *plugin)
{
+ ply_list_node_t *node;
+
assert (plugin != NULL);
assert (plugin->loop != NULL);
@@ -314,29 +595,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;
- ply_frame_buffer_fill_with_hex_color (plugin->frame_buffer, NULL,
- PLYMOUTH_BACKGROUND_COLOR);
+ view = ply_list_node_get_data (node);
+ next_node = ply_list_get_next_node (plugin->views, node);
- 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_progress_animation_hide (view->progress_animation);
+ ply_animation_stop (view->end_animation);
- ply_frame_buffer_fill_with_color (plugin->frame_buffer, NULL,
- 0.0, 0.0, 0.0, 1.0);
-#endif
+ node = next_node;
+ }
}
static void
@@ -344,7 +616,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,138 +624,144 @@ 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)
-{
-}
+ plugin = view->plugin;
-void
-on_enter (ply_boot_splash_plugin_t *plugin,
- const char *text)
-{
+ area.x = x;
+ area.y = y;
+ area.width = width;
+ area.height = height;
+
+ if (plugin->background_start_color != plugin->background_end_color)
+ ply_pixel_buffer_fill_with_gradient (pixel_buffer, &area,
+ plugin->background_start_color,
+ plugin->background_end_color);
+ else
+ ply_pixel_buffer_fill_with_hex_color (pixel_buffer, &area,
+ plugin->background_start_color);
}
-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;
+
+ 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
{
- ply_progress_animation_draw (plugin->progress_animation);
+ 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_frame_buffer_area_t screen_area;
- ply_frame_buffer_area_t image_area;
+ ply_rectangle_t screen_area;
+ ply_rectangle_t image_area;
- ply_frame_buffer_get_size (plugin->frame_buffer, &screen_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_frame_buffer_fill_with_argb32_data (plugin->frame_buffer, &image_area, 0, 0, ply_image_get_data (plugin->corner_image));
+ ply_pixel_buffer_fill_with_argb32_data (pixel_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)
+static void
+add_pixel_display (ply_boot_splash_plugin_t *plugin,
+ ply_pixel_display_t *display)
{
- ply_frame_buffer_area_t area;
+ view_t *view;
- area.x = x;
- area.y = y;
- area.width = width;
- area.height = height;
+ view = view_new (plugin, display);
- if (plugin->background_start_color != plugin->background_end_color)
- ply_frame_buffer_fill_with_gradient (plugin->frame_buffer, &area,
- plugin->background_start_color,
- plugin->background_end_color);
- else
- ply_frame_buffer_fill_with_hex_color (plugin->frame_buffer, &area,
- plugin->background_start_color);
+ 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_handlers (ply_boot_splash_plugin_t *plugin)
+remove_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);
+ ply_list_node_t *node;
- 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);
-}
+ node = ply_list_get_first_node (plugin->views);
+ while (node != NULL)
+ {
+ view_t *view;
+ ply_list_node_t *next_node;
-static void
-remove_handlers (ply_boot_splash_plugin_t *plugin)
-{
+ view = ply_list_node_get_data (node);
+ next_node = ply_list_get_next_node (plugin->views, 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);
-}
+ if (view->display == display)
+ {
-static void
-add_window (ply_boot_splash_plugin_t *plugin,
- ply_window_t *window)
-{
- plugin->window = window;
-}
+ ply_pixel_display_set_draw_handler (view->display, NULL, NULL);
+ view_free (view);
+ ply_list_remove_node (plugin->views, node);
+ return;
+ }
-static void
-remove_window (ply_boot_splash_plugin_t *plugin,
- ply_window_t *window)
-{
- plugin->window = NULL;
+ node = next_node;
+ }
}
static bool
@@ -495,19 +772,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 +794,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 +809,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;
@@ -584,6 +836,28 @@ on_animation_stopped (ply_boot_splash_plugin_t *plugin)
}
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,
double percent_done)
@@ -592,15 +866,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 +887,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 +897,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 +907,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;
-
- uint32_t *box_data, *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_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;
+ ply_list_node_t *next_node;
+ view_t *view;
- plugin->lock_area.width = ply_image_get_width (plugin->lock_image);
- plugin->lock_area.height = ply_image_get_height (plugin->lock_image);
+ 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);
- 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);
+ node = next_node;
+ }
+}
- ply_entry_show (plugin->entry, plugin->loop, plugin->window, x, y);
+static void
+show_prompt (ply_boot_splash_plugin_t *plugin,
+ const char *prompt,
+ const char *entry_text)
+{
+ ply_list_node_t *node;
- 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);
- }
- else
- {
- ply_entry_draw (plugin->entry);
- }
- if (prompt != NULL)
+ node = ply_list_get_first_node (plugin->views);
+ while (node != 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 +974,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 +1025,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 +1040,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 +1057,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 +1073,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 */
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-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
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