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 12:51:20 +01:00
parent 9ec25583a9
commit af20edb21d
1 changed files with 98 additions and 59 deletions

View File

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