diff --git a/ChangeLog b/ChangeLog index 122283726..f8a014880 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +2013-11-08 Vladimir Testov + + * grub-core/gfxmenu/gui_box.c: Updated to work with area status. + * grub-core/gfxmenu/gui_canvas.c: Likewise. + * grub-core/gfxmenu/view.c: Likewise. + * grub-core/video/fb/video_fb.c: Introduce new functions: + grub_video_set_area_status, grub_video_get_area_status, + grub_video_set_region, grub_video_get_region. + * grub-core/video/bochs.c: Likewise. + * grub-core/video/capture.c: Likewise. + * grub-core/video/video.c: Likewise. + * grub-core/video/cirrus.c: Likewise. + * grub-core/video/efi_gop.c: Likewise. + * grub-core/video/efi_uga.c: Likewise. + * grub-core/video/emu/sdl.c: Likewise. + * grub-core/video/radeon_fuloong2e.c: Likewise. + * grub-core/video/sis315pro.c: Likewise. + * grub-core/video/sm712.c: Likewise. + * grub-core/video/i386/pc/vbe.c: Likewise. + * grub-core/video/i386/pc/vga.c: Likewise. + * grub-core/video/ieee1275.c: Likewise. + * grub-core/video/i386/coreboot/cbfb.c: Likewise. + * include/grub/video.h: Likewise. + * include/grub/video_fb.h: Likewise. + * include/grub/fbfill.h: Updated render_target structure. + grub_video_rect_t viewport, region, area + int area_offset_x, area_offset_y, area_enabled + * include/grub/gui.h: New helper function + grub_video_bounds_inside_region. + * docs/grub-dev.texi: Added information about new functions. + 2013-11-08 Vladimir Serbinenko * grub-core/kern/mm.c (grub_real_malloc): Use AND rather than MOD diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi index 9499f8bc4..6caec7896 100644 --- a/docs/grub-dev.texi +++ b/docs/grub-dev.texi @@ -1113,6 +1113,47 @@ struct grub_video_palette_data Used to query indexed color palettes. If mode is RGB mode, colors will be copied from emulated palette data. In Indexed Color modes, palettes will be read from hardware. Color values will be converted to suit structure format. @code{start} will tell what hardware color index (or emulated color index) will be used as a source for first indice of @code{palette_data}, after that both hardware color index and @code{palette_data} index will be incremented until @code{count} number of colors have been read. @end itemize +@subsection grub_video_set_area_status +@itemize + +@item Prototype: +@example +grub_err_t +grub_video_set_area_status (grub_video_area_status_t area_status); +@end example +@example +enum grub_video_area_status_t + @{ + GRUB_VIDEO_AREA_DISABLED, + GRUB_VIDEO_AREA_ENABLED + @}; +@end example + +@item Description: + +Used to set area drawing mode for redrawing the specified region. Draw commands +are performed in the intersection of the viewport and the region called area. +Coordinates remain related to the viewport. If draw commands try to draw over +the area, they are clipped. +Set status to DISABLED if you need to draw everything. +Set status to ENABLED and region to the desired rectangle to redraw everything +inside the region leaving everything else intact. +Should be used for redrawing of active elements. +@end itemize + +@subsection grub_video_get_area_status +@itemize + +@item Prototype: +@example +grub_err_r +grub_video_get_area_status (grub_video_area_status_t *area_status); +@end example + +@item Description: +Used to query the area status. +@end itemize + @subsection grub_video_set_viewport @itemize @item Prototype: @@ -1139,6 +1180,37 @@ grub_video_get_viewport (unsigned int *x, unsigned int *y, unsigned int *width, Used to query current viewport dimensions. Software developer can use this to choose best way to render contents of the viewport. @end itemize +@subsection grub_video_set_region +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_set_region (unsigned int x, unsigned int y, unsigned int width, unsigned int height); +@end example +@item Description: + +Used to specify the region of the screen which should be redrawn. Use absolute +values. When the region is set and area status is ENABLE all draw commands will +be performed inside the interseption of region and viewport named area. +If draw commands try to draw over viewport, they are clipped. If developer +requests larger than possible region, width and height will be clamped to fit +screen. Should be used for redrawing of active elements. +@end itemize + +@subsection grub_video_get_region +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_get_region (unsigned int *x, unsigned int *y, unsigned int *width, unsigned int *height); +@end example +@item Description: + +Used to query current region dimensions. +@end itemize + @subsection grub_video_map_color @itemize @item Prototype: diff --git a/grub-core/gfxmenu/gui_box.c b/grub-core/gfxmenu/gui_box.c index 38b15f96d..37bab3fbb 100644 --- a/grub-core/gfxmenu/gui_box.c +++ b/grub-core/gfxmenu/gui_box.c @@ -234,14 +234,30 @@ static void box_paint (void *vself, const grub_video_rect_t *region) { grub_gui_box_t self = vself; + struct component_node *cur; grub_video_rect_t vpsave; + grub_video_area_status_t box_area_status; + grub_video_get_area_status (&box_area_status); + grub_gui_set_viewport (&self->bounds, &vpsave); for (cur = self->chead.next; cur != &self->ctail; cur = cur->next) { grub_gui_component_t comp = cur->component; + grub_video_rect_t r; + comp->ops->get_bounds(comp, &r); + + if (!grub_video_have_common_points (region, &r)) + continue; + + /* Paint the child. */ + if (box_area_status == GRUB_VIDEO_AREA_ENABLED + && grub_video_bounds_inside_region (&r, region)) + grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED); comp->ops->paint (comp, region); + if (box_area_status == GRUB_VIDEO_AREA_ENABLED) + grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED); } grub_gui_restore_viewport (&vpsave); } diff --git a/grub-core/gfxmenu/gui_canvas.c b/grub-core/gfxmenu/gui_canvas.c index b3919c2d3..a05491242 100644 --- a/grub-core/gfxmenu/gui_canvas.c +++ b/grub-core/gfxmenu/gui_canvas.c @@ -80,9 +80,13 @@ static void canvas_paint (void *vself, const grub_video_rect_t *region) { grub_gui_canvas_t self = vself; + struct component_node *cur; grub_video_rect_t vpsave; + grub_video_area_status_t canvas_area_status; + grub_video_get_area_status (&canvas_area_status); + grub_gui_set_viewport (&self->bounds, &vpsave); for (cur = self->components.next; cur; cur = cur->next) { @@ -135,9 +139,16 @@ canvas_paint (void *vself, const grub_video_rect_t *region) r.height = h; comp->ops->set_bounds (comp, &r); + if (!grub_video_have_common_points (region, &r)) + continue; + /* Paint the child. */ - if (grub_video_have_common_points (region, &r)) - comp->ops->paint (comp, region); + if (canvas_area_status == GRUB_VIDEO_AREA_ENABLED + && grub_video_bounds_inside_region (&r, region)) + grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED); + comp->ops->paint (comp, region); + if (canvas_area_status == GRUB_VIDEO_AREA_ENABLED) + grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED); } grub_gui_restore_viewport (&vpsave); } diff --git a/grub-core/gfxmenu/view.c b/grub-core/gfxmenu/view.c index ed58cdc6d..ad5e82b81 100644 --- a/grub-core/gfxmenu/view.c +++ b/grub-core/gfxmenu/view.c @@ -213,6 +213,7 @@ redraw_timeouts (struct grub_gfxmenu_view *view) { grub_video_rect_t bounds; cur->self->ops->get_bounds (cur->self, &bounds); + grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED); grub_gfxmenu_view_redraw (view, &bounds); } } @@ -321,6 +322,11 @@ grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view, grub_gfxterm_schedule_repaint (); grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + grub_video_area_status_t area_status; + grub_video_get_area_status (&area_status); + if (area_status == GRUB_VIDEO_AREA_ENABLED) + grub_video_set_region (region->x, region->y, + region->width, region->height); redraw_background (view, region); if (view->canvas) @@ -328,6 +334,9 @@ grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view, draw_title (view); if (grub_video_have_common_points (&view->progress_message_frame, region)) draw_message (view); + + if (area_status == GRUB_VIDEO_AREA_ENABLED) + grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED); } void @@ -350,10 +359,15 @@ grub_gfxmenu_view_draw (grub_gfxmenu_view_t view) refresh_menu_components (view); update_menu_components (view); + grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED); grub_gfxmenu_view_redraw (view, &view->screen); grub_video_swap_buffers (); if (view->double_repaint) - grub_gfxmenu_view_redraw (view, &view->screen); + { + grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED); + grub_gfxmenu_view_redraw (view, &view->screen); + } + } static void @@ -367,6 +381,7 @@ redraw_menu_visit (grub_gui_component_t component, grub_video_rect_t bounds; component->ops->get_bounds (component, &bounds); + grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED); grub_gfxmenu_view_redraw (view, &bounds); } } @@ -404,6 +419,8 @@ grub_gfxmenu_draw_terminal_box (void) if (!term_box) return; + grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED); + term_box->set_content_size (term_box, term_view->terminal_rect.width, term_view->terminal_rect.height); diff --git a/grub-core/video/bochs.c b/grub-core/video/bochs.c index 287ae0ff3..4b8c205fb 100644 --- a/grub-core/video/bochs.c +++ b/grub-core/video/bochs.c @@ -401,6 +401,10 @@ static struct grub_video_adapter grub_video_bochs_adapter = .get_palette = grub_video_fb_get_palette, .set_viewport = grub_video_fb_set_viewport, .get_viewport = grub_video_fb_get_viewport, + .set_region = grub_video_fb_set_region, + .get_region = grub_video_fb_get_region, + .set_area_status = grub_video_fb_set_area_status, + .get_area_status = grub_video_fb_get_area_status, .map_color = grub_video_fb_map_color, .map_rgb = grub_video_fb_map_rgb, .map_rgba = grub_video_fb_map_rgba, diff --git a/grub-core/video/capture.c b/grub-core/video/capture.c index bae6401ab..67c8edde8 100644 --- a/grub-core/video/capture.c +++ b/grub-core/video/capture.c @@ -51,6 +51,10 @@ static struct grub_video_adapter grub_video_capture_adapter = .get_palette = grub_video_fb_get_palette, .set_viewport = grub_video_fb_set_viewport, .get_viewport = grub_video_fb_get_viewport, + .set_region = grub_video_fb_set_region, + .get_region = grub_video_fb_get_region, + .set_area_status = grub_video_fb_set_area_status, + .get_area_status = grub_video_fb_get_area_status, .map_color = grub_video_fb_map_color, .map_rgb = grub_video_fb_map_rgb, .map_rgba = grub_video_fb_map_rgba, diff --git a/grub-core/video/cirrus.c b/grub-core/video/cirrus.c index 00e6516ac..41baae490 100644 --- a/grub-core/video/cirrus.c +++ b/grub-core/video/cirrus.c @@ -480,6 +480,10 @@ static struct grub_video_adapter grub_video_cirrus_adapter = .get_palette = grub_video_fb_get_palette, .set_viewport = grub_video_fb_set_viewport, .get_viewport = grub_video_fb_get_viewport, + .set_region = grub_video_fb_set_region, + .get_region = grub_video_fb_get_region, + .set_area_status = grub_video_fb_set_area_status, + .get_area_status = grub_video_fb_get_area_status, .map_color = grub_video_fb_map_color, .map_rgb = grub_video_fb_map_rgb, .map_rgba = grub_video_fb_map_rgba, diff --git a/grub-core/video/efi_gop.c b/grub-core/video/efi_gop.c index 428564400..7f9d1c2df 100644 --- a/grub-core/video/efi_gop.c +++ b/grub-core/video/efi_gop.c @@ -586,6 +586,10 @@ static struct grub_video_adapter grub_video_gop_adapter = .get_palette = grub_video_fb_get_palette, .set_viewport = grub_video_fb_set_viewport, .get_viewport = grub_video_fb_get_viewport, + .set_region = grub_video_fb_set_region, + .get_region = grub_video_fb_get_region, + .set_area_status = grub_video_fb_set_area_status, + .get_area_status = grub_video_fb_get_area_status, .map_color = grub_video_fb_map_color, .map_rgb = grub_video_fb_map_rgb, .map_rgba = grub_video_fb_map_rgba, diff --git a/grub-core/video/efi_uga.c b/grub-core/video/efi_uga.c index 159df8e61..464ede874 100644 --- a/grub-core/video/efi_uga.c +++ b/grub-core/video/efi_uga.c @@ -327,6 +327,10 @@ static struct grub_video_adapter grub_video_uga_adapter = .get_palette = grub_video_fb_get_palette, .set_viewport = grub_video_fb_set_viewport, .get_viewport = grub_video_fb_get_viewport, + .set_region = grub_video_fb_set_region, + .get_region = grub_video_fb_get_region, + .set_area_status = grub_video_fb_set_area_status, + .get_area_status = grub_video_fb_get_area_status, .map_color = grub_video_fb_map_color, .map_rgb = grub_video_fb_map_rgb, .map_rgba = grub_video_fb_map_rgba, diff --git a/grub-core/video/emu/sdl.c b/grub-core/video/emu/sdl.c index 6fd01be39..a2f639f66 100644 --- a/grub-core/video/emu/sdl.c +++ b/grub-core/video/emu/sdl.c @@ -220,6 +220,10 @@ static struct grub_video_adapter grub_video_sdl_adapter = .get_palette = grub_video_fb_get_palette, .set_viewport = grub_video_fb_set_viewport, .get_viewport = grub_video_fb_get_viewport, + .set_region = grub_video_fb_set_region, + .get_region = grub_video_fb_get_region, + .set_area_status = grub_video_fb_set_area_status, + .get_area_status = grub_video_fb_get_area_status, .map_color = grub_video_fb_map_color, .map_rgb = grub_video_fb_map_rgb, .map_rgba = grub_video_fb_map_rgba, diff --git a/grub-core/video/fb/video_fb.c b/grub-core/video/fb/video_fb.c index 6401e8a77..722bb3bb4 100644 --- a/grub-core/video/fb/video_fb.c +++ b/grub-core/video/fb/video_fb.c @@ -399,12 +399,67 @@ grub_video_fb_set_palette (unsigned int start, unsigned int count, return GRUB_ERR_NONE; } +static grub_err_t +grub_video_fb_set_area (void) +{ + unsigned int viewport_x1 = framebuffer.render_target->viewport.x; + unsigned int viewport_y1 = framebuffer.render_target->viewport.y; + unsigned int viewport_width = framebuffer.render_target->viewport.width; + unsigned int viewport_height = framebuffer.render_target->viewport.height; + unsigned int viewport_x2 = viewport_x1 + viewport_width; + unsigned int viewport_y2 = viewport_y1 + viewport_height; + + unsigned int region_x1 = framebuffer.render_target->region.x; + unsigned int region_y1 = framebuffer.render_target->region.y; + unsigned int region_width = framebuffer.render_target->region.width; + unsigned int region_height = framebuffer.render_target->region.height; + unsigned int region_x2 = region_x1 + region_width; + unsigned int region_y2 = region_y1 + region_height; + + unsigned int max_x1 = grub_max (viewport_x1, region_x1); + unsigned int min_x2 = grub_min (viewport_x2, region_x2); + unsigned int max_y1 = grub_max (viewport_y1, region_y1); + unsigned int min_y2 = grub_min (viewport_y2, region_y2); + + /* Viewport and region do not intersect. */ + if (viewport_width == 0 || viewport_height == 0 || region_width == 0 + || region_height == 0 || max_x1 >= min_x2 || max_y1 >= min_y2) + { + framebuffer.render_target->area.x = 0; + framebuffer.render_target->area.y = 0; + framebuffer.render_target->area.width = 0; + framebuffer.render_target->area.height = 0; + framebuffer.render_target->area_offset_x = 0; + framebuffer.render_target->area_offset_y = 0; + return GRUB_ERR_NONE; + } + + /* There is non-zero intersection. */ + framebuffer.render_target->area.x = max_x1; + framebuffer.render_target->area.y = max_y1; + framebuffer.render_target->area.width = min_x2 - max_x1; + framebuffer.render_target->area.height = min_y2 - max_y1; + + if (region_x1 > viewport_x1) + framebuffer.render_target->area_offset_x = (int)region_x1 + - (int)viewport_x1; + else + framebuffer.render_target->area_offset_x = 0; + if (region_y1 > viewport_y1) + framebuffer.render_target->area_offset_y = (int)region_y1 + - (int)viewport_y1; + else + framebuffer.render_target->area_offset_y = 0; + + return GRUB_ERR_NONE; +} + grub_err_t grub_video_fb_set_viewport (unsigned int x, unsigned int y, unsigned int width, unsigned int height) { - /* Make sure viewport is withing screen dimensions. If viewport was set - to be out of the region, mark its size as zero. */ + /* Make sure viewport is within screen dimensions. If viewport was set + to be out of the screen, mark its size as zero. */ if (x > framebuffer.render_target->mode_info.width) { x = 0; @@ -428,6 +483,10 @@ grub_video_fb_set_viewport (unsigned int x, unsigned int y, framebuffer.render_target->viewport.width = width; framebuffer.render_target->viewport.height = height; + /* Count drawing area only if needed. */ + if (framebuffer.render_target->area_enabled) + grub_video_fb_set_area (); + return GRUB_ERR_NONE; } @@ -443,6 +502,78 @@ grub_video_fb_get_viewport (unsigned int *x, unsigned int *y, return GRUB_ERR_NONE; } +grub_err_t +grub_video_fb_set_region (unsigned int x, unsigned int y, + unsigned int width, unsigned int height) +{ + /* Make sure region is within screen dimensions. If region was set + to be out of the screen, mark its size as zero. */ + if (x > framebuffer.render_target->mode_info.width) + { + x = 0; + width = 0; + } + + if (y > framebuffer.render_target->mode_info.height) + { + y = 0; + height = 0; + } + + if (x + width > framebuffer.render_target->mode_info.width) + width = framebuffer.render_target->mode_info.width - x; + + if (y + height > framebuffer.render_target->mode_info.height) + height = framebuffer.render_target->mode_info.height - y; + + framebuffer.render_target->region.x = x; + framebuffer.render_target->region.y = y; + framebuffer.render_target->region.width = width; + framebuffer.render_target->region.height = height; + + /* If we have called set_region then area is needed. */ + grub_video_fb_set_area (); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_video_fb_get_region (unsigned int *x, unsigned int *y, + unsigned int *width, unsigned int *height) +{ + if (x) *x = framebuffer.render_target->region.x; + if (y) *y = framebuffer.render_target->region.y; + if (width) *width = framebuffer.render_target->region.width; + if (height) *height = framebuffer.render_target->region.height; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_video_fb_set_area_status (grub_video_area_status_t area_status) +{ + if (area_status == GRUB_VIDEO_AREA_ENABLED) + framebuffer.render_target->area_enabled = 1; + else + framebuffer.render_target->area_enabled = 0; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_video_fb_get_area_status (grub_video_area_status_t *area_status) +{ + if (!area_status) + return GRUB_ERR_NONE; + + if (framebuffer.render_target->area_enabled) + *area_status = GRUB_VIDEO_AREA_ENABLED; + else + *area_status = GRUB_VIDEO_AREA_DISABLED; + + return GRUB_ERR_NONE; +} + /* Maps color name to target optimized color format. */ grub_video_color_t grub_video_fb_map_color (grub_uint32_t color_name) @@ -714,14 +845,36 @@ grub_video_fb_fill_rect (grub_video_color_t color, int x, int y, unsigned int width, unsigned int height) { struct grub_video_fbblit_info target; + unsigned int area_x; + unsigned int area_y; + unsigned int area_width; + unsigned int area_height; + if (framebuffer.render_target->area_enabled) + { + area_x = framebuffer.render_target->area.x; + area_y = framebuffer.render_target->area.y; + area_width = framebuffer.render_target->area.width; + area_height = framebuffer.render_target->area.height; + x -= framebuffer.render_target->area_offset_x; + y -= framebuffer.render_target->area_offset_y; + } + else + { + area_x = framebuffer.render_target->viewport.x; + area_y = framebuffer.render_target->viewport.y; + area_width = framebuffer.render_target->viewport.width; + area_height = framebuffer.render_target->viewport.height; + } /* Make sure there is something to do. */ - if ((x >= (int)framebuffer.render_target->viewport.width) || (x + (int)width < 0)) + if ((area_width == 0) || (area_height == 0)) return GRUB_ERR_NONE; - if ((y >= (int)framebuffer.render_target->viewport.height) || (y + (int)height < 0)) + if ((x >= (int)area_width) || (x + (int)width < 0)) + return GRUB_ERR_NONE; + if ((y >= (int)area_height) || (y + (int)height < 0)) return GRUB_ERR_NONE; - /* Do not allow drawing out of viewport. */ + /* Do not allow drawing out of area. */ if (x < 0) { width += x; @@ -733,14 +886,14 @@ grub_video_fb_fill_rect (grub_video_color_t color, int x, int y, y = 0; } - if ((x + width) > framebuffer.render_target->viewport.width) - width = framebuffer.render_target->viewport.width - x; - if ((y + height) > framebuffer.render_target->viewport.height) - height = framebuffer.render_target->viewport.height - y; + if ((x + width) > area_width) + width = area_width - x; + if ((y + height) > area_height) + height = area_height - y; - /* Add viewport offset. */ - x += framebuffer.render_target->viewport.x; - y += framebuffer.render_target->viewport.y; + /* Add area offset. */ + x += area_x; + y += area_y; dirty (y, height); @@ -760,13 +913,33 @@ grub_video_fb_blit_source (struct grub_video_fbblit_info *source, unsigned int width, unsigned int height) { struct grub_video_fbblit_info target; + unsigned int area_x; + unsigned int area_y; + unsigned int area_width; + unsigned int area_height; + if (framebuffer.render_target->area_enabled) + { + area_x = framebuffer.render_target->area.x; + area_y = framebuffer.render_target->area.y; + area_width = framebuffer.render_target->area.width; + area_height = framebuffer.render_target->area.height; + x -= framebuffer.render_target->area_offset_x; + y -= framebuffer.render_target->area_offset_y; + } + else + { + area_x = framebuffer.render_target->viewport.x; + area_y = framebuffer.render_target->viewport.y; + area_width = framebuffer.render_target->viewport.width; + area_height = framebuffer.render_target->viewport.height; + } /* Make sure there is something to do. */ - if ((width == 0) || (height == 0)) + if ((area_width == 0) || (area_height == 0) || (width == 0) || (height == 0)) return GRUB_ERR_NONE; - if ((x >= (int)framebuffer.render_target->viewport.width) || (x + (int)width < 0)) + if ((x >= (int)area_width) || (x + (int)width < 0)) return GRUB_ERR_NONE; - if ((y >= (int)framebuffer.render_target->viewport.height) || (y + (int)height < 0)) + if ((y >= (int)area_height) || (y + (int)height < 0)) return GRUB_ERR_NONE; if ((x + (int)source->mode_info->width) < 0) return GRUB_ERR_NONE; @@ -808,11 +981,11 @@ grub_video_fb_blit_source (struct grub_video_fbblit_info *source, y = 0; } - /* Do not allow drawing out of viewport. */ - if ((x + width) > framebuffer.render_target->viewport.width) - width = framebuffer.render_target->viewport.width - x; - if ((y + height) > framebuffer.render_target->viewport.height) - height = framebuffer.render_target->viewport.height - y; + /* Do not allow drawing out of area. */ + if ((x + width) > area_width) + width = area_width - x; + if ((y + height) > area_height) + height = area_height - y; if ((offset_x + width) > source->mode_info->width) width = source->mode_info->width - offset_x; @@ -827,8 +1000,8 @@ grub_video_fb_blit_source (struct grub_video_fbblit_info *source, height = source->mode_info->height; /* Add viewport offset. */ - x += framebuffer.render_target->viewport.x; - y += framebuffer.render_target->viewport.y; + x += area_x; + y += area_y; /* Use fbblit_info to encapsulate rendering. */ target.mode_info = &framebuffer.render_target->mode_info; @@ -1058,12 +1231,25 @@ grub_video_fb_create_render_target (struct grub_video_fbrender_target **result, /* Mark render target as allocated. */ target->is_allocated = 1; - /* Maximize viewport. */ + /* Maximize viewport, region and area. */ target->viewport.x = 0; target->viewport.y = 0; target->viewport.width = width; target->viewport.height = height; + target->region.x = 0; + target->region.y = 0; + target->region.width = width; + target->region.height = height; + + target->area_enabled = 0; + target->area.x = 0; + target->area.y = 0; + target->area.width = width; + target->area.height = height; + target->area_offset_x = 0; + target->area_offset_y = 0; + /* Setup render target format. */ target->mode_info.width = width; target->mode_info.height = height; @@ -1150,12 +1336,25 @@ grub_video_fb_create_render_target_from_pointer (struct grub_video_fbrender_targ grub_memcpy (&(target->mode_info), mode_info, sizeof (target->mode_info)); - /* Reset viewport to match new mode. */ + /* Reset viewport, region and area to match new mode. */ target->viewport.x = 0; target->viewport.y = 0; target->viewport.width = mode_info->width; target->viewport.height = mode_info->height; + target->region.x = 0; + target->region.y = 0; + target->region.width = mode_info->width; + target->region.height = mode_info->height; + + target->area_enabled = 0; + target->area.x = 0; + target->area.y = 0; + target->area.width = mode_info->width; + target->area.height = mode_info->height; + target->area_offset_x = 0; + target->area_offset_y = 0; + /* Clear render target with black and maximum transparency. */ for (y = 0; y < mode_info->height; y++) grub_memset (target->data + mode_info->pitch * y, 0, diff --git a/grub-core/video/i386/coreboot/cbfb.c b/grub-core/video/i386/coreboot/cbfb.c index 62b86db2b..dede0c37e 100644 --- a/grub-core/video/i386/coreboot/cbfb.c +++ b/grub-core/video/i386/coreboot/cbfb.c @@ -138,6 +138,10 @@ static struct grub_video_adapter grub_video_cbfb_adapter = .get_palette = grub_video_fb_get_palette, .set_viewport = grub_video_fb_set_viewport, .get_viewport = grub_video_fb_get_viewport, + .set_region = grub_video_fb_set_region, + .get_region = grub_video_fb_get_region, + .set_area_status = grub_video_fb_set_area_status, + .get_area_status = grub_video_fb_get_area_status, .map_color = grub_video_fb_map_color, .map_rgb = grub_video_fb_map_rgb, .map_rgba = grub_video_fb_map_rgba, diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index a29a15dc3..62b5c2245 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -1214,6 +1214,10 @@ static struct grub_video_adapter grub_video_vbe_adapter = .get_palette = grub_video_fb_get_palette, .set_viewport = grub_video_fb_set_viewport, .get_viewport = grub_video_fb_get_viewport, + .set_region = grub_video_fb_set_region, + .get_region = grub_video_fb_get_region, + .set_area_status = grub_video_fb_set_area_status, + .get_area_status = grub_video_fb_get_area_status, .map_color = grub_video_fb_map_color, .map_rgb = grub_video_fb_map_rgb, .map_rgba = grub_video_fb_map_rgba, diff --git a/grub-core/video/i386/pc/vga.c b/grub-core/video/i386/pc/vga.c index 997e132a2..01f47112d 100644 --- a/grub-core/video/i386/pc/vga.c +++ b/grub-core/video/i386/pc/vga.c @@ -372,6 +372,10 @@ static struct grub_video_adapter grub_video_vga_adapter = .get_palette = grub_video_fb_get_palette, .set_viewport = grub_video_fb_set_viewport, .get_viewport = grub_video_fb_get_viewport, + .set_region = grub_video_fb_set_region, + .get_region = grub_video_fb_get_region, + .set_area_status = grub_video_fb_set_area_status, + .get_area_status = grub_video_fb_get_area_status, .map_color = grub_video_fb_map_color, .map_rgb = grub_video_fb_map_rgb, .map_rgba = grub_video_fb_map_rgba, diff --git a/grub-core/video/ieee1275.c b/grub-core/video/ieee1275.c index 5c5870278..0b150ec24 100644 --- a/grub-core/video/ieee1275.c +++ b/grub-core/video/ieee1275.c @@ -328,6 +328,10 @@ static struct grub_video_adapter grub_video_ieee1275_adapter = .get_palette = grub_video_fb_get_palette, .set_viewport = grub_video_fb_set_viewport, .get_viewport = grub_video_fb_get_viewport, + .set_region = grub_video_fb_set_region, + .get_region = grub_video_fb_get_region, + .set_area_status = grub_video_fb_set_area_status, + .get_area_status = grub_video_fb_get_area_status, .map_color = grub_video_fb_map_color, .map_rgb = grub_video_fb_map_rgb, .map_rgba = grub_video_fb_map_rgba, diff --git a/grub-core/video/radeon_fuloong2e.c b/grub-core/video/radeon_fuloong2e.c index ddcf9a39e..b4da34b5e 100644 --- a/grub-core/video/radeon_fuloong2e.c +++ b/grub-core/video/radeon_fuloong2e.c @@ -207,6 +207,10 @@ static struct grub_video_adapter grub_video_radeon_fuloong2e_adapter = .get_palette = grub_video_fb_get_palette, .set_viewport = grub_video_fb_set_viewport, .get_viewport = grub_video_fb_get_viewport, + .set_region = grub_video_fb_set_region, + .get_region = grub_video_fb_get_region, + .set_area_status = grub_video_fb_set_area_status, + .get_area_status = grub_video_fb_get_area_status, .map_color = grub_video_fb_map_color, .map_rgb = grub_video_fb_map_rgb, .map_rgba = grub_video_fb_map_rgba, diff --git a/grub-core/video/sis315pro.c b/grub-core/video/sis315pro.c index c1ae27019..22a0c85a6 100644 --- a/grub-core/video/sis315pro.c +++ b/grub-core/video/sis315pro.c @@ -420,6 +420,10 @@ static struct grub_video_adapter grub_video_sis315pro_adapter = .get_palette = grub_video_fb_get_palette, .set_viewport = grub_video_fb_set_viewport, .get_viewport = grub_video_fb_get_viewport, + .set_region = grub_video_fb_set_region, + .get_region = grub_video_fb_get_region, + .set_area_status = grub_video_fb_set_area_status, + .get_area_status = grub_video_fb_get_area_status, .map_color = grub_video_fb_map_color, .map_rgb = grub_video_fb_map_rgb, .map_rgba = grub_video_fb_map_rgba, diff --git a/grub-core/video/sm712.c b/grub-core/video/sm712.c index 441faabd3..10c46eb65 100644 --- a/grub-core/video/sm712.c +++ b/grub-core/video/sm712.c @@ -779,6 +779,10 @@ static struct grub_video_adapter grub_video_sm712_adapter = .get_palette = grub_video_fb_get_palette, .set_viewport = grub_video_fb_set_viewport, .get_viewport = grub_video_fb_get_viewport, + .set_region = grub_video_fb_set_region, + .get_region = grub_video_fb_get_region, + .set_area_status = grub_video_fb_set_area_status, + .get_area_status = grub_video_fb_get_area_status, .map_color = grub_video_fb_map_color, .map_rgb = grub_video_fb_map_rgb, .map_rgba = grub_video_fb_map_rgba, diff --git a/grub-core/video/video.c b/grub-core/video/video.c index 5215ac967..f252663c1 100644 --- a/grub-core/video/video.c +++ b/grub-core/video/video.c @@ -225,6 +225,48 @@ grub_video_get_viewport (unsigned int *x, unsigned int *y, return grub_video_adapter_active->get_viewport (x, y, width, height); } +/* Set region dimensions. */ +grub_err_t +grub_video_set_region (unsigned int x, unsigned int y, + unsigned int width, unsigned int height) +{ + if (! grub_video_adapter_active) + return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated"); + + return grub_video_adapter_active->set_region (x, y, width, height); +} + +/* Get region dimensions. */ +grub_err_t +grub_video_get_region (unsigned int *x, unsigned int *y, + unsigned int *width, unsigned int *height) +{ + if (! grub_video_adapter_active) + return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated"); + + return grub_video_adapter_active->get_region (x, y, width, height); +} + +/* Set status of the intersection of the viewport and the region. */ +grub_err_t +grub_video_set_area_status (grub_video_area_status_t area_status) +{ + if (! grub_video_adapter_active) + return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated"); + + return grub_video_adapter_active->set_area_status (area_status); +} + +/* Get status of the intersection of the viewport and the region. */ +grub_err_t +grub_video_get_area_status (grub_video_area_status_t *area_status) +{ + if (! grub_video_adapter_active) + return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated"); + + return grub_video_adapter_active->get_area_status (area_status); +} + /* Map color name to adapter specific color. */ grub_video_color_t grub_video_map_color (grub_uint32_t color_name) diff --git a/include/grub/fbfill.h b/include/grub/fbfill.h index 12d164bd6..35a80b820 100644 --- a/include/grub/fbfill.h +++ b/include/grub/fbfill.h @@ -30,13 +30,17 @@ struct grub_video_fbrender_target mode_type has been re-adjusted to requested render target settings. */ struct grub_video_mode_info mode_info; - struct - { - unsigned int x; - unsigned int y; - unsigned int width; - unsigned int height; - } viewport; + /* We should not draw outside of viewport. */ + grub_video_rect_t viewport; + /* Set region to make a re-draw of a part of the screen. */ + grub_video_rect_t region; + /* Should be set to 0 if the viewport is inside of the region. */ + int area_enabled; + /* Internal structure - intersection of the viewport and the region. */ + grub_video_rect_t area; + /* Internal values - offsets from the left top point of the viewport. */ + int area_offset_x; + int area_offset_y; /* Indicates whether the data has been allocated by us and must be freed when render target is destroyed. */ diff --git a/include/grub/gui.h b/include/grub/gui.h index 6f818627e..7504c8047 100644 --- a/include/grub/gui.h +++ b/include/grub/gui.h @@ -248,4 +248,15 @@ grub_video_have_common_points (const grub_video_rect_t *a, return 1; } +static inline int +grub_video_bounds_inside_region (const grub_video_rect_t *b, + const grub_video_rect_t *r) +{ + if (r->x > b->x || r->x + r->width < b->x + b->width) + return 0; + if (r->y > b->y || r->y + r->height < b->y + b->height) + return 0; + return 1; +} + #endif /* ! GRUB_GUI_H */ diff --git a/include/grub/video.h b/include/grub/video.h index 5dd99c136..601261e15 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -301,6 +301,11 @@ typedef enum grub_video_adapter_prio GRUB_VIDEO_ADAPTER_PRIO_NATIVE = 100 } grub_video_adapter_prio_t; +typedef enum grub_video_area_status + { + GRUB_VIDEO_AREA_DISABLED, + GRUB_VIDEO_AREA_ENABLED + } grub_video_area_status_t; struct grub_video_adapter { @@ -341,6 +346,16 @@ struct grub_video_adapter grub_err_t (*get_viewport) (unsigned int *x, unsigned int *y, unsigned int *width, unsigned int *height); + grub_err_t (*set_region) (unsigned int x, unsigned int y, + unsigned int width, unsigned int height); + + grub_err_t (*get_region) (unsigned int *x, unsigned int *y, + unsigned int *width, unsigned int *height); + + grub_err_t (*set_area_status) (grub_video_area_status_t area_status); + + grub_err_t (*get_area_status) (grub_video_area_status_t *area_status); + grub_video_color_t (*map_color) (grub_uint32_t color_name); grub_video_color_t (*map_rgb) (grub_uint8_t red, grub_uint8_t green, @@ -447,6 +462,22 @@ grub_err_t EXPORT_FUNC (grub_video_get_viewport) (unsigned int *x, unsigned int *width, unsigned int *height); +grub_err_t EXPORT_FUNC (grub_video_set_region) (unsigned int x, + unsigned int y, + unsigned int width, + unsigned int height); + +grub_err_t EXPORT_FUNC (grub_video_get_region) (unsigned int *x, + unsigned int *y, + unsigned int *width, + unsigned int *height); + +grub_err_t EXPORT_FUNC (grub_video_set_area_status) + (grub_video_area_status_t area_status); + +grub_err_t EXPORT_FUNC (grub_video_get_area_status) + (grub_video_area_status_t *area_status); + grub_video_color_t EXPORT_FUNC (grub_video_map_color) (grub_uint32_t color_name); grub_video_color_t EXPORT_FUNC (grub_video_map_rgb) (grub_uint8_t red, diff --git a/include/grub/video_fb.h b/include/grub/video_fb.h index d1560d982..4a64fb8b7 100644 --- a/include/grub/video_fb.h +++ b/include/grub/video_fb.h @@ -58,6 +58,22 @@ EXPORT_FUNC(grub_video_fb_get_viewport) (unsigned int *x, unsigned int *y, unsigned int *width, unsigned int *height); +grub_err_t +EXPORT_FUNC(grub_video_fb_set_region) (unsigned int x, unsigned int y, + unsigned int width, unsigned int height); +grub_err_t +EXPORT_FUNC(grub_video_fb_get_region) (unsigned int *x, unsigned int *y, + unsigned int *width, + unsigned int *height); + +grub_err_t +EXPORT_FUNC(grub_video_fb_set_area_status) + (grub_video_area_status_t area_status); + +grub_err_t +EXPORT_FUNC(grub_video_fb_get_area_status) + (grub_video_area_status_t *area_status); + grub_video_color_t EXPORT_FUNC(grub_video_fb_map_color) (grub_uint32_t color_name);