* grub-core/gfxmenu/gui_box.c: Updated to work with area status.
authorVladimir Testov <vladimir.testov@rosalab.ru>
Fri, 8 Nov 2013 11:42:38 +0000 (15:42 +0400)
committerVladimir Testov <vladimir.testov@rosalab.ru>
Fri, 8 Nov 2013 11:42:38 +0000 (15:42 +0400)
        * 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.

24 files changed:
ChangeLog
docs/grub-dev.texi
grub-core/gfxmenu/gui_box.c
grub-core/gfxmenu/gui_canvas.c
grub-core/gfxmenu/view.c
grub-core/video/bochs.c
grub-core/video/capture.c
grub-core/video/cirrus.c
grub-core/video/efi_gop.c
grub-core/video/efi_uga.c
grub-core/video/emu/sdl.c
grub-core/video/fb/video_fb.c
grub-core/video/i386/coreboot/cbfb.c
grub-core/video/i386/pc/vbe.c
grub-core/video/i386/pc/vga.c
grub-core/video/ieee1275.c
grub-core/video/radeon_fuloong2e.c
grub-core/video/sis315pro.c
grub-core/video/sm712.c
grub-core/video/video.c
include/grub/fbfill.h
include/grub/gui.h
include/grub/video.h
include/grub/video_fb.h

index 1222837..f8a0148 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,34 @@
+2013-11-08  Vladimir Testov  <vladimir.testov@rosalab.ru>
+
+       * 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  <phcoder@gmail.com>
 
        * grub-core/kern/mm.c (grub_real_malloc): Use AND rather than MOD
index 9499f8b..6caec78 100644 (file)
@@ -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:
index 38b15f9..37bab3f 100644 (file)
@@ -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);
 }
index b3919c2..a054912 100644 (file)
@@ -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);
 }
index ed58cdc..ad5e82b 100644 (file)
@@ -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);
   
index 287ae0f..4b8c205 100644 (file)
@@ -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,
index bae6401..67c8edd 100644 (file)
@@ -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,
index 00e6516..41baae4 100644 (file)
@@ -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,
index 4285644..7f9d1c2 100644 (file)
@@ -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,
index 159df8e..464ede8 100644 (file)
@@ -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,
index 6fd01be..a2f639f 100644 (file)
@@ -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,
index 6401e8a..722bb3b 100644 (file)
@@ -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 ((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;
 
-  /* 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,
index 62b86db..dede0c3 100644 (file)
@@ -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,
index a29a15d..62b5c22 100644 (file)
@@ -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,
index 997e132..01f4711 100644 (file)
@@ -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,
index 5c58702..0b150ec 100644 (file)
@@ -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,
index ddcf9a3..b4da34b 100644 (file)
@@ -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,
index c1ae270..22a0c85 100644 (file)
@@ -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,
index 441faab..10c46eb 100644 (file)
@@ -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,
index 5215ac9..f252663 100644 (file)
@@ -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)
index 12d164b..35a80b8 100644 (file)
@@ -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.  */
index 6f81862..7504c80 100644 (file)
@@ -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 */
index 5dd99c1..601261e 100644 (file)
@@ -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,
index d1560d9..4a64fb8 100644 (file)
@@ -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);