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. */
}
}
+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)
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;
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. */
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;
static grub_err_t
doublebuf_blit_update_screen (void)
{
- grub_memcpy ((void *) framebuffer.pages[0], framebuffer.back_target->data,
- framebuffer.back_target->mode_info.pitch
- * framebuffer.back_target->mode_info.height);
+ 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.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;
}
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;
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;
}
{
int new_displayed_page;
grub_err_t err;
-
- grub_memcpy ((void *) framebuffer.pages[framebuffer.render_page],
- framebuffer.back_target->data,
- framebuffer.back_target->mode_info.pitch
- * framebuffer.back_target->mode_info.height);
+ int first_line, last_line;
+
+ 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
+ * (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;
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)
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;