2009-11-30 Vladimir Serbinenko <phcoder@gmail.com>

Agglomerate scrolling in gfxterm.

	* term/gfxterm.c (grub_virtual_screen): New member 'total_screen'.
	(grub_virtual_screen_setup): Initialise 'total_screen'.
	(write_char): Split to ...
	(paint_char): ... this ...
	(write_char): ... and this.
	(paint_char): Handle delayed scrolling.
	(draw_cursor): Likewise.
	(scroll_up): Split to ...
	(real_scroll): ... this ...
	(scroll_up): ... and this.
	(real_scroll): Handle multi-line scroll and draw below-the-bottom
	characters.
	(grub_gfxterm_refresh): Call real_scroll.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2009-11-30 13:16:35 +01:00
commit d9b091d9ff
2 changed files with 116 additions and 59 deletions

18
ChangeLog.gfxtermscroll Normal file
View file

@ -0,0 +1,18 @@
2009-11-30 Vladimir Serbinenko <phcoder@gmail.com>
Agglomerate scrolling in gfxterm.
* term/gfxterm.c (grub_virtual_screen): New member 'total_screen'.
(grub_virtual_screen_setup): Initialise 'total_screen'.
(write_char): Split to ...
(paint_char): ... this ...
(write_char): ... and this.
(paint_char): Handle delayed scrolling.
(draw_cursor): Likewise.
(scroll_up): Split to ...
(real_scroll): ... this ...
(scroll_up): ... and this.
(real_scroll): Handle multi-line scroll and draw below-the-bottom
characters.
(grub_gfxterm_refresh): Call real_scroll.

View file

