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:
parent
e169a1805f
commit
52f0f64384
2 changed files with 92 additions and 8 deletions
16
ChangeLog
16
ChangeLog
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue