Avoid unnecessary memcpy of whole video buffer.

* grub-core/video/fb/video_fb.c (dirty): New struct.
	(framebuffer): Add members current_dirty and previous_dirty.
	(dirty): New function.
	(grub_video_fb_fill_rect): Update dirty.
	(common_blitter): Likewise.
	(grub_video_fb_scroll): Likewise.
	(doublebuf_blit_update_screen): Copy only dirty part.
	(doublebuf_pageflipping_update_screen): Likewise.
	(grub_video_fb_doublebuf_blit_init): Init dirty.
	(doublebuf_pageflipping_init): Likewise.
	(grub_video_fb_setup): Likewise.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2012-06-19 19:34:51 +02:00
parent e169a1805f
commit 52f0f64384
2 changed files with 92 additions and 8 deletions

View file

@ -1,3 +1,19 @@
2012-06-19 Vladimir Serbinenko <phcoder@gmail.com>
Avoid unnecessary memcpy of whole video buffer.
* grub-core/video/fb/video_fb.c (dirty): New struct.
(framebuffer): Add members current_dirty and previous_dirty.
(dirty): New function.
(grub_video_fb_fill_rect): Update dirty.
(common_blitter): Likewise.
(grub_video_fb_scroll): Likewise.
(doublebuf_blit_update_screen): Copy only dirty part.
(doublebuf_pageflipping_update_screen): Likewise.
(grub_video_fb_doublebuf_blit_init): Init dirty.
(doublebuf_pageflipping_init): Likewise.
(grub_video_fb_setup): Likewise.
2012-06-19 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/net/drivers/ieee1275/ofnet.c (search_net_devices): Decrease

View file

