]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
* grub-core/term/efi/console.c (grub_efi_console_init): Set text mode.
authorMatthew Garrett <mjg@redhat.com>
Sat, 26 May 2012 11:33:34 +0000 (13:33 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sat, 26 May 2012 11:33:34 +0000 (13:33 +0200)
(grub_efi_console_fini): Likewise.
* grub-core/video/efi_gop.c (framebuffer): New field offscreen.
(grub_video_gop_fill_mode_info): Rename to ...
(grub_video_gop_fill_real_mode_info): ... this.
(grub_video_gop_fill_mode_info): New function.
(grub_video_gop_setup): Setup double framebuffer.
(grub_video_gop_get_info_and_fini): Use original framebuffer.
Free offscreen.
(grub_video_gop_swap_buffers): Copy framebuffer.
(grub_video_gop_fini): Free offscreen buffer.
* include/grub/efi/graphics_output.h (grub_efi_gop_blt_operation_t):
New enum.
(grub_efi_gop_blt_pixel): New struct.

ChangeLog
grub-core/term/efi/console.c
grub-core/video/efi_gop.c
include/grub/efi/graphics_output.h

index 42206a69cb30682e1df420e8bf6049d2c0dc4d77..20dd6860a5f8ae29e2e85ff31ff4208f46e787d5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2012-05-26  Matthew Garrett  <mjg@redhat.com>
+
+       * grub-core/term/efi/console.c (grub_efi_console_init): Set text mode.
+       (grub_efi_console_fini): Likewise.
+       * grub-core/video/efi_gop.c (framebuffer): New field offscreen.
+       (grub_video_gop_fill_mode_info): Rename to ...
+       (grub_video_gop_fill_real_mode_info): ... this.
+       (grub_video_gop_fill_mode_info): New function.
+       (grub_video_gop_setup): Setup double framebuffer.
+       (grub_video_gop_get_info_and_fini): Use original framebuffer.
+       Free offscreen.
+       (grub_video_gop_swap_buffers): Copy framebuffer.
+       (grub_video_gop_fini): Free offscreen buffer.
+       * include/grub/efi/graphics_output.h (grub_efi_gop_blt_operation_t):
+       New enum.
+       (grub_efi_gop_blt_pixel): New struct.
+
 2012-05-26  Vladimir Serbinenko  <phcoder@gmail.com>
 
        * gentpl.py: Remove error disabling for objconv.
index 8fd89b0932a40fe510a64715ccd666949b5fb5fd..e57a815b01039dd8b9f390796fc90d201a8d87e0 100644 (file)
@@ -234,6 +234,7 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)),
 static grub_err_t
 grub_efi_console_init (struct grub_term_output *term)
 {
+  grub_efi_set_text_mode (1);
   grub_console_setcursor (term, 1);
   return 0;
 }
@@ -242,6 +243,7 @@ static grub_err_t
 grub_efi_console_fini (struct grub_term_output *term)
 {
   grub_console_setcursor (term, 0);
+  grub_efi_set_text_mode (0);
   return 0;
 }
 
index 73c5d08e523c3b4d4dc7f1acc1de9af6892945e7..3e1cc2357b0eb3ee529d491b8b9680e6b94e415e 100644 (file)
@@ -49,6 +49,7 @@ static struct
   struct grub_video_mode_info mode_info;
   struct grub_video_render_target *render_target;
   grub_uint8_t *ptr;
+  grub_uint8_t *offscreen;
 } framebuffer;
 
 
@@ -105,6 +106,8 @@ grub_video_gop_fini (void)
       efi_call_2 (gop->set_mode, gop, old_mode);
       restore_needed = 0;
     }
+  grub_free (framebuffer.offscreen);
+  framebuffer.offscreen = 0;
   return grub_video_fb_fini ();
 }
 
@@ -165,9 +168,9 @@ grub_video_gop_get_bitmask (grub_uint32_t mask, unsigned int *mask_size,
 }
 
 static grub_err_t