@ -102,6 +102,8 @@ struct grub_virtual_screen
/* Text buffer for virtual screen. Contains (columns * rows) number /* Text buffer for virtual screen. Contains (columns * rows) number
of entries. */ of entries. */
struct grub_colored_char *text_buffer; struct grub_colored_char *text_buffer;
int total_scroll;
}; };
struct grub_gfxterm_window struct grub_gfxterm_window
@ -225,6 +227,7 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y,
virtual_screen.cursor_x = 0; virtual_screen.cursor_x = 0;
virtual_screen.cursor_y = 0; virtual_screen.cursor_y = 0;
virtual_screen.cursor_state = 1; virtual_screen.cursor_state = 1;
virtual_screen.total_scroll = 0;
/* Calculate size of text buffer. */ /* Calculate size of text buffer. */
virtual_screen.columns = virtual_screen.width / virtual_screen.normal_char_width; virtual_screen.columns = virtual_screen.width / virtual_screen.normal_char_width;
@ -586,8 +589,8 @@ dirty_region_redraw (void)
redraw_screen_rect (x, y, width, height); redraw_screen_rect (x, y, width, height);
} }
static void static inline void
write_char (void) paint_char (unsigned cx, unsigned cy)
{ {
struct grub_colored_char *p; struct grub_colored_char *p;
struct grub_font_glyph *glyph; struct grub_font_glyph *glyph;
@ -599,10 +602,12 @@ write_char (void)
unsigned int height; unsigned int height;
unsigned int width; unsigned int width;
if (cy + virtual_screen.total_scroll >= virtual_screen.rows)
return;
/* Find out active character. */ /* Find out active character. */
p = (virtual_screen.text_buffer p = (virtual_screen.text_buffer
+ virtual_screen.cursor_x + cx + (cy * virtual_screen.columns));
+ (virtual_screen.cursor_y * virtual_screen.columns));
p -= p->index; p -= p->index;
@ -616,8 +621,8 @@ write_char (void)
color = p->fg_color; color = p->fg_color;
bgcolor = p->bg_color; bgcolor = p->bg_color;
x = virtual_screen.cursor_x * virtual_screen.normal_char_width; x = cx * virtual_screen.normal_char_width;
y = virtual_screen.cursor_y * virtual_screen.normal_char_height; y = (cy + virtual_screen.total_scroll) * virtual_screen.normal_char_height;
/* Render glyph to text layer. */ /* Render glyph to text layer. */
grub_video_set_active_render_target (text_layer); grub_video_set_active_render_target (text_layer);
@ -630,64 +635,58 @@ write_char (void)
width, height); width, height);
} }
static void static inline void
write_char (void)
{
paint_char (virtual_screen.cursor_x, virtual_screen.cursor_y);
}
static inline void
draw_cursor (int show) draw_cursor (int show)
{ {
unsigned int x;
unsigned int y;
unsigned int width;
unsigned int height;
grub_video_color_t color;
write_char (); write_char ();
if (show) if (!show)
{ return;
unsigned int x;
unsigned int y;
unsigned int width;
unsigned int height;
grub_video_color_t color;
/* Determine cursor properties and position on text layer. */ if (virtual_screen.cursor_y + virtual_screen.total_scroll
x = virtual_screen.cursor_x * virtual_screen.normal_char_width; >= virtual_screen.rows)
width = virtual_screen.normal_char_width; return;
color = virtual_screen.fg_color;
y = (virtual_screen.cursor_y * virtual_screen.normal_char_height
+ grub_font_get_ascent (virtual_screen.font));
height = 2;
/* Render cursor to text layer. */ /* Determine cursor properties and position on text layer. */
grub_video_set_active_render_target (text_layer); x = virtual_screen.cursor_x * virtual_screen.normal_char_width;
grub_video_fill_rect (color, x, y, width, height); width = virtual_screen.normal_char_width;
grub_video_set_active_render_target (render_target); color = virtual_screen.fg_color;
y = ((virtual_screen.cursor_y + virtual_screen.total_scroll)
* virtual_screen.normal_char_height
+ grub_font_get_ascent (virtual_screen.font));
height = 2;
/* Mark cursor to be redrawn. */ /* Render cursor to text layer. */
dirty_region_add (virtual_screen.offset_x + x, grub_video_set_active_render_target (text_layer);
virtual_screen.offset_y + y, grub_video_fill_rect (color, x, y, width, height);
width, height); grub_video_set_active_render_target (render_target);
}
/* Mark cursor to be redrawn. */
dirty_region_add (virtual_screen.offset_x + x,
virtual_screen.offset_y + y,
width, height);
} }
static void static void
scroll_up (void) real_scroll (void)
{ {
unsigned int i; unsigned int i, j, was_scroll;
grub_video_color_t color; grub_video_color_t color;
/* If we don't have background bitmap, remove cursor. */ if (!virtual_screen.total_scroll)
if (!bitmap) return;
{
/* Remove cursor. */
draw_cursor (0);
}
/* Scroll text buffer with one line to up. */
grub_memmove (virtual_screen.text_buffer,
virtual_screen.text_buffer + virtual_screen.columns,
sizeof (*virtual_screen.text_buffer)
* virtual_screen.columns
* (virtual_screen.rows - 1));
/* Clear last line in text buffer. */
for (i = virtual_screen.columns * (virtual_screen.rows - 1);
i < virtual_screen.columns * virtual_screen.rows;
i++)
clear_char (&(virtual_screen.text_buffer[i]));
/* If we have bitmap, re-draw screen, otherwise scroll physical screen too. */ /* If we have bitmap, re-draw screen, otherwise scroll physical screen too. */
if (bitmap) if (bitmap)
@ -695,7 +694,8 @@ scroll_up (void)
/* Scroll physical screen. */ /* Scroll physical screen. */
grub_video_set_active_render_target (text_layer); grub_video_set_active_render_target (text_layer);
color = virtual_screen.bg_color; color = virtual_screen.bg_color;
grub_video_scroll (color, 0, -virtual_screen.normal_char_height); grub_video_scroll (color, 0, -virtual_screen.normal_char_height
* virtual_screen.total_scroll);
/* Mark virtual screen to be redrawn. */ /* Mark virtual screen to be redrawn. */
dirty_region_add_virtualscreen (); dirty_region_add_virtualscreen ();
@ -704,6 +704,9 @@ scroll_up (void)
{ {
grub_video_rect_t saved_view; grub_video_rect_t saved_view;
/* Remove cursor. */
draw_cursor (0);
grub_video_set_active_render_target (render_target); grub_video_set_active_render_target (render_target);
/* Save viewport and set it to our window. */ /* Save viewport and set it to our window. */
grub_video_get_viewport ((unsigned *) &saved_view.x, grub_video_get_viewport ((unsigned *) &saved_view.x,
@ -723,13 +726,15 @@ scroll_up (void)
virtual_screen.offset_x, virtual_screen.offset_x,
virtual_screen.offset_y, virtual_screen.offset_y,
virtual_screen.width, virtual_screen.width,
virtual_screen.normal_char_height); virtual_screen.normal_char_height
* virtual_screen.total_scroll);
grub_video_set_active_render_target (render_target); grub_video_set_active_render_target (render_target);
dirty_region_redraw (); dirty_region_redraw ();
/* Scroll physical screen. */ /* Scroll physical screen. */
grub_video_scroll (color, 0, -virtual_screen.normal_char_height); grub_video_scroll (color, 0, -virtual_screen.normal_char_height
* virtual_screen.total_scroll);
if (i) if (i)
grub_video_swap_buffers (); grub_video_swap_buffers ();
@ -739,22 +744,54 @@ scroll_up (void)
/* Scroll physical screen. */ /* Scroll physical screen. */
grub_video_set_active_render_target (text_layer); grub_video_set_active_render_target (text_layer);
color = virtual_screen.bg_color; color = virtual_screen.bg_color;
grub_video_scroll (color, 0, -virtual_screen.normal_char_height); grub_video_scroll (color, 0, -virtual_screen.normal_char_height
* virtual_screen.total_scroll);
/* Restore saved viewport. */ /* Restore saved viewport. */
grub_video_set_viewport (saved_view.x, saved_view.y, grub_video_set_viewport (saved_view.x, saved_view.y,
saved_view.width, saved_view.height); saved_view.width, saved_view.height);
grub_video_set_active_render_target (render_target); grub_video_set_active_render_target (render_target);
/* Draw cursor if visible. */
if (virtual_screen.cursor_state)
draw_cursor (1);
} }
/* Draw cursor if visible. */
if (virtual_screen.cursor_state)
draw_cursor (1);
was_scroll = virtual_screen.total_scroll;
virtual_screen.total_scroll = 0;
/* Draw shadow part. */
for (i = virtual_screen.rows - was_scroll;
i < virtual_screen.rows; i++)
for (j = 0; j < virtual_screen.columns; j++)
paint_char (j, i);
if (repaint_callback) if (repaint_callback)
repaint_callback (window.x, window.y, window.width, window.height); repaint_callback (window.x, window.y, window.width, window.height);
} }
static void
scroll_up (void)
{
unsigned int i;
/* Scroll text buffer with one line to up. */
grub_memmove (virtual_screen.text_buffer,
virtual_screen.text_buffer + virtual_screen.columns,
sizeof (*virtual_screen.text_buffer)
* virtual_screen.columns
* (virtual_screen.rows - 1));
/* Clear last line in text buffer. */
for (i = virtual_screen.columns * (virtual_screen.rows - 1);
i < virtual_screen.columns * virtual_screen.rows;
i++)
clear_char (&(virtual_screen.text_buffer[i]));
virtual_screen.total_scroll++;
}
static void static void
grub_gfxterm_putchar (grub_uint32_t c) grub_gfxterm_putchar (grub_uint32_t c)
{ {
@ -1023,6 +1060,8 @@ grub_gfxterm_setcursor (int on)
static void static void
grub_gfxterm_refresh (void) grub_gfxterm_refresh (void)
{ {
real_scroll ();
/* Redraw only changed regions. */ /* Redraw only changed regions. */
dirty_region_redraw (); dirty_region_redraw ();