@ -31,13 +31,24 @@ GRUB_MOD_LICENSE ("GPLv3+");
typedef grub_err_t (*grub_video_fb_doublebuf_update_screen_t) (void);
typedef volatile void *framebuf_t;
struct dirty
{
int first_line;
int last_line;
};
static struct
{
struct grub_video_fbrender_target *render_target;
struct grub_video_fbrender_target *back_target;
struct grub_video_palette_data *palette;
framebuf_t pages[2];
unsigned int palette_size;
struct dirty current_dirty;
struct dirty previous_dirty;
/* For page flipping strategy. */
int displayed_page; /* The page # that is the front buffer. */
int render_page; /* The page # that is the back buffer. */
@ -424,6 +435,17 @@ grub_video_fb_unmap_color_int (struct grub_video_fbblit_info * source,
}
}
static void
dirty (int y, int height)
{
if (framebuffer.render_target != framebuffer.back_target)
return;
if (framebuffer.current_dirty.first_line > y)
framebuffer.current_dirty.first_line = y;
if (framebuffer.current_dirty.last_line < y + height)
framebuffer.current_dirty.last_line = y + height;
}
grub_err_t
grub_video_fb_fill_rect (grub_video_color_t color, int x, int y,
unsigned int width, unsigned int height)
@ -457,6 +479,8 @@ grub_video_fb_fill_rect (grub_video_color_t color, int x, int y,
x += framebuffer.render_target->viewport.x;
y += framebuffer.render_target->viewport.y;
dirty (y, height);
/* Use fbblit_info to encapsulate rendering. */
target.mode_info = &framebuffer.render_target->mode_info;
target.data = framebuffer.render_target->data;
@ -515,6 +539,8 @@ common_blitter (struct grub_video_fbblit_info *target,
unsigned int width, unsigned int height,
int offset_x, int offset_y)
{
dirty (y, height);
if (oper == GRUB_VIDEO_BLIT_REPLACE)
{
/* Try to figure out more optimized version for replace operator. */
@ -977,6 +1003,9 @@ grub_video_fb_scroll (grub_video_color_t color, int dx, int dy)
width = framebuffer.render_target->viewport.width - grub_abs (dx);
height = framebuffer.render_target->viewport.height - grub_abs (dy);
dirty (framebuffer.render_target->viewport.y,
framebuffer.render_target->viewport.height);
if (dx < 0)
{
src_x = framebuffer.render_target->viewport.x - dx;
@ -1286,9 +1315,21 @@ grub_video_fb_get_active_render_target (struct grub_video_fbrender_target **targ
static grub_err_t
doublebuf_blit_update_screen (void)
{
grub_memcpy ((void *) framebuffer.pages[0], framebuffer.back_target->data,
if (framebuffer.current_dirty.first_line
<= framebuffer.current_dirty.last_line)
grub_memcpy ((char *) framebuffer.pages[0]
+ framebuffer.current_dirty.first_line
* framebuffer.back_target->mode_info.pitch,
(char *) framebuffer.back_target->data
+ framebuffer.current_dirty.first_line
* framebuffer.back_target->mode_info.pitch,
framebuffer.back_target->mode_info.pitch
* framebuffer.back_target->mode_info.height);
* (framebuffer.current_dirty.last_line
- framebuffer.current_dirty.first_line));
framebuffer.current_dirty.first_line
= framebuffer.back_target->mode_info.height;
framebuffer.current_dirty.last_line = 0;
return GRUB_ERR_NONE;
}
@ -1300,7 +1341,7 @@ grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **back,
grub_err_t err;
grub_size_t page_size = mode_info.pitch * mode_info.height;
framebuffer.offscreen_buffer = grub_malloc (page_size);
framebuffer.offscreen_buffer = grub_zalloc (page_size);
if (! framebuffer.offscreen_buffer)
return grub_errno;
@ -1320,6 +1361,8 @@ grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **back,
framebuffer.pages[0] = framebuf;
framebuffer.displayed_page = 0;
framebuffer.render_page = 0;
framebuffer.current_dirty.first_line = mode_info.height;
framebuffer.current_dirty.last_line = 0;
return GRUB_ERR_NONE;
}
@ -1329,11 +1372,26 @@ doublebuf_pageflipping_update_screen (void)
{
int new_displayed_page;
grub_err_t err;
int first_line, last_line;
grub_memcpy ((void *) framebuffer.pages[framebuffer.render_page],
framebuffer.back_target->data,
first_line = framebuffer.current_dirty.first_line;
last_line = framebuffer.current_dirty.last_line;
if (first_line > framebuffer.previous_dirty.first_line)
first_line = framebuffer.previous_dirty.first_line;
if (last_line < framebuffer.previous_dirty.last_line)
last_line = framebuffer.previous_dirty.last_line;
if (first_line <= last_line)
grub_memcpy ((char *) framebuffer.pages[framebuffer.render_page]
+ first_line * framebuffer.back_target->mode_info.pitch,
(char *) framebuffer.back_target->data
+ first_line * framebuffer.back_target->mode_info.pitch,
framebuffer.back_target->mode_info.pitch
* framebuffer.back_target->mode_info.height);
* (last_line - first_line));
framebuffer.previous_dirty = framebuffer.current_dirty;
framebuffer.current_dirty.first_line
= framebuffer.back_target->mode_info.height;
framebuffer.current_dirty.last_line = 0;
/* Swap the page numbers in the framebuffer struct. */
new_displayed_page = framebuffer.render_page;
@ -1386,6 +1444,13 @@ doublebuf_pageflipping_init (struct grub_video_mode_info *mode_info,
framebuffer.pages[0] = page0_ptr;
framebuffer.pages[1] = page1_ptr;
framebuffer.current_dirty.first_line
= framebuffer.back_target->mode_info.height;
framebuffer.current_dirty.last_line = 0;
framebuffer.previous_dirty.first_line
= framebuffer.back_target->mode_info.height;
framebuffer.previous_dirty.last_line = 0;
/* Set the framebuffer memory data pointer and display the right page. */
err = set_page_in (framebuffer.displayed_page);
if (err)
@ -1470,6 +1535,9 @@ grub_video_fb_setup (unsigned int mode_type, unsigned int mode_mask,
framebuffer.displayed_page = 0;
framebuffer.render_page = 0;
framebuffer.set_page = 0;
framebuffer.current_dirty.first_line
= framebuffer.back_target->mode_info.height;
framebuffer.current_dirty.last_line = 0;
mode_info->mode_type &= ~GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;