-grub_video_gop_fill_mode_info (unsigned mode,
-                              struct grub_efi_gop_mode_info *in,
-                              struct grub_video_mode_info *out)
+grub_video_gop_fill_real_mode_info (unsigned mode,
+                                   struct grub_efi_gop_mode_info *in,
+                                   struct grub_video_mode_info *out)
 {
   out->mode_number = mode;
   out->number_of_colors = 256;
@@ -223,6 +226,35 @@ grub_video_gop_fill_mode_info (unsigned mode,
   return GRUB_ERR_NONE;
 }
 
+static grub_err_t
+grub_video_gop_fill_mode_info (unsigned mode,
+                              struct grub_efi_gop_mode_info *in,
+                              struct grub_video_mode_info *out)
+{
+  out->mode_number = mode;
+  out->number_of_colors = 256;
+  out->width = in->width;
+  out->height = in->height;
+  out->mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
+  out->bytes_per_pixel = sizeof (struct grub_efi_gop_blt_pixel);
+  out->bpp = out->bytes_per_pixel << 3;
+  out->pitch = in->width * out->bytes_per_pixel;
+  out->red_mask_size = 8;
+  out->red_field_pos = 16;
+  out->green_mask_size = 8;
+  out->green_field_pos = 8;
+  out->blue_mask_size = 8;
+  out->blue_field_pos = 0;
+  out->reserved_mask_size = 8;
+  out->reserved_field_pos = 24;
+
+  out->blit_format = GRUB_VIDEO_BLIT_FORMAT_BGRA_8888;
+  out->mode_type |= (GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
+                    | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
+
+  return GRUB_ERR_NONE;
+}
+
 static int
 grub_video_gop_iterate (int (*hook) (const struct grub_video_mode_info *info))
 {
@@ -327,6 +359,7 @@ grub_video_gop_setup (unsigned int width, unsigned int height,
   int found = 0;
   unsigned long long best_volume = 0;
   unsigned int preferred_width = 0, preferred_height = 0;
+  grub_uint8_t *buffer;
 
   depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
     >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS;
@@ -442,13 +475,28 @@ grub_video_gop_setup (unsigned int width, unsigned int height,
     }
 
   framebuffer.ptr = (void *) (grub_addr_t) gop->mode->fb_base;
-
+  framebuffer.offscreen
+    = grub_malloc (framebuffer.mode_info.height
+                  * framebuffer.mode_info.width 
+                  * sizeof (struct grub_efi_gop_blt_pixel));
+
+  buffer = framebuffer.offscreen;
+      
+  if (!buffer)
+    {
+      grub_dprintf ("video", "GOP: couldn't allocate shadow\n");
+      grub_errno = 0;
+      err = grub_video_gop_fill_mode_info (gop->mode->mode, info,
+                                          &framebuffer.mode_info);
+      buffer = framebuffer.ptr;
+    }
+    
   grub_dprintf ("video", "GOP: initialising FB @ %p %dx%dx%d\n",
                framebuffer.ptr, framebuffer.mode_info.width,
                framebuffer.mode_info.height, framebuffer.mode_info.bpp);
  
   err = grub_video_fb_create_render_target_from_pointer
-    (&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr);
+    (&framebuffer.render_target, &framebuffer.mode_info, buffer);
 
   if (err)
     {
@@ -478,7 +526,13 @@ grub_video_gop_setup (unsigned int width, unsigned int height,
 static grub_err_t
 grub_video_gop_swap_buffers (void)
 {
-  /* TODO: Implement buffer swapping.  */
+  if (framebuffer.offscreen)
+    {
+      efi_call_10 (gop->blt, gop, framebuffer.offscreen,
+                  GRUB_EFI_BLT_BUFFER_TO_VIDEO, 0, 0, 0, 0,
+                  framebuffer.mode_info.width, framebuffer.mode_info.height,
+                  framebuffer.mode_info.width * 4);
+    }
   return GRUB_ERR_NONE;
 }
 
@@ -495,11 +549,23 @@ static grub_err_t
 grub_video_gop_get_info_and_fini (struct grub_video_mode_info *mode_info,
                                  void **framebuf)
 {
-  grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info));
+  grub_err_t err;
+
+  err = grub_video_gop_fill_real_mode_info (gop->mode->mode, gop->mode->info,
+                                           mode_info);
+  if (err)
+    {
+      grub_dprintf ("video", "GOP: couldn't fill mode info\n");
+      return err;
+    }
+
   *framebuf = (char *) framebuffer.ptr;
 
   grub_video_fb_fini ();
 
+  grub_free (framebuffer.offscreen);
+  framebuffer.offscreen = 0;
+
   return GRUB_ERR_NONE;
 }
 
index a292219195963dcf2411e0a654942f6055948c94..129777411928a7059dfc347b614db8d049466279 100644 (file)
@@ -32,6 +32,24 @@ typedef enum
   }
   grub_efi_gop_pixel_format_t;
 
+typedef enum
+  {
+    GRUB_EFI_BLT_VIDEO_FILL,
+    GRUB_EFI_BLT_VIDEO_TO_BLT_BUFFER,
+    GRUB_EFI_BLT_BUFFER_TO_VIDEO,
+    GRUB_EFI_BLT_VIDEO_TO_VIDEO,
+    GRUB_EFI_BLT_OPERATION_MAX
+  }
+  grub_efi_gop_blt_operation_t;
+
+struct grub_efi_gop_blt_pixel
+{
+  grub_uint8_t blue;
+  grub_uint8_t green;
+  grub_uint8_t red;
+  grub_uint8_t reserved;
+};
+
 struct grub_efi_gop_pixel_bitmask
 {
   grub_uint32_t r;