grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: New patch for video subsystem...


From: Vesa Jääskeläinen
Subject: Re: New patch for video subsystem...
Date: Fri, 03 Mar 2006 17:23:36 +0200
User-agent: Thunderbird 1.5 (Windows/20051201)

Marco Gerards wrote:
> Vesa Jääskeläinen <address@hidden> writes:
> 
> Hi Vesa,
> 
> Thanks for your patch.  I have done a review, but you should know that
> I am not a graphics expert and don't understand all of the code in
> detail.  Most issues are GCS related, they don't only apply to the
> line I commented on, but in general.  Please make sure all the code is
> fixed and not this single line.

That wasn't a small job ;).. I hope I got all right.

> I hope other people will do a quick review as well, so the code can be
> committed soon in a state everyone is happy with.

Sounds fine.

I have made modifications and attached it as a new diff in this message.

Thanks,
Vesa Jääskeläinen

>> How to use it:
>> In order to have graphical console, you need to first load video driver
>> (that would be vbe module) and then load videoterm module. After that
>> you will need to tell what video mode you would like to use. And last
>> you just initialize it with "terminal videoterm".
>>
>> Example command sequence:
>> insmod font
>> font /boot/grub/unifont.pff
>> insmod terminal
>> insmod vbe
>> insmod videoterm
>> set video_mode=1024x768
>> terminal videoterm
>>
>> How to fine tune video mode:
>> Handling of video_mode environment variable is a flexible one. You can
>> specify multiple settings at one line. If video_mode is not set, it will
>> use 1024x768 as a default resolution and will use highes number of
>> colors available. Supported options are following:
> 
> Personally I would prefer a VGA compatible default.  The reason for
> that is that not always videoterm.mod is loaded from grub.cfg.  For
> example, the module might be added to the (GRUB 2) kernel when loading
> GRUB via the network.

Well that default is in videoterm, and if it is not loaded then I do not
see that as a problem. We can change the default resolution easily if
that is the case. And if you need it for other purposes currently you
will need to tell what mode you want.

Nowadays 1024x768 is a normal standard resolution.

> As for the name, I do not think videoterm is a good name.  For my
> feeling something like `fbterm' or so is better.  Perhaps someone else
> has some good suggestions.

I am all ears for suggestions.

>> width=<value>
>> height=<value>
>> index
>> rgb
>> <width>x<height>x<depth>
>>
>> And you can make combo's of those like:
>>
>> set video_mode="width=1024 height=768 rgb"
> 
> I prefer to just use a simplified notation.  So 1024x768x24.  Most
> people understand this notation, it will make scripting easier and
> doesn't require that much code for parsing.

Reason why I added more complex one is that there might be settings that
would be good to be parsed to flags field.

>> +2006-02-25  Vesa Jaaskelainen  <address@hidden>
>> +
>> +    * DISTLIST: Added include/grub/video.h, term/videoterm.c,
>> +    video/video.c.
>> +    Removed term/i386/pc/vesafb.c.
>> +
>> +    * conf/i386-pc.rmk (pkgdata_MODULES): Added video.mod,
>> +    videoterm.mod.
>> +    Removed vga.mod, vesafb.mod.
> 
> Just put the removed line on the same line as where you say things
> were added.  It looks a bit nicer and that is what we in general do.

Ok.

> 
>> +    * font/manager.c (fill_with_default_glyph): Modified to use
>> +    grub_font_glyph.
>> +    (grub_font_get_glyph): Modified to use grub_font_glyph.
>> +    (fontmanager): Renamed to font_manager.
>> +
>> +    * include/grub/font.h (grub_font_glyph): Added.
> 
> Please say `New function.' or `New variable.'.  It's in general better
> to do that, you can immediatly see what it is.

Ok.

>> +    * include/grub/i386/pc/vbe.h (GRUB_VBE_STATUS_OK): Added.
>> +    (GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL): Likewise.
>> +    (GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR): Likewise.
> 
> `New macro.' would be better.

Ok.

> 
>> +    (grub_vbe_get_controller_info): Renamed to
>> +    grub_vbe_bios_get_controller_info.
> 
> we use this syntax:
> 
>       (grub_vbe_get_controller_info): Renamed from this...
>       (grub_vbe_bios_get_controller_info): ... to this.  All users
>         changed to use the new function name.
> 
> It's important that it is visible that the new function did not just
> pop up.  So now you can look back in the changelog entry where it was
> added.

Ok. I left out additional description as it would have made huge entries.

>> +    * include/grub/video.h: Added.
> 
> `New file.' is more consistent with the rest of GRUB.

Ok.

> 
>> +    * normal/cmdline.c (cl_set_pos): Made it refresh screen, to enable
>> +    better visual experience to video drivers.
> 
> Just use something like `Refresh the screen.'.  It's a general bug
> fix, not only for the video drivers (although it unfortunately shows
> up there :)).

Ok.

>> +    * term/videoterm.c: Added.
>> +
>> +    * video/video.c: Added
> 
> `New file.' again.

Ok.

>> +    * video/i386/pc/vbe.c: Refactored to new video subsystem.
> 
> Just leave away this line.  Usually this is done by using `All users
> changed.' when interfaces change or functions are renamed.

Hmm. But then there is no mentioning about changes done in this file at
all?. (I have removed it from current diff.)

>> -# For vga.mod.
>> -vga_mod_SOURCES = term/i386/pc/vga.c
>> -vga_mod_CFLAGS = $(COMMON_CFLAGS)
>> -vga_mod_LDFLAGS = $(COMMON_LDFLAGS)
> 
> Why do you remove this?

After modifying the fontmanager it would have needed to make some
changes to VGA code. And I am not familiar with VGA planes and such, so
I left it out.

>>  include $(srcdir)/conf/common.mk
>> diff -ruN -x '*CVS*' grub2/font/manager.c grub2.new/font/manager.c
>> --- grub2/font/manager.c     2005-11-13 17:47:09.000000000 +0200
>> +++ grub2.new/font/manager.c 2006-02-25 14:16:16.000000000 +0200
>> @@ -24,6 +24,7 @@
>>  #include <grub/types.h>
>>  #include <grub/mm.h>
>>  #include <grub/font.h>
>> +//#include <grub/gzio.h>
> 
> Can you remove this line?

Sure.

>>  struct entry
>>  {
>> @@ -50,6 +51,7 @@
>>    struct font *font = 0;
>>  
>>    file = grub_file_open (filename);
>> +  //file = grub_gzfile_open (filename, 1);
> 
> And this one.

Ok.

> 
>>  /* Get a glyph corresponding to the codepoint CODE. Always fill BITMAP
>>     and WIDTH with something, even if no glyph is found.  */
>>  int
>>  grub_font_get_glyph (grub_uint32_t code,
>> -                 unsigned char bitmap[32], unsigned *width)
>> +                 grub_font_glyph_t glyph)
> 
> The prototype was changed, but the comment wasn't.

Oh, yes... Fixed.

>>  {
>>    struct font *font;
>> +  grub_uint8_t bitmap[32];
>>  
>>    /* FIXME: It is necessary to cache glyphs!  */
>>    
>> @@ -183,12 +186,19 @@
>>        if (offset)
>>      {
>>        grub_uint32_t w;
>> +      grub_uint8_t x;
>> +      grub_uint8_t y;
>> +      grub_uint32_t len;
> 
> Please just use int here.  You read w from disk, so I understand why
> it is a grub_uint32_t, but the others don't come from disk, right?

Ok.

>> -      if (grub_file_read (font->file, (char *) &w, 4) != 4)
>> +      if ((len = grub_file_read (font->file, (char *) &w, 4)) != 4)
> 
> I'm sorry that I am commenting on old code, but can you change this to
> some sizeof test or so?

Changed to sizeof (grub_uint32_t).

>> +      glyph->baseline = (16*3)/4;
> 
> Can you place some spaces around the operators, so:
> 
>         glyph->baseline = (16 * 3) / 4;

Sure. I must have forgotten this one.

>> +struct grub_font_glyph
>> +{
>> +  /* Glyph width in pixels.  */
>> +  grub_uint8_t width;
>> +  
>> +  /* Glyph height in pixels.  */
>> +  grub_uint8_t height;
>> +  
>> +  /* Glyph width in characters.  */
>> +  grub_uint8_t char_width;
>> +  
>> +  /* Glyph baseline position in pixels (from up).  */
>> +  grub_uint8_t baseline;
>> +  
>> +  /* Glyph bitmap data array of bytes in ((width + 7) / 8) * height.
>> +     Bitmap is formulated by height scanlines, each scanline having
>> +     width number of pixels. Pixels are coded as bits, value 1 meaning
>> +     of opaque pixel and 0 is transparent. If width does not fit byte
>> +     boundary, it will be padded with 0 to make it fit.  */
>> +  grub_uint8_t bitmap[32];
>> +};
>> +
>> +typedef struct grub_font_glyph *grub_font_glyph_t;
> 
> I hope Okuji will look at this, I am clueless about the font manager
> as for now. :-)
> 
>>  #endif /* ! GRUB_MISC_HEADER */
>> diff -ruN -x '*CVS*' grub2/include/grub/video.h 
>> grub2.new/include/grub/video.h
>> --- grub2/include/grub/video.h       1970-01-01 02:00:00.000000000 +0200
>> +++ grub2.new/include/grub/video.h   2006-03-02 15:33:32.650225312 +0200
>> @@ -0,0 +1,300 @@
>> +/*
>> + *  GRUB  --  GRand Unified Bootloader
>> + *  Copyright (C) 2002,2003,2005  Free Software Foundation, Inc.
> 
> I think it should just be 2006, right?

Yep ;)

>> +typedef grub_uint32_t grub_color_t;
> 
> I think grub_video_color_t is better.

It is a long one, but changed.

>> +struct grub_video_mode_info {
> 
> It think it is more appropriate to use `int' instead of
> `grub_uint32_t' for the members of this struct.

Ok.

>> +};
> 
>> +  grub_err_t (*get_info) (struct grub_video_mode_info * mode_info);
> 
> Can you remove the space between `*' and `mode_info'?

Ok.

>> +  grub_err_t (*get_viewport) (unsigned int * x,
>> +                          unsigned int * y,
>> +                          unsigned int * width,
>> +                          unsigned int * height);
> 
> Same here.  Please look at other places where you did this too.

Ok.

>> +struct grub_virtual_screen
>> +{
>> +  /* Dimensions of the virual screen.  */
> 
> Typo.
> 
> Can you change grub_uint32_t to ints inside this struct?

Fixed. Ok.

>> +};
> 
> 
>> +/* Make seure text buffer is not marked as allocated.  */
> 
> Typo: seure->sure

Fixed.

>> +static struct grub_virtual_screen virtual_screen =
>> +  {
>> +    .text_buffer = 0
>> +  };
> 
> You can leave away the initiazation, it is done automatically.
> 
>> +static struct grub_video_render_target *text_layer = 0;
> 
> Same here.

Ok.

>> +  /* Cleare new render target for text layer.  */
> 
> Typo: Cleare->Create (right?)

Fixed.

>> +  grub_video_create_render_target (&text_layer,
>> +                                   GRUB_VIDEO_MODE_TYPE_RGB
>> +                                   | GRUB_VIDEO_MODE_TYPE_ALPHA,
>> +                                   virtual_screen.width,
>> +                                   virtual_screen.height);
> 
>> +static grub_err_t
>> +grub_videoterm_init (void)
>> +{
>> +  char *modevar;
>> +  int width = 1024;
>> +  int height = 768;
> 
> Please make macros for these defaults.  In that case it can be easily
> changed without looking at the code.

Ok.

>> +  /* Leave borders for virtual screen.  */
>> +  width = mode_info.width - (2 * 10);
>> +  height = mode_info.height - (2 * 10);
> 
> Can you explain this?  Isn't it better to use some font width
> multiple?

It was something from the "hat". Basic idea here is here to show that it
can be anything. In future this most likely changes to something
completely different as we want(?) to have more flexibility on configure
things.

>> +      if (x < dirty_region.top_left_x)
>> +        {
>> +          dirty_region.top_left_x = x;
>> +        }
> 
> You don't have to use { and } for a singe line.  It makes this code
> hard to read.  So please don't use it for such if statements.

I think the opposite, but changed.

>> diff -ruN -x '*CVS*' grub2/video/i386/pc/vbe.c grub2.new/video/i386/pc/vbe.c
>> --- grub2/video/i386/pc/vbe.c        2005-09-19 00:04:41.000000000 +0300
>> +++ grub2.new/video/i386/pc/vbe.c    2006-03-02 20:35:43.719014568 +0200
>> @@ -1,6 +1,6 @@
>>  /*
>>   *  GRUB  --  GRand Unified Bootloader
>> - *  Copyright (C) 2005  Free Software Foundation, Inc.
>> + *  Copyright (C) 2005-2006  Free Software Foundation, Inc.
> 
> Please use commas to separate lines.  For legal reasons a range of
> years is unfortunately not allowed.

Oh. Fixed.

>> +      render_target->mode_info.bpp = active_mode_info.bits_per_pixel;
>> +      render_target->mode_info.bytes_per_pixel = 
>> framebuffer.bytes_per_pixel;
>> +      render_target->mode_info.pitch = framebuffer.bytes_per_scan_line;
>> +      render_target->mode_info.number_of_colors = 256; /* TODO: fix me.  */
>> +      render_target->mode_info.red_mask_size = 
>> active_mode_info.red_mask_size;
>> +      render_target->mode_info.red_field_pos = 
>> active_mode_info.red_field_position;
>> +      render_target->mode_info.green_mask_size = 
>> active_mode_info.green_mask_size;
>> +      render_target->mode_info.green_field_pos = 
>> active_mode_info.green_field_position;
>> +      render_target->mode_info.blue_mask_size = 
>> active_mode_info.blue_mask_size;
>> +      render_target->mode_info.blue_field_pos = 
>> active_mode_info.blue_field_position;
>> +      render_target->mode_info.reserved_mask_size = 
>> active_mode_info.rsvd_mask_size;
>> +      render_target->mode_info.reserved_field_pos = 
>> active_mode_info.rsvd_field_position;
> 
> Isn't it possible to copy this in a single statement?

No. As structure types are different.

>> +  /* If we have negative coordintes, optimize drawing to minimum.  */
> 
> Typo.

Fixed.

> 
>> +  width = render_target->viewport.width - grub_abs(dx);
>> +  height = render_target->viewport.height - grub_abs(dy);
> 
> Please add a space after `grub_abs'.

Ok.

>> +  // TODO: PROOFREAD THIS!.
> 
> Ehm? :-)

Whups :).

>> +static grub_err_t 
>> +grub_video_vbe_swap_buffers (void)
>> +{
>> +  /* TODO: Implement buffer swapping.  */
> 
> Sin't this just activating another region in the video memory?  I
> think it would be quite trivial when using VESA.

Depends if we have enough memory on card. But will be done. I was
intending to implement this functionality after we have version
in CVS.

>> +  /* TODO: Implement other types too.  */
>> +  size = (width * 4) * height;
> 
> Please use sizeof here.

I made different change :).

>> +  /* Setup render target format.  */
>> +  target->mode_info.width = width;
>> +  target->mode_info.height = height;
>> +  target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB 
>> +                                | GRUB_VIDEO_MODE_TYPE_ALPHA;
>> +  target->mode_info.bpp = 32;
>> +  target->mode_info.bytes_per_pixel = 4;
>> +  target->mode_info.pitch = target->mode_info.bytes_per_pixel * width;
>> +  target->mode_info.number_of_colors = 256;
>> +  target->mode_info.red_mask_size = 8;
>> +  target->mode_info.red_field_pos = 0;
>> +  target->mode_info.green_mask_size = 8;
>> +  target->mode_info.green_field_pos = 8;
>> +  target->mode_info.blue_mask_size = 8;
>> +  target->mode_info.blue_field_pos = 16;
>> +  target->mode_info.reserved_mask_size = 8;
>> +  target->mode_info.reserved_field_pos = 24;
> 
> These are all defaults, right?  First of all, I prefer macros instead
> of hardcoded values.

In most cases I would agree, but this one is something that should not
be modified. But if that is a real problem, then of course I will change it.

> bpp is set to 32, while number of colors says 256, are you sure this
> is correct?  I prefer a bpp of 8 as default, for compatibility
> reasons.

number_of_colors tells how many indexed colors we have in mode. In RGB
rendering target we have always 256 emulated indexed colors.

As there is a comment in file (now perhaps better written), currently
only RGB rendering targets are supported. This is not a huge problem as
blit function can handle it even for indexed color modes.

>> +static grub_err_t
>> +grub_video_vbe_delete_render_target (struct grub_video_render_target * 
>> target)
>> +{
>> +  /* If there is no target, then just return without error.  */
>> +  if (! target)
>> +    {
>> +      return GRUB_ERR_NONE;
>> +    }
> 
> No braces, like before.  Same for the code below.

Ok.

>> +static grub_err_t
>> +grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)),
>> +                    int argc __attribute__ ((unused)),
>> +                    char **args __attribute__ ((unused)))
> 
> It's better to move this to another file, like commands/videotest.c.
> Or do you think this is only useful for debugging, in that case better
> put it in some #ifdef.

Moved as new module.
diff -ruN -x '*CVS*' grub2/ChangeLog grub2.new/ChangeLog
--- grub2/ChangeLog     2006-02-09 00:42:47.000000000 +0200
+++ grub2.new/ChangeLog 2006-03-03 16:51:42.214034272 +0200
@@ -1,3 +1,110 @@
+2006-02-25  Vesa Jaaskelainen  <address@hidden>
+
+       * DISTLIST: Added include/grub/video.h, term/videoterm.c,
+       video/video.c. Removed term/i386/pc/vesafb.c.
+
+       * conf/i386-pc.rmk (pkgdata_MODULES): Added video.mod,
+       videoterm.mod, videotest.mod. Removed vga.mod, vesafb.mod.
+       (video_mod_SOURCES): Added.
+       (video_mod_CFLAGS): Likewise.
+       (video_mod_LDFLAGS): Likewise.
+       (videoterm_mod_SOURCES): Likewise.
+       (videoterm_mod_CFLAGS): Likewise.
+       (videoterm_mod_LDFLAGS): Likewise.
+       (videotest_mod_SOURCES): Likewise.
+       (videotest_mod_CFLAGS): Likewise.
+       (videotest_mod_LDFLAGS): Likewise.
+       (vesafb_mod_SOURCES): Removed.
+       (vesafb_mod_CFLAGS): Likewise.
+       (vesafb_mod_LDFLAGS): Likewise.
+       (vga_mod_SOURCES): Likewise.
+       (vga_mod_CFLAGS): Likewise.
+       (vga_mod_LDFLAGS): Likewise.
+
+       * commands/videotest.c: New file.
+
+       * font/manager.c (fill_with_default_glyph): Modified to use
+       grub_font_glyph.
+       (grub_font_get_glyph): Likewise.
+       (fontmanager): Renamed from this...
+       (font_manager): ... to this.
+
+       * include/grub/font.h (grub_font_glyph): Added new structure.
+       (grub_font_get_glyph): Modified to use grub_font_glyph.
+
+       * include/grub/misc.h (grub_abs): Added as inline function.
+
+       * include/grub/i386/pc/vbe.h (GRUB_VBE_STATUS_OK): New macro.
+       (GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL): Likewise.
+       (GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR): Likewise.
+       (grub_vbe_get_controller_info): Renamed from this...
+       (grub_vbe_bios_get_controller_info): ... to this.
+       (grub_vbe_get_mode_info): Renamed from this...
+       (grub_vbe_bios_get_mode_info): ... to this.
+       (grub_vbe_set_mode): Renamed from this...
+       (grub_vbe_bios_set_mode): ... to this.
+       (grub_vbe_get_mode): Renamed from this...
+       (grub_vbe_bios_get_mode): ... to this.
+       (grub_vbe_set_memory_window): Renamed from this...
+       (grub_vbe_bios_set_memory_window): ... to this.
+       (grub_vbe_get_memory_window): Renamed from this...
+       (grub_vbe_bios_get_memory_window): ... to this.
+       (grub_vbe_set_scanline_length): Renamed from this...
+       (grub_vbe_set_scanline_length): ... to this.
+       (grub_vbe_get_scanline_length): Renamed from this...
+       (grub_vbe_bios_get_scanline_length): ... to this.
+       (grub_vbe_set_display_start): Renamed from this...
+       (grub_vbe_bios_set_display_start): ... to this.
+       (grub_vbe_get_display_start): Renamed from this...
+       (grub_vbe_bios_get_display_start): ... to this.
+       (grub_vbe_set_palette_data): Renamed from this...
+       (grub_vbe_bios_set_palette_data): ... to this.
+       (grub_vbe_set_pixel_rgb): Removed.
+       (grub_vbe_set_pixel_index): Likewise.
+
+       * include/grub/video.h: New file.
+
+       * kern/i386/pc/startup.S (grub_vbe_get_controller_info): Renamed
+       from this...
+       (grub_vbe_bios_get_controller_info): ... to this.
+       (grub_vbe_get_mode_info): Renamed from this...
+       (grub_vbe_bios_get_mode_info): ... to this.
+       (grub_vbe_set_mode): Renamed from this...
+       (grub_vbe_bios_set_mode): ... to this.
+       (grub_vbe_get_mode): Renamed from this...
+       (grub_vbe_bios_get_mode): ... to this.
+       (grub_vbe_set_memory_window): Renamed from this...
+       (grub_vbe_bios_set_memory_window): ... to this.
+       (grub_vbe_get_memory_window): Renamed from this...
+       (grub_vbe_bios_get_memory_window): ... to this.
+       (grub_vbe_set_scanline_length): Renamed from this...
+       (grub_vbe_set_scanline_length): ... to this.
+       (grub_vbe_get_scanline_length): Renamed from this...
+       (grub_vbe_bios_get_scanline_length): ... to this.
+       (grub_vbe_set_display_start): Renamed from this...
+       (grub_vbe_bios_set_display_start): ... to this.
+       (grub_vbe_get_display_start): Renamed from this...
+       (grub_vbe_bios_get_display_start): ... to this.
+       (grub_vbe_set_palette_data): Renamed from this...
+       (grub_vbe_bios_set_palette_data): ... to this.
+       (grub_vbe_bios_get_controller_info): Fixed problem with registers
+       getting corrupted after calling it. Added more pushes and pops.
+       (grub_vbe_bios_set_mode): Likewise.
+       (grub_vbe_bios_get_mode): Likewise.
+       (grub_vbe_bios_get_memory_window): Likewise.
+       (grub_vbe_bios_set_scanline_length): Likewise.
+       (grub_vbe_bios_get_scanline_length): Likewise.
+       (grub_vbe_bios_get_display_start): Likewise.
+       (grub_vbe_bios_set_palette_data): Likewise.
+
+       * normal/cmdline.c (cl_set_pos): Refresh the screen.
+       (cl_insert): Likewise.
+       (cl_delete): Likewise.
+
+       * term/videoterm.c: New file.
+
+       * video/video.c: New file.
+
 2006-02-01  Yoshinori K. Okuji  <address@hidden>
 
        * boot/i386/pc/boot.S (general_error): Before looping, try INT
diff -ruN -x '*CVS*' grub2/DISTLIST grub2.new/DISTLIST
--- grub2/DISTLIST      2005-12-26 01:04:28.000000000 +0200
+++ grub2.new/DISTLIST  2006-02-25 13:29:16.000000000 +0200
@@ -106,6 +106,7 @@
 include/grub/terminfo.h
 include/grub/tparm.h
 include/grub/types.h
+include/grub/video.h
 include/grub/i386/setjmp.h
 include/grub/i386/types.h
 include/grub/i386/pc/biosdisk.h
@@ -208,6 +209,7 @@
 partmap/sun.c
 term/terminfo.c
 term/tparm.c
+term/videoterm.c
 term/i386/pc/console.c
 term/i386/pc/serial.c
 term/i386/pc/vesafb.c
@@ -229,4 +231,5 @@
 util/i386/pc/misc.c
 util/powerpc/ieee1275/grub-mkimage.c
 util/powerpc/ieee1275/misc.c
+video/video.c
 video/i386/pc/vbe.c
diff -ruN -x '*CVS*' grub2/commands/videotest.c grub2.new/commands/videotest.c
--- grub2/commands/videotest.c  1970-01-01 02:00:00.000000000 +0200
+++ grub2.new/commands/videotest.c      2006-03-03 16:56:57.792059120 +0200
@@ -0,0 +1,133 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/machine/memory.h>
+#include <grub/video.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/arg.h>
+#include <grub/mm.h>
+#include <grub/font.h>
+#include <grub/term.h>
+
+static grub_err_t
+grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)),
+                    int argc __attribute__ ((unused)),
+                    char **args __attribute__ ((unused)))
+{
+  if (grub_video_setup (1024, 
+                        768,
+                        GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != GRUB_ERR_NONE)
+    {
+      return grub_errno;
+    }
+  
+  grub_getkey ();
+
+  grub_video_color_t color;
+  unsigned int x, y, width, height;
+  int i;
+  struct grub_font_glyph glyph;
+  struct grub_video_render_target *text_layer;
+  grub_video_color_t palette[16];
+  
+  grub_video_get_viewport (&x, &y, &width, &height);
+
+  grub_video_create_render_target (&text_layer,
+                                   GRUB_VIDEO_MODE_TYPE_RGB
+                                   | GRUB_VIDEO_MODE_TYPE_ALPHA,
+                                   width,
+                                   height);
+
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);      
                             
+
+  color = grub_video_map_rgb (0, 0, 0);
+  grub_video_fill_rect (color, 0, 0, width, height);
+  
+  color = grub_video_map_rgb (255,0,0);
+  grub_video_fill_rect (color, 0, 0, 100, 100);
+  
+  color = grub_video_map_rgb (0,255,255);
+  grub_video_fill_rect (color, 100, 100, 100, 100);
+
+  grub_font_get_glyph ('*', &glyph);  
+  grub_video_blit_glyph (&glyph, color, 200 ,0);
+
+  grub_video_set_viewport (x + 150, y + 150, width - 150*2, height - 150*2);
+  color = grub_video_map_rgb (77,33,77);
+  grub_video_fill_rect (color, 0, 0, width, height);
+  
+  grub_video_set_active_render_target (text_layer);
+  
+  color = grub_video_map_rgb (255,255,255);
+  
+  grub_font_get_glyph ('A', &glyph);  
+  grub_video_blit_glyph (&glyph, color, 16, 16);
+  grub_font_get_glyph ('B', &glyph);  
+  grub_video_blit_glyph (&glyph, color, 16*2, 16);
+
+  grub_font_get_glyph ('*', &glyph);  
+  
+  for (i = 0; i < 16; i++)
+    {
+      color = grub_video_map_color (i);
+      palette[i] = color;
+      grub_video_blit_glyph (&glyph, color, 16 + i * 16, 32);
+    }
+
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+  for (i = 0; i < 255; i++)
+    {
+      color = grub_video_map_rgb (i, 33, 77);
+      grub_video_fill_rect (color, 0, 0, width, height);
+      grub_video_blit_render_target (text_layer, 0, 0, 0, 0, width, height);
+    }
+  
+  grub_getkey ();
+  
+  grub_video_delete_render_target (text_layer);
+  
+  grub_video_restore ();
+  
+  for (i = 0; i < 16; i++)
+    {
+      grub_printf("color %d: %08x\n", i, palette[i]);
+    }
+  
+  grub_errno = GRUB_ERR_NONE;
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(videotest)
+{
+  grub_register_command ("videotest",
+                         grub_cmd_videotest,
+                         GRUB_COMMAND_FLAG_BOTH,
+                         "videotest",
+                         "Test video subsystem",
+                         0);
+}
+
+GRUB_MOD_FINI(videotest)
+{
+  grub_unregister_command ("videotest");
+}
diff -ruN -x '*CVS*' grub2/conf/i386-pc.rmk grub2.new/conf/i386-pc.rmk
--- grub2/conf/i386-pc.rmk      2005-12-26 01:04:29.000000000 +0200
+++ grub2.new/conf/i386-pc.rmk  2006-03-03 16:56:09.548393272 +0200
@@ -113,9 +113,10 @@
 grub_install_SOURCES = util/i386/pc/grub-install.in
 
 # Modules.
-pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod vga.mod   \
+pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod \
        _multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod      \
-       vbe.mod vesafb.mod vbetest.mod vbeinfo.mod play.mod
+       vbe.mod vbetest.mod vbeinfo.mod video.mod videoterm.mod \
+       videotest.mod play.mod
 
 # For _chain.mod.
 _chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -157,11 +158,6 @@
 halt_mod_CFLAGS = $(COMMON_CFLAGS)
 halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
-# For vga.mod.
-vga_mod_SOURCES = term/i386/pc/vga.c
-vga_mod_CFLAGS = $(COMMON_CFLAGS)
-vga_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
 # For serial.mod.
 serial_mod_SOURCES = term/i386/pc/serial.c
 serial_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -182,11 +178,6 @@
 vbe_mod_CFLAGS = $(COMMON_CFLAGS)
 vbe_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
-# For vesafb.mod.
-vesafb_mod_SOURCES = term/i386/pc/vesafb.c
-vesafb_mod_CFLAGS = $(COMMON_CFLAGS)
-vesafb_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
 # For vbeinfo.mod.
 vbeinfo_mod_SOURCES = commands/i386/pc/vbeinfo.c
 vbeinfo_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -202,4 +193,19 @@
 play_mod_CFLAGS = $(COMMON_CFLAGS)
 play_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For video.mod.
+video_mod_SOURCES = video/video.c
+video_mod_CFLAGS = $(COMMON_CFLAGS)
+video_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For videoterm.mod.
+videoterm_mod_SOURCES = term/videoterm.c
+videoterm_mod_CFLAGS = $(COMMON_CFLAGS)
+videoterm_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For videotest.mod.
+videotest_mod_SOURCES = commands/videotest.c
+videotest_mod_CFLAGS = $(COMMON_CFLAGS)
+videotest_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff -ruN -x '*CVS*' grub2/font/manager.c grub2.new/font/manager.c
--- grub2/font/manager.c        2005-11-13 17:47:09.000000000 +0200
+++ grub2.new/font/manager.c    2006-03-03 15:55:20.440376240 +0200
@@ -151,26 +151,27 @@
 
 /* Set the glyph to something stupid.  */
 static void
-fill_with_default_glyph (unsigned char bitmap[32], unsigned *width)
+fill_with_default_glyph (grub_font_glyph_t glyph)
 {
-  if (bitmap)
-    {
-      unsigned i;
+  unsigned i;
 
-      for (i = 0; i < 16; i++)
-       bitmap[i] = (i & 1) ? 0x55 : 0xaa;
-    }
-      
-  *width = 1;
+  for (i = 0; i < 16; i++)
+    glyph->bitmap[i] = (i & 1) ? 0x55 : 0xaa;
+
+  glyph->char_width = 1;
+  glyph->width = glyph->char_width * 8;
+  glyph->height = 16;
+  glyph->baseline = (16*3)/4;
 }
 
-/* Get a glyph corresponding to the codepoint CODE. Always fill BITMAP
-   and WIDTH with something, even if no glyph is found.  */
+/* Get a glyph corresponding to the codepoint CODE. Always fill glyph
+   information with something, even if no glyph is found.  */
 int
 grub_font_get_glyph (grub_uint32_t code,
-                    unsigned char bitmap[32], unsigned *width)
+                    grub_font_glyph_t glyph)
 {
   struct font *font;
+  grub_uint8_t bitmap[32];
 
   /* FIXME: It is necessary to cache glyphs!  */
   
@@ -183,12 +184,19 @@
       if (offset)
        {
          grub_uint32_t w;
+         unsigned int x;
+         unsigned int y;
+         int len;
+
+          /* Make sure we can find glyphs for error messages. Push active
+             error message to error stack and reset error message.  */
+          grub_error_push ();
          
          grub_file_seek (font->file, offset);
-         if (grub_file_read (font->file, (char *) &w, 4) != 4)
+         if ((len = grub_file_read (font->file, (char *) &w, sizeof (w))) != 4)
            {
-             remove_font (font);
-             goto restart;
+              remove_font (font);
+              goto restart;
            }
 
          w = grub_le_to_cpu32 (w);
@@ -206,14 +214,30 @@
              remove_font (font);
              goto restart;
            }
-
-         *width = w;
+           
+          /* Temporary workaround, fix font bitmap.  */
+          for (y = 0; y < 16; y++)
+            {
+              for (x = 0; x < w; x++)
+                {
+                  glyph->bitmap[y * w + x] = bitmap[x * 16 + y];
+                }
+            }
+          
+         glyph->char_width = w;
+         glyph->width = glyph->char_width * 8;
+         glyph->height = 16;
+         glyph->baseline = (16 * 3) / 4;
+         
+         /* Restore old error message.  */
+          grub_error_pop ();
+          
          return 1;
        }
     }
 
   /* Uggh... No font was found.  */
-  fill_with_default_glyph (bitmap, width);
+  fill_with_default_glyph (glyph);
   return 0;
 }
 
@@ -232,7 +256,7 @@
   return 0;
 }
 
-GRUB_MOD_INIT(fontmanager)
+GRUB_MOD_INIT(font_manager)
 {
   (void) mod; /* Stop warning.  */
   grub_register_command ("font", font_command, GRUB_COMMAND_FLAG_BOTH,
@@ -240,7 +264,7 @@
                         "Specify one or more font files to display.", 0);
 }
 
-GRUB_MOD_FINI(fontmanager)
+GRUB_MOD_FINI(font_manager)
 {
   grub_unregister_command ("font");
 }
diff -ruN -x '*CVS*' grub2/include/grub/font.h grub2.new/include/grub/font.h
--- grub2/include/grub/font.h   2004-04-04 16:46:00.000000000 +0300
+++ grub2.new/include/grub/font.h       2006-02-25 13:43:08.000000000 +0200
@@ -24,7 +24,31 @@
 
 #define GRUB_FONT_MAGIC        "PPF\x7f"
 
+struct grub_font_glyph
+{
+  /* Glyph width in pixels.  */
+  grub_uint8_t width;
+  
+  /* Glyph height in pixels.  */
+  grub_uint8_t height;
+  
+  /* Glyph width in characters.  */
+  grub_uint8_t char_width;
+  
+  /* Glyph baseline position in pixels (from up).  */
+  grub_uint8_t baseline;
+  
+  /* Glyph bitmap data array of bytes in ((width + 7) / 8) * height.
+     Bitmap is formulated by height scanlines, each scanline having
+     width number of pixels. Pixels are coded as bits, value 1 meaning
+     of opaque pixel and 0 is transparent. If width does not fit byte
+     boundary, it will be padded with 0 to make it fit.  */
+  grub_uint8_t bitmap[32];
+};
+
+typedef struct grub_font_glyph *grub_font_glyph_t;
+
 int grub_font_get_glyph (grub_uint32_t code,
-                        unsigned char bitmap[32], unsigned *width);
+                        grub_font_glyph_t glyph);
 
 #endif /* ! GRUB_FONT_HEADER */
diff -ruN -x '*CVS*' grub2/include/grub/i386/pc/vbe.h 
grub2.new/include/grub/i386/pc/vbe.h
--- grub2/include/grub/i386/pc/vbe.h    2005-08-16 21:34:17.000000000 +0300
+++ grub2.new/include/grub/i386/pc/vbe.h        2006-03-03 16:47:37.589222896 
+0200
@@ -27,6 +27,13 @@
 /* Default video mode to be used.  */
 #define GRUB_VBE_DEFAULT_VIDEO_MODE     0x101
 
+/* VBE status codes.  */
+#define GRUB_VBE_STATUS_OK             0x004f
+
+/* VBE memory model types.  */
+#define GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL     0x04
+#define GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR     0x06
+
 /* Note:
  
    Please refer to VESA BIOS Extension 3.0 Specification for more descriptive
@@ -147,45 +154,45 @@
 /* Prototypes for kernel real mode thunks.  */
 
 /* Call VESA BIOS 0x4f00 to get VBE Controller Information, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_controller_info) (struct 
grub_vbe_info_block *controller_info);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_controller_info) (struct 
grub_vbe_info_block *controller_info);
 
 /* Call VESA BIOS 0x4f01 to get VBE Mode Information, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_mode_info) (grub_uint32_t mode,
-                                                       struct 
grub_vbe_mode_info_block *mode_info);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_mode_info) (grub_uint32_t mode,
+                                                            struct 
grub_vbe_mode_info_block *mode_info);
 
 /* Call VESA BIOS 0x4f02 to set video mode, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_mode) (grub_uint32_t mode,
-                                                  struct 
grub_vbe_crtc_info_block *crtc_info);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_mode) (grub_uint32_t mode,
+                                                       struct 
grub_vbe_crtc_info_block *crtc_info);
 
 /* Call VESA BIOS 0x4f03 to return current VBE Mode, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_mode) (grub_uint32_t *mode);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_mode) (grub_uint32_t *mode);
 
 /* Call VESA BIOS 0x4f05 to set memory window, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_memory_window) (grub_uint32_t 
window,
-                                                           grub_uint32_t 
position);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_memory_window) (grub_uint32_t 
window,
+                                                                grub_uint32_t 
position);
 
 /* Call VESA BIOS 0x4f05 to return memory window, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_memory_window) (grub_uint32_t 
window,
-                                                           grub_uint32_t 
*position);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_memory_window) (grub_uint32_t 
window,
+                                                                grub_uint32_t 
*position);
 
 /* Call VESA BIOS 0x4f06 to set scanline length (in bytes), return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_scanline_length) (grub_uint32_t 
length);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_scanline_length) 
(grub_uint32_t length);
 
 /* Call VESA BIOS 0x4f06 to return scanline length (in bytes), return status.  
*/
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_scanline_length) (grub_uint32_t 
*length);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_scanline_length) 
(grub_uint32_t *length);
 
 /* Call VESA BIOS 0x4f07 to set display start, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_display_start) (grub_uint32_t x,
-                                                           grub_uint32_t y);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_display_start) (grub_uint32_t 
x,
+                                                                grub_uint32_t 
y);
 
 /* Call VESA BIOS 0x4f07 to get display start, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_display_start) (grub_uint32_t *x,
-                                                           grub_uint32_t *y);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_display_start) (grub_uint32_t 
*x,
+                                                                grub_uint32_t 
*y);
 
 /* Call VESA BIOS 0x4f09 to set palette data, return status.  */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_palette_data) (grub_uint32_t 
color_count,
-                                                          grub_uint32_t 
start_index,
-                                                          struct 
grub_vbe_palette_data *palette_data);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_palette_data) (grub_uint32_t 
color_count,
+                                                               grub_uint32_t 
start_index,
+                                                               struct 
grub_vbe_palette_data *palette_data);
 
 /* Prototypes for helper functions.  */
 
@@ -195,13 +202,5 @@
 grub_err_t grub_vbe_get_video_mode (grub_uint32_t *mode);
 grub_err_t grub_vbe_get_video_mode_info (grub_uint32_t mode,
                                          struct grub_vbe_mode_info_block 
*mode_info);
-void grub_vbe_set_pixel_rgb (grub_uint32_t x,
-                             grub_uint32_t y,
-                             grub_uint8_t red,
-                             grub_uint8_t green,
-                             grub_uint8_t blue);
-void grub_vbe_set_pixel_index (grub_uint32_t x,
-                               grub_uint32_t y,
-                               grub_uint8_t color);
 
 #endif /* ! GRUB_VBE_MACHINE_HEADER */
diff -ruN -x '*CVS*' grub2/include/grub/misc.h grub2.new/include/grub/misc.h
--- grub2/include/grub/misc.h   2005-10-24 13:23:46.000000000 +0300
+++ grub2.new/include/grub/misc.h       2006-03-02 20:40:08.000000000 +0200
@@ -76,4 +76,14 @@
                                             const grub_uint8_t *src,
                                             grub_size_t size);
 
+/* Inline functions.  */
+static inline unsigned int
+grub_abs (int x)
+{
+  if (x < 0)
+    return (unsigned int)(-x);
+  else
+    return (unsigned int)x;
+}
+
 #endif /* ! GRUB_MISC_HEADER */
diff -ruN -x '*CVS*' grub2/include/grub/video.h grub2.new/include/grub/video.h
--- grub2/include/grub/video.h  1970-01-01 02:00:00.000000000 +0200
+++ grub2.new/include/grub/video.h      2006-03-03 16:48:40.981585792 +0200
@@ -0,0 +1,301 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef GRUB_VIDEO_HEADER
+#define GRUB_VIDEO_HEADER      1
+
+#include <grub/err.h>
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+typedef grub_uint32_t grub_video_color_t;
+
+struct grub_video_render_target;
+
+/* Defines used to describe video mode or rendering target.  */
+#define GRUB_VIDEO_MODE_TYPE_ALPHA             0x00000008
+#define GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED   0x00000004
+#define GRUB_VIDEO_MODE_TYPE_INDEX_COLOR       0x00000002
+#define GRUB_VIDEO_MODE_TYPE_RGB               0x00000001
+
+/* Defines used to mask flags.  */
+#define GRUB_VIDEO_MODE_TYPE_COLOR_MASK                0x00000003
+
+/* Defined predefined render targets.  */
+#define GRUB_VIDEO_RENDER_TARGET_DISPLAY       ((struct 
grub_video_render_target *) 0)
+#define GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER  ((struct 
grub_video_render_target *) 0)
+#define GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER   ((struct 
grub_video_render_target *) 1)
+
+struct grub_video_mode_info {
+  /* Width of the screen.  */
+  unsigned int width;
+  
+  /* Height of the screen.  */
+  unsigned int height;
+
+  /* Mode type bitmask. Contains information like is it Index color or 
+     RGB mode.  */
+  unsigned int mode_type;
+
+  /* Bits per pixel.  */
+  unsigned int bpp;
+  
+  /* Bytes per pixel.  */
+  unsigned int bytes_per_pixel;
+  
+  /* Pitch of one scanline. How many bytes there are for scanline.  */
+  unsigned int pitch;
+
+  /* In index color mode, number of colors. In RGB mode this is 256.  */
+  unsigned int number_of_colors;
+
+  /* How many bits are reserved for red color.  */
+  unsigned int red_mask_size;
+
+  /* What is location of red color bits. In Index Color mode, this is 0.  */
+  unsigned int red_field_pos;
+
+  /* How many bits are reserved for green color.  */
+  unsigned int green_mask_size;
+
+  /* What is location of green color bits. In Index Color mode, this is 0.  */
+  unsigned int green_field_pos;
+
+  /* How many bits are reserved for blue color.  */
+  unsigned int blue_mask_size;
+
+  /* What is location of blue color bits. In Index Color mode, this is 0.  */
+  unsigned int blue_field_pos;
+
+  /* How many bits are reserved in color.  */
+  unsigned int reserved_mask_size;
+
+  /* What is location of reserved color bits. In Index Color mode, 
+     this is 0.  */
+  unsigned int reserved_field_pos;
+};
+
+struct grub_video_render_target {
+  /* Copy of the screen's mode info structure, except that width, height and
+     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;
+
+  /* Indicates wether the data has been allocated by us and must be freed 
+     when render target is destroyed.  */
+  int is_allocated;
+  
+  /* Pointer to data. Can either be in video card memory or in local host's
+     memory.  */
+  void *data;
+};
+
+struct grub_video_palette_data {
+  grub_uint8_t r; /* Red color value (0-255).  */
+  grub_uint8_t g; /* Green color value (0-255).  */
+  grub_uint8_t b; /* Blue color value (0-255).  */
+  grub_uint8_t a; /* Reserved bits value (0-255).  */
+};
+
+struct grub_font_glyph;
+struct grub_video_bitmap;
+
+struct grub_video_adapter
+{
+  /* The video adapter name.  */
+  const char *name;
+
+  /* Initialize the video adapter.  */
+  grub_err_t (*init) (void);
+
+  /* Clean up the video adapter.  */
+  grub_err_t (*fini) (void);
+
+  grub_err_t (*setup) (unsigned int width, 
+                      unsigned int height,
+                      unsigned int mode_type);
+
+  grub_err_t (*get_info) (struct grub_video_mode_info *mode_info);
+  
+  grub_err_t (*set_palette) (unsigned int start,
+                            unsigned int count,
+                            struct grub_video_palette_data *palette_data);
+
+  grub_err_t (*get_palette) (unsigned int start,
+                            unsigned int count,
+                            struct grub_video_palette_data *palette_data);
+
+  grub_err_t (*set_viewport) (unsigned int x,
+                             unsigned int y,
+                             unsigned int width,
+                             unsigned int height);
+
+  grub_err_t (*get_viewport) (unsigned int *x,
+                             unsigned int *y,
+                             unsigned int *width,
+                             unsigned int *height);
+
+  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,
+                                grub_uint8_t blue);
+
+  grub_video_color_t (*map_rgba) (grub_uint8_t red,
+                                 grub_uint8_t green,
+                                 grub_uint8_t blue,
+                                 grub_uint8_t alpha);
+
+  grub_err_t (*fill_rect) (grub_video_color_t color,
+                          int x,
+                          int y,
+                          unsigned int width,
+                          unsigned int height);
+
+  grub_err_t (*blit_glyph) (struct grub_font_glyph *glyph,
+                           grub_video_color_t color,
+                           int x,
+                           int y);
+
+  grub_err_t (*blit_bitmap) (struct grub_video_bitmap *bitmap,
+                            int x,
+                            int y,
+                            int offset_x,
+                            int offset_y,
+                            unsigned int width,
+                            unsigned int height);
+
+  grub_err_t (*blit_render_target) (struct grub_video_render_target *source,
+                                   int x,
+                                   int y,
+                                   int offset_x,
+                                   int offset_y,
+                                   unsigned int width,
+                                   unsigned int height);
+
+  grub_err_t (*scroll) (grub_video_color_t color,
+                       int dx,
+                       int dy);
+
+  grub_err_t (*swap_buffers) (void);
+
+  grub_err_t (*create_render_target) (struct grub_video_render_target **result,
+                                     unsigned int mode_type,
+                                     unsigned int width,
+                                     unsigned int height);
+
+  grub_err_t (*delete_render_target) (struct grub_video_render_target *target);
+
+  grub_err_t (*set_active_render_target) (struct grub_video_render_target 
*target);
+
+  /* The next video adapter.  */
+  struct grub_video_adapter *next;
+};
+typedef struct grub_video_adapter *grub_video_adapter_t;
+
+void EXPORT_FUNC(grub_video_register) (grub_video_adapter_t adapter);
+void EXPORT_FUNC(grub_video_unregister) (grub_video_adapter_t adapter);
+void EXPORT_FUNC(grub_video_iterate) (int (*hook) (grub_video_adapter_t 
adapter));
+
+grub_err_t EXPORT_FUNC(grub_video_setup) (unsigned int width,
+                                         unsigned int height,
+                                         unsigned int mode_type);
+
+grub_err_t EXPORT_FUNC(grub_video_restore) (void);
+
+grub_err_t EXPORT_FUNC(grub_video_get_info) (struct grub_video_mode_info 
*mode_info);
+
+grub_err_t EXPORT_FUNC(grub_video_set_palette) (unsigned int start,
+                                               unsigned int count,
+                                               struct grub_video_palette_data 
*palette_data);
+
+grub_err_t EXPORT_FUNC(grub_video_get_palette) (unsigned int start,
+                                               unsigned int count,
+                                               struct grub_video_palette_data 
*palette_data);
+
+grub_err_t EXPORT_FUNC(grub_video_set_viewport) (unsigned int x,
+                                                unsigned int y,
+                                                unsigned int width,
+                                                unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_get_viewport) (unsigned int *x,
+                                                unsigned int *y,
+                                                unsigned int *width,
+                                                unsigned int *height);
+
+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,
+                                                   grub_uint8_t green,
+                                                   grub_uint8_t blue);
+
+grub_video_color_t EXPORT_FUNC(grub_video_map_rgba) (grub_uint8_t red,
+                                                    grub_uint8_t green,
+                                                    grub_uint8_t blue,
+                                                    grub_uint8_t alpha);
+
+grub_err_t EXPORT_FUNC(grub_video_fill_rect) (grub_video_color_t color,
+                                             int x,
+                                             int y,
+                                             unsigned int width,
+                                             unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_blit_glyph) (struct grub_font_glyph *glyph,
+                                              grub_video_color_t color,
+                                              int x,
+                                              int y);
+
+grub_err_t EXPORT_FUNC(grub_video_blit_bitmap) (struct grub_video_bitmap 
*bitmap,
+                                               int x,
+                                               int y,
+                                               int offset_x,
+                                               int offset_y,
+                                               unsigned int width,
+                                               unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_blit_render_target) (struct 
grub_video_render_target *source,
+                                                      int x,
+                                                      int y,
+                                                      int offset_x,
+                                                      int offset_y,
+                                                      unsigned int width,
+                                                      unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_scroll) (grub_video_color_t color,
+                                          int dx,
+                                          int dy);
+
+grub_err_t EXPORT_FUNC(grub_video_swap_buffers) (void);
+
+grub_err_t EXPORT_FUNC(grub_video_create_render_target) (struct 
grub_video_render_target **result,
+                                                        unsigned int mode_type,
+                                                        unsigned int width,
+                                                        unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_delete_render_target) (struct 
grub_video_render_target *target);
+
+grub_err_t EXPORT_FUNC(grub_video_set_active_render_target) (struct 
grub_video_render_target *target);
+                                          
+#endif /* ! GRUB_VIDEO_HEADER */
diff -ruN -x '*CVS*' grub2/kern/i386/pc/startup.S 
grub2.new/kern/i386/pc/startup.S
--- grub2/kern/i386/pc/startup.S        2005-10-15 20:28:36.000000000 +0300
+++ grub2.new/kern/i386/pc/startup.S    2006-03-02 14:14:06.000000000 +0200
@@ -1758,14 +1758,15 @@
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_get_controller_info (struct grub_vbe_info_block 
*controller_info)
+ * grub_vbe_bios_status_t grub_vbe_get_controller_info (struct 
grub_vbe_info_block *controller_info)
  *
  * Register allocations for parameters:
  * %eax                *controller_info
  */
-FUNCTION(grub_vbe_get_controller_info)
+FUNCTION(grub_vbe_bios_get_controller_info)
        pushl   %ebp
        pushl   %edi
+       pushl   %edx
 
        movw    %ax, %di        /* Store *controller_info to %edx:%di.  */
        xorw    %ax, %ax
@@ -1791,19 +1792,20 @@
        movl    %edx, %eax
        andl    $0x0FFFF, %eax  /* Return value in %eax.  */
        
+       pop     %edx
        popl    %edi
        popl    %ebp
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_get_mode_info (grub_uint32_t mode,
- *                                          struct grub_vbe_mode_info_block 
*mode_info)
+ * grub_vbe_status_t grub_vbe_bios_get_mode_info (grub_uint32_t mode,
+ *                                               struct 
grub_vbe_mode_info_block *mode_info)
  *
  * Register allocations for parameters:
  * %eax                mode
  * %edx                *mode_info
  */
-FUNCTION(grub_vbe_get_mode_info)
+FUNCTION(grub_vbe_bios_get_mode_info)
        pushl   %ebp
        pushl   %edi
 
@@ -1837,16 +1839,17 @@
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_set_mode (grub_uint32_t mode,
- *                                     struct grub_vbe_crtc_info_block 
*crtc_info)
+ * grub_vbe_status_t grub_vbe_bios_set_mode (grub_uint32_t mode,
+ *                                          struct grub_vbe_crtc_info_block 
*crtc_info)
  *
  * Register allocations for parameters:
  * %eax                mode
  * %edx                *crtc_info
  */
-FUNCTION(grub_vbe_set_mode)
+FUNCTION(grub_vbe_bios_set_mode)
        pushl   %ebp
        pushl   %ebx
+       pushl   %edi
 
        movl    %eax, %ebx      /* Store mode in %ebx.  */
 
@@ -1874,19 +1877,22 @@
        movw    %dx, %ax
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
 
+       popl    %edi
        popl    %ebx
        popl    %ebp
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_get_mode (grub_uint32_t *mode)
+ * grub_vbe_status_t grub_vbe_bios_get_mode (grub_uint32_t *mode)
  *
  * Register allocations for parameters:
  * %eax                *mode
  */
-FUNCTION(grub_vbe_get_mode)
+FUNCTION(grub_vbe_bios_get_mode)
        pushl   %ebp
        pushl   %ebx
+       pushl   %edi
+       pushl   %edx
        pushl   %eax            /* Push *mode to stack.  */
 
        call    prot_to_real
@@ -1907,19 +1913,21 @@
        movw    %dx, %ax
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
 
+       popl    %edx
+       popl    %edi
        popl    %ebx
        popl    %ebp
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_set_memory_window (grub_uint32_t window,
- *                                              grub_uint32_t position);
+ * grub_vbe_status_t grub_vbe_bios_set_memory_window (grub_uint32_t window,
+ *                                                   grub_uint32_t position);
  *
  * Register allocations for parameters:
  * %eax                window
  * %edx                position
  */
-FUNCTION(grub_vbe_set_memory_window)
+FUNCTION(grub_vbe_bios_set_memory_window)
        pushl   %ebp
        pushl   %ebx
 
@@ -1945,16 +1953,17 @@
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_get_memory_window (grub_uint32_t window,
- *                                              grub_uint32_t *position);
+ * grub_vbe_status_t grub_vbe_bios_get_memory_window (grub_uint32_t window,
+ *                                                   grub_uint32_t *position);
  *
  * Register allocations for parameters:
  * %eax                window
  * %edx                *position
  */
-FUNCTION(grub_vbe_get_memory_window)
+FUNCTION(grub_vbe_bios_get_memory_window)
        pushl   %ebp
        pushl   %ebx
+       pushl   %edi
        pushl   %edx            /* Push *position to stack.  */
 
        movl    %eax, %ebx      /* Store window in %ebx.  */
@@ -1979,19 +1988,21 @@
        movw    %bx, %ax
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
 
+       popl    %edi
        popl    %ebx
        popl    %ebp
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_set_scanline_length (grub_uint32_t length)
+ * grub_vbe_status_t grub_vbe_bios_set_scanline_length (grub_uint32_t length)
  *
  * Register allocations for parameters:
  * %eax                length
  */
-FUNCTION(grub_vbe_set_scanline_length)
+FUNCTION(grub_vbe_bios_set_scanline_length)
        pushl   %ebp
        pushl   %ebx
+       pushl   %edx
 
        movl    %eax, %ecx      /* Store length in %ecx.  */
 
@@ -2010,19 +2021,21 @@
        movw    %dx, %ax
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
 
+       popl    %edx
        popl    %ebx
        popl    %ebp
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_get_scanline_length (grub_uint32_t *length)
+ * grub_vbe_status_t grub_vbe_bios_get_scanline_length (grub_uint32_t *length)
  *
  * Register allocations for parameters:
  * %eax                *length
  */
-FUNCTION(grub_vbe_get_scanline_length)
+FUNCTION(grub_vbe_bios_get_scanline_length)
        pushl   %ebp
        pushl   %ebx
+       pushl   %edi
        pushl   %edx            /* Push *length to stack.  */
 
        call    prot_to_real
@@ -2044,19 +2057,20 @@
        movw    %dx, %ax
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
 
+       popl    %edi
        popl    %ebx
        popl    %ebp
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_set_display_start (grub_uint32_t x,
- *                                              grub_uint32_t y)
+ * grub_vbe_status_t grub_vbe_bios_set_display_start (grub_uint32_t x,
+ *                                                   grub_uint32_t y)
  *
  * Register allocations for parameters:
  * %eax                x
  * %edx                y
  */
-FUNCTION(grub_vbe_set_display_start)
+FUNCTION(grub_vbe_bios_set_display_start)
        pushl   %ebp
        pushl   %ebx
 
@@ -2083,16 +2097,17 @@
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_get_display_start (grub_uint32_t *x,
- *                                              grub_uint32_t *y)
+ * grub_vbe_status_t grub_vbe_bios_get_display_start (grub_uint32_t *x,
+ *                                                   grub_uint32_t *y)
  *
  * Register allocations for parameters:
  * %eax                *x
  * %edx                *y
  */
-FUNCTION(grub_vbe_get_display_start)
+FUNCTION(grub_vbe_bios_get_display_start)
        pushl   %ebp
        pushl   %ebx
+       pushl   %edi
        pushl   %eax            /* Push *x to stack.  */
        pushl   %edx            /* Push *y to stack.  */
 
@@ -2119,23 +2134,25 @@
        movw    %bx, %ax
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
 
+       popl    %edi
        popl    %ebx
        popl    %ebp
        ret
 
 /*
- * grub_vbe_status_t grub_vbe_set_palette_data (grub_uint32_t color_count,
- *                                             grub_uint32_t start_index,
- *                                             struct grub_vbe_palette_data 
*palette_data)
+ * grub_vbe_status_t grub_vbe_bios_set_palette_data (grub_uint32_t color_count,
+ *                                                  grub_uint32_t start_index,
+ *                                                  struct 
grub_vbe_palette_data *palette_data)
  *
  * Register allocations for parameters:
  * %eax                color_count
  * %edx                start_index
  * %ecx                *palette_data
  */
-FUNCTION(grub_vbe_set_palette_data)
+FUNCTION(grub_vbe_bios_set_palette_data)
        pushl   %ebp
        pushl   %ebx
+       pushl   %edi
 
        movl    %eax, %ebx      /* Store color_count in %ebx.  */
 
@@ -2165,6 +2182,7 @@
        movw    %dx, %ax
        andl    $0xFFFF, %eax   /* Return value in %eax.  */
 
+       popl    %edi
        popl    %ebx
        popl    %ebp
        ret
diff -ruN -x '*CVS*' grub2/normal/cmdline.c grub2.new/normal/cmdline.c
--- grub2/normal/cmdline.c      2005-08-28 20:01:16.000000000 +0300
+++ grub2.new/normal/cmdline.c  2006-02-25 14:50:44.000000000 +0200
@@ -231,6 +231,8 @@
       xpos = (plen + lpos) % 79;
       ypos = ystart + (plen + lpos) / 79;
       grub_gotoxy (xpos, ypos);
+      
+      grub_refresh ();
     }
   
   void cl_print (int pos, int c)
@@ -271,6 +273,8 @@
          cl_print (lpos - len, echo_char);
          cl_set_pos ();
        }
+      
+      grub_refresh ();
     }
 
   void cl_delete (unsigned len)
@@ -290,6 +294,8 @@
          cl_print (lpos, echo_char);
          cl_set_pos ();
        }
+      
+      grub_refresh ();
     }
   
   plen = grub_strlen (prompt);
diff -ruN -x '*CVS*' grub2/term/videoterm.c grub2.new/term/videoterm.c
--- grub2/term/videoterm.c      1970-01-01 02:00:00.000000000 +0200
+++ grub2.new/term/videoterm.c  2006-03-03 15:58:20.868946928 +0200
@@ -0,0 +1,877 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/machine/memory.h>
+#include <grub/machine/console.h>
+#include <grub/term.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/font.h>
+#include <grub/arg.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+#include <grub/video.h>
+
+#define DEFAULT_VIDEO_WIDTH    1024
+#define DEFAULT_VIDEO_HEIGHT   768
+#define DEFAULT_VIDEO_FLAGS    0
+
+#define DEFAULT_CHAR_WIDTH     8
+#define DEFAULT_CHAR_HEIGHT    16
+
+#define DEFAULT_FG_COLOR       0x0a
+#define DEFAULT_BG_COLOR       0x00
+#define DEFAULT_CURSOR_COLOR   0x0f
+
+struct grub_dirty_region
+{
+  int top_left_x;
+  int top_left_y;
+  int bottom_right_x;
+  int bottom_right_y;
+};
+
+struct grub_colored_char
+{
+  /* An Unicode codepoint.  */
+  grub_uint32_t code;
+
+  /* Color values.  */
+  grub_video_color_t fg_color;
+  grub_video_color_t bg_color;
+
+  /* The width of this character minus one.  */
+  unsigned char width;
+
+  /* The column index of this character.  */
+  unsigned char index;
+};
+
+struct grub_virtual_screen
+{
+  /* Dimensions of the virtual screen.  */
+  unsigned int width;
+  unsigned int height;
+
+  /* Offset in the display.  */
+  unsigned int offset_x;
+  unsigned int offset_y;
+
+  /* TTY Character sizes.  */
+  unsigned int char_width;
+  unsigned int char_height;
+
+  /* Virtual screen TTY size.  */
+  unsigned int columns;
+  unsigned int rows;
+
+  /* Current cursor details.  */
+  unsigned int cursor_x;
+  unsigned int cursor_y;
+  int cursor_state;
+  
+  /* Color settings.  */
+  grub_video_color_t fg_color_setting;
+  grub_video_color_t bg_color_setting;
+  grub_video_color_t fg_color;
+  grub_video_color_t bg_color;
+  grub_video_color_t cursor_color;
+
+  /* Text buffer for virual screen. Contains (columns * rows) number
+     of entries.  */
+  struct grub_colored_char *text_buffer;
+};
+
+static struct grub_virtual_screen virtual_screen;
+
+static grub_dl_t my_mod;
+static struct grub_video_mode_info mode_info;
+
+static struct grub_video_render_target *text_layer;
+
+static struct grub_dirty_region dirty_region;
+
+static void dirty_region_reset (void);
+
+static int dirty_region_is_empty (void);
+
+static void dirty_region_add (int x, 
+                              int y,
+                              unsigned int width,
+                              unsigned int height);
+
+static void
+grub_virtual_screen_free (void)
+{
+  /* If virtual screen has been allocated, free it.  */
+  if (virtual_screen.text_buffer != 0)
+    grub_free (virtual_screen.text_buffer);
+
+  /* Reset virtual screen data.  */
+  grub_memset (&virtual_screen, 0, sizeof (virtual_screen));
+  
+  /* Free render targets.  */
+  grub_video_delete_render_target (text_layer);
+  text_layer = 0;
+}
+
+static grub_err_t
+grub_virtual_screen_setup (unsigned int x,
+                           unsigned int y,
+                           unsigned int width,
+                          unsigned int height)
+{
+  /* Free old virtual screen.  */
+  grub_virtual_screen_free ();
+
+  /* Initialize with default data.  */
+  virtual_screen.width = width;
+  virtual_screen.height = height;
+  virtual_screen.offset_x = x;
+  virtual_screen.offset_y = y;
+  virtual_screen.char_width = DEFAULT_CHAR_WIDTH;
+  virtual_screen.char_height = DEFAULT_CHAR_HEIGHT;
+  virtual_screen.cursor_x = 0;
+  virtual_screen.cursor_y = 0;
+  virtual_screen.cursor_state = 1;
+
+  /* Calculate size of text buffer.  */
+  virtual_screen.columns = virtual_screen.width / virtual_screen.char_width;
+  virtual_screen.rows = virtual_screen.height / virtual_screen.char_height;
+
+  /* Allocate memory for text buffer.  */
+  virtual_screen.text_buffer =
+    (struct grub_colored_char *) grub_malloc (virtual_screen.columns
+                                             * virtual_screen.rows
+                                             * sizeof 
(*virtual_screen.text_buffer));
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* Create new render target for text layer.  */
+  grub_video_create_render_target (&text_layer,
+                                   GRUB_VIDEO_MODE_TYPE_RGB
+                                   | GRUB_VIDEO_MODE_TYPE_ALPHA,
+                                   virtual_screen.width,
+                                   virtual_screen.height);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+  
+  /* As we want to have colors compatible with rendering target,
+     we can only have those after mode is initialized.  */    
+  grub_video_set_active_render_target (text_layer);
+  
+  virtual_screen.fg_color_setting = grub_video_map_color (DEFAULT_FG_COLOR);
+  virtual_screen.bg_color_setting = grub_video_map_color (DEFAULT_BG_COLOR);
+  virtual_screen.fg_color = virtual_screen.fg_color_setting;
+  virtual_screen.bg_color = virtual_screen.bg_color_setting;
+  virtual_screen.cursor_color = grub_video_map_color (DEFAULT_CURSOR_COLOR);
+  
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+  
+  return grub_errno;
+}
+
+static grub_err_t
+grub_videoterm_init (void)
+{
+  char *modevar;
+  int width = DEFAULT_VIDEO_WIDTH;
+  int height = DEFAULT_VIDEO_HEIGHT;
+  int flags = DEFAULT_VIDEO_FLAGS;
+  grub_video_color_t color;
+  
+  /* Parse video_mode environment variable if set.  */
+  modevar = grub_env_get ("video_mode");
+  if (modevar)
+    {
+      char *tmp;
+      char *param;
+      char *value;
+      
+      /* Take copy of env.var. as we don't want to modify that.  */
+      tmp = grub_strdup (modevar);
+      modevar = tmp;
+      
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;        
+      
+      /* Skip whitespace.  */
+      while (grub_isspace (*tmp))
+        tmp++;
+      
+      /* Initialize token holders.  */
+      param = tmp;
+      value = NULL;
+
+      /* Loop until all characters have been handled.  */
+      while (1)
+        {
+          if (grub_isspace (*tmp) || (*tmp == 0))
+            {
+              /* If there are more variables, mark seperator with NUL.  */
+              if (*tmp != 0)
+                *tmp++ = 0;
+
+              /* Analyze setting.  */
+              
+              /* Handle width=<number>.  */
+              if ((grub_strcmp (param, "width") == 0) && (value != NULL))
+                {
+                  width = grub_strtoul (value, 0, 0);
+                  if (grub_errno != GRUB_ERR_NONE)
+                    {
+                      /* Free memory before returning.  */
+                      grub_free (modevar);
+                      return grub_errno;
+                    }
+                }
+
+              /* Handle height=<number>.  */
+              if ((grub_strcmp (param, "height") == 0) && (value != NULL))
+                {
+                  height = grub_strtoul (value, 0, 0);
+                  if (grub_errno != GRUB_ERR_NONE)
+                    {
+                      /* Free memory before returning.  */
+                      grub_free (modevar);
+                      return grub_errno;
+                    }
+                }
+
+              /* Handle rgb. Used to request RGB mode.  */
+              if ((grub_strcmp (param, "rgb") == 0) && (value == NULL))
+                {
+                  flags &= ~GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+                  flags |= GRUB_VIDEO_MODE_TYPE_RGB;
+                }
+
+              /* Handle index. Used to request index color mode.  */
+              if ((grub_strcmp (param, "index") == 0) && (value == NULL))
+                {
+                  flags &= ~GRUB_VIDEO_MODE_TYPE_RGB;
+                  flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+                }                
+
+              /* Handle double. Used to request double buffering mode.  */
+              if ((grub_strcmp (param, "double") == 0) && (value == NULL))
+                flags |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
+              
+              /* Handle <width>x<height>[x<depth>]*/
+              if (grub_isdigit (param[0]))
+                {
+                  /* Find width value.  */
+                  value = param;
+                  param = grub_strchr(param, 'x');
+                  if (param == NULL)
+                    {
+                      /* Free memory before returning.  */
+                      grub_free (modevar);
+                      return grub_error (GRUB_ERR_BAD_ARGUMENT, 
+                                         "Invalid argument: %s\n",
+                                         param);
+                    }
+                    
+                  *param = 0;
+                  param++;
+                      
+                  width = grub_strtoul (value, 0, 0);
+                  if (grub_errno != GRUB_ERR_NONE)
+                    {
+                      /* Free memory before returning.  */
+                      grub_free (modevar);
+                      return grub_errno;
+                    }                      
+
+                  /* Find height value.  */
+                  value = param;
+                  param = grub_strchr(param, 'x');
+                  if (param == NULL)
+                    {                    
+                      height = grub_strtoul (value, 0, 0);
+                      if (grub_errno != GRUB_ERR_NONE)
+                        {
+                          /* Free memory before returning.  */
+                          grub_free (modevar);
+                          return grub_errno;
+                        }                      
+                    }
+                  else
+                    {
+                      /* We have optional color depth value.  */
+                      *param = 0;
+                      param++;
+                      
+                      height = grub_strtoul (value, 0, 0);
+                      if (grub_errno != GRUB_ERR_NONE)
+                        {
+                          /* Free memory before returning.  */
+                          grub_free (modevar);
+                          return grub_errno;
+                        }                      
+                      
+                      /* Convert color depth value.  */
+                      value = param;
+#if 0                      
+                      depth = grub_strtoul (value, 0, 0);
+                      if (grub_errno != GRUB_ERR_NONE)
+                        {
+                          /* Free memory before returning.  */
+                          grub_free (modevar);
+                          return grub_errno;
+                        }
+#endif                        
+                    }
+                }
+                
+              /* Skip whitespace.  */
+              while (grub_isspace (*tmp))
+                tmp++;
+
+              /* Check if we are at end of string.  */
+              if (*tmp == 0)
+                break;
+              
+              /* Initialize token holders.  */
+              param = tmp;
+              value = NULL;
+            }
+          
+          /* Check if there is value seperator.  */
+          if (*tmp == '=')
+            {
+              *tmp++ = 0;
+              value = tmp;
+            }
+          
+          /* Advance to next character.  */
+          tmp++;
+        }
+        
+        /* Free memory.  */
+        grub_free (modevar);
+    }
+
+  /* Intialize user requested mode.  */
+  if (grub_video_setup (width, height, flags) != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* Figure out what mode we ended up.  */
+  if (grub_video_get_info (&mode_info) != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* Make sure screen is black.  */
+  color = grub_video_map_rgb (0, 0, 0);
+  grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
+
+  /* Leave borders for virtual screen.  */
+  width = mode_info.width - (2 * 10);
+  height = mode_info.height - (2 * 10);
+  
+  /* Create virtual screen.  */
+  if (grub_virtual_screen_setup (10,
+                                 10,
+                                 width,
+                                height) != GRUB_ERR_NONE)
+    {
+      grub_video_restore ();
+      return grub_errno;
+    }
+
+  /* Mark whole screen as dirty.  */
+  dirty_region_reset ();  
+  dirty_region_add (0, 0, mode_info.width, mode_info.height);
+
+  return (grub_errno = GRUB_ERR_NONE);
+}
+
+static grub_err_t
+grub_videoterm_fini (void)
+{
+  grub_virtual_screen_free ();
+
+  grub_video_restore ();
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+redraw_screen_rect (unsigned int x, 
+                    unsigned int y, 
+                    unsigned int width, 
+                    unsigned int height)
+{
+  grub_video_color_t color;
+  
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+  /* Render background layer.  */
+  color = virtual_screen.bg_color;
+  grub_video_fill_rect (color, x, y, width, height);
+  
+  /* Render text layer.  */
+  grub_video_blit_render_target (text_layer,
+                                 x,
+                                 y,
+                                 x - virtual_screen.offset_x,
+                                 y - virtual_screen.offset_y,
+                                 width,
+                                 height);
+}
+
+static void
+dirty_region_reset (void)
+{
+  dirty_region.top_left_x = -1;
+  dirty_region.top_left_y = -1;
+  dirty_region.bottom_right_x = -1;
+  dirty_region.bottom_right_y = -1;
+}
+
+static int
+dirty_region_is_empty (void)
+{
+  if ((dirty_region.top_left_x == -1)
+      || (dirty_region.top_left_y == -1)
+      || (dirty_region.bottom_right_x == -1)
+      || (dirty_region.bottom_right_y == -1))
+    {
+      return 1;
+    }
+  return 0;
+}
+
+static void
+dirty_region_add (int x, int y, unsigned int width, unsigned int height)
+{
+  if ((width == 0) || (height == 0))
+    return;
+    
+  if (dirty_region_is_empty ())
+    {
+      dirty_region.top_left_x = x;
+      dirty_region.top_left_y = y;
+      dirty_region.bottom_right_x = x + width - 1;
+      dirty_region.bottom_right_y = y + height - 1;
+    } 
+  else
+    {
+      if (x < dirty_region.top_left_x)
+        {
+          dirty_region.top_left_x = x;
+        }
+      if (y < dirty_region.top_left_y)
+        {
+          dirty_region.top_left_y = y;
+        }
+      if ((x + (int)width - 1) > dirty_region.bottom_right_x)
+        {
+          dirty_region.bottom_right_x = x + width - 1;
+        }
+      if ((y + (int)height - 1) > dirty_region.bottom_right_y)
+        {
+          dirty_region.bottom_right_y = y + height - 1;
+        }
+    }
+} 
+
+static void
+dirty_region_add_virtualscreen (void)
+{
+  /* Mark virtual screen as dirty.  */
+  dirty_region_add (virtual_screen.offset_x, virtual_screen.offset_y,
+                    virtual_screen.width, virtual_screen.height);
+}
+
+
+static void
+dirty_region_redraw (void)
+{
+  int x;
+  int y;
+  int width;
+  int height;
+  
+  if (dirty_region_is_empty ())
+    return;
+  
+  x = dirty_region.top_left_x;
+  y = dirty_region.top_left_y;
+  
+  width = dirty_region.bottom_right_x - x + 1;
+  height = dirty_region.bottom_right_y - y + 1;
+  
+  redraw_screen_rect (x, y, width, height);
+  
+  dirty_region_reset ();
+}
+
+static void
+write_char (void)
+{
+  struct grub_colored_char *p;
+  struct grub_font_glyph glyph;
+  grub_video_color_t color;
+  grub_video_color_t bgcolor;    
+  unsigned int x;
+  unsigned int y;
+
+  /* Find out active character.  */
+  p = (virtual_screen.text_buffer
+       + virtual_screen.cursor_x
+       + (virtual_screen.cursor_y * virtual_screen.columns));
+
+  p -= p->index;
+
+  /* Get glyph for character.  */
+  grub_font_get_glyph (p->code, &glyph);
+
+  color = p->fg_color;
+  bgcolor = p->bg_color;
+
+  x = virtual_screen.cursor_x * virtual_screen.char_width;
+  y = virtual_screen.cursor_y * virtual_screen.char_height;
+
+  /* Render glyph to text layer.  */
+  grub_video_set_active_render_target (text_layer);
+  grub_video_fill_rect (bgcolor, x, y, glyph.width, glyph.height);
+  grub_video_blit_glyph (&glyph, color, x, y);  
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+  /* Mark character to be drawn.  */
+  dirty_region_add (virtual_screen.offset_x + x,
+                    virtual_screen.offset_y + y,
+                    glyph.width,
+                    glyph.height);
+}
+
+static void
+write_cursor (void)
+{
+  unsigned int x;
+  unsigned int y;
+  unsigned int width;
+  unsigned int height;
+  grub_video_color_t color;
+
+  /* Determine cursor properties and position on text layer. */
+  x = virtual_screen.cursor_x * virtual_screen.char_width;
+  y = ((virtual_screen.cursor_y + 1) * virtual_screen.char_height) - 3;  
+  width = virtual_screen.char_width;
+  height = 2;
+
+  color = virtual_screen.cursor_color;
+
+  /* Render cursor to text layer.  */
+  grub_video_set_active_render_target (text_layer);
+  grub_video_fill_rect (color, x, y, width, height);
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+  /* Mark cursor to be redrawn.  */
+  dirty_region_add (virtual_screen.offset_x + x,
+                    virtual_screen.offset_y + y,
+                    width,
+                    height);
+}
+
+static void
+scroll_up (void)
+{
+  unsigned int i;
+  grub_video_color_t color;
+
+  /* Scroll text buffer with one line to up.  */
+  grub_memmove (virtual_screen.text_buffer,
+               virtual_screen.text_buffer + virtual_screen.columns,
+                sizeof (*virtual_screen.text_buffer)
+                * virtual_screen.columns
+                * (virtual_screen.rows - 1));
+
+  /* Clear last line in text buffer.  */
+  for (i = virtual_screen.columns * (virtual_screen.rows - 1);
+       i < virtual_screen.columns * virtual_screen.rows;
+       i++)
+    {
+      virtual_screen.text_buffer[i].code = ' ';
+      virtual_screen.text_buffer[i].fg_color = virtual_screen.fg_color;
+      virtual_screen.text_buffer[i].bg_color = virtual_screen.bg_color;
+      virtual_screen.text_buffer[i].width = 0;
+      virtual_screen.text_buffer[i].index = 0;
+    }
+    
+  /* Scroll physical screen.  */
+  grub_video_set_active_render_target (text_layer);
+  color = virtual_screen.bg_color;
+  grub_video_scroll (color, 0, -virtual_screen.char_height);
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+  
+  /* Mark virtual screen to be redrawn.  */
+  dirty_region_add_virtualscreen ();
+}
+
+static void
+grub_videoterm_putchar (grub_uint32_t c)
+{
+  if (c == '\a')
+    /* FIXME */
+    return;
+
+  if (c == '\b' || c == '\n' || c == '\r')
+    {
+      /* Erase current cursor, if any.  */
+      if (virtual_screen.cursor_state)
+       write_char ();
+
+      switch (c)
+       {
+       case '\b':
+         if (virtual_screen.cursor_x > 0)
+           virtual_screen.cursor_x--;
+         break;
+         
+       case '\n':
+         if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
+           scroll_up ();
+         else
+           virtual_screen.cursor_y++;
+         break;
+         
+       case '\r':
+         virtual_screen.cursor_x = 0;
+         break;
+       }
+
+      /* Redraw cursor if visible.  */
+      if (virtual_screen.cursor_state)
+       write_cursor ();
+    }
+  else
+    {
+      struct grub_font_glyph glyph;
+      struct grub_colored_char *p;
+  
+      /* Get properties of the character.  */    
+      grub_font_get_glyph (c, &glyph);
+
+      /* If we are about to exceed line length, wrap to next line.  */
+      if (virtual_screen.cursor_x + glyph.char_width > virtual_screen.columns)
+       grub_putchar ('\n');
+
+      /* Find position on virtual screen, and fill information.  */
+      p = (virtual_screen.text_buffer +
+          virtual_screen.cursor_x +
+          virtual_screen.cursor_y * virtual_screen.columns);
+      p->code = c;
+      p->fg_color = virtual_screen.fg_color;
+      p->bg_color = virtual_screen.bg_color;
+      p->width = glyph.char_width - 1;
+      p->index = 0;
+
+      /* If we have large glyph, add fixup info.  */
+      if (glyph.char_width > 1)
+       {
+         unsigned i;
+
+         for (i = 1; i < glyph.char_width; i++)
+           {
+             p[i].code = ' ';
+             p[i].width = glyph.char_width - 1;
+             p[i].index = i;
+           }
+       }
+         
+      /* Draw glyph.  */
+      write_char ();
+  
+      /* Make sure we scroll screen when needed and wrap line correctly.  */
+      virtual_screen.cursor_x += glyph.char_width;
+      if (virtual_screen.cursor_x >= virtual_screen.columns)
+       {
+         virtual_screen.cursor_x = 0;
+         
+         if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
+           scroll_up ();
+         else
+           virtual_screen.cursor_y++;
+       }
+
+      /* Draw cursor if visible.  */
+      if (virtual_screen.cursor_state)
+       write_cursor ();
+    }
+}
+
+static grub_ssize_t
+grub_videoterm_getcharwidth (grub_uint32_t c)
+{
+  struct grub_font_glyph glyph;
+  
+  if (! grub_font_get_glyph (c, &glyph))
+    return 0;
+
+  return glyph.char_width;
+}
+
+static grub_uint16_t
+grub_virtual_screen_getwh (void)
+{
+  return (virtual_screen.columns << 8) | virtual_screen.rows;
+}
+
+static grub_uint16_t
+grub_virtual_screen_getxy (void)
+{
+  return ((virtual_screen.cursor_x << 8) | virtual_screen.cursor_y);
+}
+
+static void
+grub_videoterm_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+  if (x >= virtual_screen.columns || y >= virtual_screen.rows)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)",
+                 (unsigned) x, (unsigned) y);
+      return;
+    }
+
+  if (virtual_screen.cursor_state)
+    write_char ();
+
+  virtual_screen.cursor_x = x;
+  virtual_screen.cursor_y = y;
+
+  if (virtual_screen.cursor_state)
+    write_cursor ();
+}
+
+static void
+grub_virtual_screen_cls (void)
+{
+  grub_uint32_t i;
+
+  for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++)
+    {
+      virtual_screen.text_buffer[i].code = ' ';
+      virtual_screen.text_buffer[i].fg_color = virtual_screen.fg_color;
+      virtual_screen.text_buffer[i].bg_color = virtual_screen.bg_color;
+      virtual_screen.text_buffer[i].width = 0;
+      virtual_screen.text_buffer[i].index = 0;
+    }
+
+  virtual_screen.cursor_x = virtual_screen.cursor_y = 0;
+}
+
+static void
+grub_videoterm_cls (void)
+{
+  grub_video_color_t color;
+
+  /* Clear virtual screen.  */
+  grub_virtual_screen_cls ();
+  
+  /* Clear text layer.  */
+  grub_video_set_active_render_target (text_layer);
+  color = virtual_screen.bg_color_setting;
+  grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+  
+  /* Mark virtual screen to be redrawn.  */
+  dirty_region_add_virtualscreen ();
+}
+
+static void
+grub_virtual_screen_setcolorstate (grub_term_color_state state)
+{
+  switch (state)
+    {
+    case GRUB_TERM_COLOR_STANDARD:
+    case GRUB_TERM_COLOR_NORMAL:
+      virtual_screen.fg_color = virtual_screen.fg_color_setting;
+      virtual_screen.bg_color = virtual_screen.bg_color_setting;
+      break;
+    case GRUB_TERM_COLOR_HIGHLIGHT:
+      virtual_screen.fg_color = virtual_screen.bg_color_setting;
+      virtual_screen.bg_color = virtual_screen.fg_color_setting;
+      break;
+    default:
+      break;
+    }
+}
+
+static void
+grub_virtual_screen_setcolor (grub_uint8_t normal_color __attribute__ 
((unused)),
+                             grub_uint8_t highlight_color __attribute__ 
((unused)))
+{
+  virtual_screen.fg_color_setting = grub_video_map_color (normal_color);
+  virtual_screen.bg_color_setting = grub_video_map_color (highlight_color);
+}
+
+static void
+grub_videoterm_setcursor (int on)
+{
+  if (virtual_screen.cursor_state != on)
+    {
+      if (virtual_screen.cursor_state)
+       write_char ();
+      else
+       write_cursor ();
+
+      virtual_screen.cursor_state = on;
+    }
+}
+
+static void
+grub_videoterm_refresh (void)
+{
+  /* Redraw only changed regions.  */
+  dirty_region_redraw ();
+}
+
+static struct grub_term grub_video_term =
+  {
+    .name = "videoterm",
+    .init = grub_videoterm_init,
+    .fini = grub_videoterm_fini,
+    .putchar = grub_videoterm_putchar,
+    .getcharwidth = grub_videoterm_getcharwidth,
+    .checkkey = grub_console_checkkey,
+    .getkey = grub_console_getkey,
+    .getwh = grub_virtual_screen_getwh,
+    .getxy = grub_virtual_screen_getxy,
+    .gotoxy = grub_videoterm_gotoxy,
+    .cls = grub_videoterm_cls,
+    .setcolorstate = grub_virtual_screen_setcolorstate,
+    .setcolor = grub_virtual_screen_setcolor,
+    .setcursor = grub_videoterm_setcursor,
+    .refresh = grub_videoterm_refresh,    
+    .flags = 0,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(term_videoterm)
+{
+  my_mod = mod;
+  grub_term_register (&grub_video_term);
+}
+
+GRUB_MOD_FINI(term_videoterm)
+{
+  grub_term_unregister (&grub_video_term);
+}
Files grub2/unifont.pff and grub2.new/unifont.pff differ
diff -ruN -x '*CVS*' grub2/video/i386/pc/vbe.c grub2.new/video/i386/pc/vbe.c
--- grub2/video/i386/pc/vbe.c   2005-09-19 00:04:41.000000000 +0300
+++ grub2.new/video/i386/pc/vbe.c       2006-03-03 16:57:36.187222168 +0200
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2005  Free Software Foundation, Inc.
+ *  Copyright (C) 2005,2006  Free Software Foundation, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -17,20 +17,20 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+/* General TODO's:
+   - Implement mode optimized operations and automatically select best
+
+*/
+
 #include <grub/err.h>
 #include <grub/machine/memory.h>
-#include <grub/machine/vga.h>
 #include <grub/machine/vbe.h>
-#include <grub/machine/console.h>
-#include <grub/term.h>
 #include <grub/types.h>
 #include <grub/dl.h>
 #include <grub/misc.h>
-#include <grub/normal.h>
 #include <grub/font.h>
-#include <grub/arg.h>
 #include <grub/mm.h>
-#include <grub/env.h>
+#include <grub/video.h>
 
 /* Specify "standard" VGA palette, some video cards may
    need this and this will also be used when using RGB modes.  */
@@ -57,15 +57,52 @@
   };
 
 static int vbe_detected = -1;
-static int index_color_mode = 0;
 
 static struct grub_vbe_info_block controller_info;
 static struct grub_vbe_mode_info_block active_mode_info;
 
-static grub_uint32_t active_mode = 0;
+static struct {
+  struct grub_video_render_target render_target;
+
+  unsigned int bytes_per_scan_line;
+  unsigned int bytes_per_pixel;
+  grub_uint32_t active_mode;
+  grub_uint8_t *ptr;
+  int index_color_mode;
+  struct grub_video_palette_data palette[256];
+} framebuffer;  
+
+static struct grub_video_render_target *render_target;
+static grub_uint32_t initial_mode;
+static grub_uint32_t mode_in_use = 0x55aa;
+static grub_uint16_t *mode_list;
+
+static grub_video_color_t
+grub_video_vbe_map_rgb (grub_uint8_t red,
+                        grub_uint8_t green,
+                        grub_uint8_t blue);
+
+static grub_video_color_t
+grub_video_vbe_map_rgba (grub_uint8_t red,
+                         grub_uint8_t green,
+                         grub_uint8_t blue,
+                         grub_uint8_t alpha);
+
+static void
+grub_video_vbe_unmap_color (struct grub_video_render_target * source,
+                            grub_video_color_t color,
+                            grub_uint8_t *red,
+                            grub_uint8_t *green,
+                            grub_uint8_t *blue,
+                            grub_uint8_t *alpha);
 
-static grub_uint8_t *framebuffer = 0;
-static grub_uint32_t bytes_per_scan_line = 0;
+
+static void *
+real2pm (grub_vbe_farptr_t ptr)
+{
+  return (void *) ((((unsigned long) ptr & 0xFFFF0000) >> 12UL)
+                   + ((unsigned long) ptr & 0x0000FFFF));
+}
 
 grub_err_t
 grub_vbe_probe (struct grub_vbe_info_block *info_block)
@@ -99,7 +136,7 @@
       vbe_ib->signature[3] = '2';
       
       /* Try to get controller info block.  */
-      status = grub_vbe_get_controller_info (vbe_ib);
+      status = grub_vbe_bios_get_controller_info (vbe_ib);
       if (status == 0x004F)
        {
          /* Copy it for later usage.  */
@@ -128,11 +165,13 @@
   grub_uint32_t old_mode;
   
   /* Make sure that VBE is supported.  */
-  if (grub_vbe_probe (0) != GRUB_ERR_NONE)
+  grub_vbe_probe (0);
+  if (grub_errno != GRUB_ERR_NONE)
     return grub_errno;
 
   /* Try to get mode info.  */
-  if (grub_vbe_get_video_mode_info (mode, &active_mode_info) != GRUB_ERR_NONE)
+  grub_vbe_get_video_mode_info (mode, &active_mode_info);
+  if (grub_errno != GRUB_ERR_NONE)
     return grub_errno;
 
   /* For all VESA BIOS modes, force linear frame buffer.  */
@@ -144,12 +183,12 @@
       /* Determine frame buffer pixel format.  */
       switch (active_mode_info.memory_model)
        {
-       case 0x04:
-         index_color_mode = 1;
+       case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL:
+         framebuffer.index_color_mode = 1;
          break;
          
-       case 0x06:
-         index_color_mode = 0;
+       case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR:
+         framebuffer.index_color_mode = 0;
          break;
          
        default:
@@ -160,51 +199,68 @@
     }
 
   /* Get current mode.  */
-  if (grub_vbe_get_video_mode (&old_mode) != GRUB_ERR_NONE)
+  grub_vbe_get_video_mode (&old_mode);
+  if (grub_errno != GRUB_ERR_NONE)
     return grub_errno;
   
   /* Try to set video mode.  */
-  status = grub_vbe_set_mode (mode, 0);
-  if (status != 0x004F)
+  status = grub_vbe_bios_set_mode (mode, 0);
+  if (status != GRUB_VBE_STATUS_OK)
     return grub_error (GRUB_ERR_BAD_DEVICE, "cannot set VBE mode %x", mode);
 
   /* Save information for later usage.  */
-  active_mode = mode;
+  framebuffer.active_mode = mode;
 
   if (mode < 0x100)
     {
       /* If this is not a VESA mode, guess address.  */
-      framebuffer = (grub_uint8_t *) 0xA0000;
-      index_color_mode = 1;
+      framebuffer.ptr = (grub_uint8_t *) 0xA0000;
+      framebuffer.index_color_mode = 1;
     }
   else
     {
-      framebuffer = (grub_uint8_t *) active_mode_info.phys_base_addr;
+      framebuffer.ptr = (grub_uint8_t *) active_mode_info.phys_base_addr;
 
       if (controller_info.version >= 0x300)
-       bytes_per_scan_line = active_mode_info.lin_bytes_per_scan_line;
+       framebuffer.bytes_per_scan_line = 
active_mode_info.lin_bytes_per_scan_line;
       else
-       bytes_per_scan_line = active_mode_info.bytes_per_scan_line;
+       framebuffer.bytes_per_scan_line = active_mode_info.bytes_per_scan_line;
+    }
+    
+  /* Calculate bytes_per_pixel value.  */
+  switch(active_mode_info.bits_per_pixel)
+    {
+    case 32: framebuffer.bytes_per_pixel = 4; break;
+    case 24: framebuffer.bytes_per_pixel = 3; break;
+    case 16: framebuffer.bytes_per_pixel = 2; break;
+    case 15: framebuffer.bytes_per_pixel = 2; break;
+    case 8: framebuffer.bytes_per_pixel = 1; break;
+    default:    
+      grub_vbe_bios_set_mode (old_mode, 0);
+      return grub_error (GRUB_ERR_BAD_DEVICE, 
+                         "cannot set VBE mode %x", 
+                         mode);
+      break;
     }
 
   /* If video mode is in indexed color, setup default VGA palette.  */
-  if (index_color_mode)
+  if (framebuffer.index_color_mode)
     {
       struct grub_vbe_palette_data *palette
        = (struct grub_vbe_palette_data *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
 
       /* Make sure that the BIOS can reach the palette.  */
       grub_memcpy (palette, vga_colors, sizeof (vga_colors));
-      status = grub_vbe_set_palette_data (sizeof (vga_colors) 
-                                          / sizeof (struct 
grub_vbe_palette_data), 
-                                          0, 
-                                          palette);
+      status = grub_vbe_bios_set_palette_data (sizeof (vga_colors) 
+                                               / sizeof (struct 
grub_vbe_palette_data), 
+                                               0, 
+                                               palette);
 
       /* For now, ignore the status. Not sure if this is fatal.  */
 #if 0
-      if (status != 0x004F)
+      if (status != GRUB_VBE_STATUS_OK)
        {
-         grub_vbe_set_mode (old_mode, 0);
+         grub_vbe_bios_set_mode (old_mode, 0);
          return grub_error (GRUB_ERR_BAD_DEVICE,
                             "cannot set the default VGA palette");
        }
@@ -224,12 +280,13 @@
   grub_vbe_status_t status;
 
   /* Make sure that VBE is supported.  */
-  if (grub_vbe_probe (0) != GRUB_ERR_NONE)
+  grub_vbe_probe (0);
+  if (grub_errno != GRUB_ERR_NONE)
     return grub_errno;
 
   /* Try to query current mode from VESA BIOS.  */
-  status = grub_vbe_get_mode (mode);
-  if (status != 0x004F)
+  status = grub_vbe_bios_get_mode (mode);
+  if (status != GRUB_VBE_STATUS_OK)
     return grub_error (GRUB_ERR_BAD_DEVICE, "cannot get current VBE mode");
 
   return GRUB_ERR_NONE;
@@ -244,15 +301,16 @@
   grub_vbe_status_t status;
 
   /* Make sure that VBE is supported.  */
-  if (grub_vbe_probe (0) != GRUB_ERR_NONE)
+  grub_vbe_probe (0);
+  if (grub_errno != GRUB_ERR_NONE)
     return grub_errno;
 
   /* If mode is not VESA mode, skip mode info query.  */
   if (mode >= 0x100)
     {
       /* Try to get mode info from VESA BIOS.  */
-      status = grub_vbe_get_mode_info (mode, mi_tmp);
-      if (status != 0x004F)
+      status = grub_vbe_bios_get_mode_info (mode, mi_tmp);
+      if (status != GRUB_VBE_STATUS_OK)
        return grub_error (GRUB_ERR_BAD_DEVICE,
                           "cannot get information on the mode %x", mode);
 
@@ -266,60 +324,75 @@
   return GRUB_ERR_NONE;
 }
 
-void
-grub_vbe_set_pixel_rgb (grub_uint32_t x,
-                       grub_uint32_t y,
-                        grub_uint8_t red,
-                        grub_uint8_t green,
-                        grub_uint8_t blue)
+static grub_uint8_t *
+grub_video_vbe_get_video_ptr (struct grub_video_render_target *source,
+                              grub_uint32_t x,
+                              grub_uint32_t y)
 {
-  grub_uint32_t value;
+  grub_uint8_t *ptr = 0;
+  
+  switch (source->mode_info.bpp)
+    {
+    case 32:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info.pitch
+            + x * 4;
+      break;
 
-  if (x >= active_mode_info.x_resolution)
-    return;
+    case 24:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info.pitch
+            + x * 3;
+      break;
 
-  if (y >= active_mode_info.y_resolution)
-    return;
+    case 16:
+    case 15:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info.pitch
+            + x * 2;
+      break;
 
-  if (controller_info.version >= 0x300)
-    {
-      red >>= 8 - active_mode_info.lin_red_mask_size;
-      green >>= 8 - active_mode_info.lin_green_mask_size;
-      blue >>= 8 - active_mode_info.lin_blue_mask_size;
-
-      value = red << active_mode_info.lin_red_field_position;
-      value |= green << active_mode_info.lin_green_field_position;
-      value |= blue << active_mode_info.lin_blue_field_position;
+    case 8:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info.pitch
+            + x;        
+      break;
     }
-  else
-    {
-      red >>= 8 - active_mode_info.red_mask_size;
-      green >>= 8 - active_mode_info.green_mask_size;
-      blue >>= 8 - active_mode_info.blue_mask_size;
+    
+  return ptr;
+}
 
-      value = red << active_mode_info.red_field_position;
-      value |= green << active_mode_info.green_field_position;
-      value |= blue << active_mode_info.blue_field_position;
-    }
+static void
+grub_video_vbe_draw_pixel (grub_uint32_t x,
+                           grub_uint32_t y,
+                           grub_video_color_t color)
+{
+  if (x >= render_target->mode_info.width)
+    return;
+
+  if (y >= render_target->mode_info.height)
+    return;
 
-  switch (active_mode_info.bits_per_pixel)
+  switch (render_target->mode_info.bpp)
     {
     case 32:
       {
-       grub_uint32_t *ptr = (grub_uint32_t *) (framebuffer
-                                               + y * bytes_per_scan_line
-                                               + x * 4);
+       grub_uint32_t *ptr;
        
-       *ptr = value;
+        ptr = (grub_uint32_t *)grub_video_vbe_get_video_ptr (render_target,
+                                                             x,
+                                                             y);
+       
+       *ptr = color;
       }
       break;
       
     case 24:
       {
-       grub_uint8_t *ptr = (grub_uint8_t *) (framebuffer
-                                             + y * bytes_per_scan_line
-                                             + x * 3);
-       grub_uint8_t *ptr2 = (grub_uint8_t *) &value;
+       grub_uint8_t *ptr;
+       grub_uint8_t *ptr2 = (grub_uint8_t *) &color;
+        
+        ptr = grub_video_vbe_get_video_ptr (render_target, x, y);
        
        ptr[0] = ptr2[0];
        ptr[1] = ptr2[1];
@@ -330,11 +403,25 @@
     case 16:
     case 15:
       {
-       grub_uint16_t *ptr = (grub_uint16_t *) (framebuffer
-                                               + y * bytes_per_scan_line
-                                               + x * 2);
+       grub_uint16_t *ptr;
+       
+        ptr = (grub_uint16_t *)grub_video_vbe_get_video_ptr (render_target,
+                                                             x,
+                                                             y);
        
-       *ptr = (grub_uint16_t) (value & 0xFFFF);
+       *ptr = (grub_uint16_t) (color & 0xFFFF);
+      }
+      break;
+
+    case 8:
+      {
+       grub_uint8_t *ptr;
+       
+        ptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (render_target,
+                                                            x,
+                                                            y);
+       
+       *ptr = (grub_uint8_t) (color & 0xFF);
       }
       break;
 
@@ -343,44 +430,1117 @@
     }
 }
 
-void
-grub_vbe_set_pixel_index (grub_uint32_t x,
-                          grub_uint32_t y,
-                          grub_uint8_t color)
+static grub_video_color_t
+grub_video_vbe_get_pixel (struct grub_video_render_target *source,
+                          grub_uint32_t x,
+                          grub_uint32_t y)
 {
-  if (x >= active_mode_info.x_resolution)
-    return;
+  grub_video_color_t color = 0;
+  
+  if (x >= source->mode_info.width)
+    return 0;
 
-  if (y >= active_mode_info.y_resolution)
-    return;
+  if (y >= source->mode_info.height)
+    return 0;
 
-  if (index_color_mode == 1)
+  switch (source->mode_info.bpp)
     {
-      grub_uint8_t *ptr = (grub_uint8_t *) (framebuffer
-                                           + y * bytes_per_scan_line
-                                           + x);
+    case 32:
+      color = *(grub_uint32_t *)grub_video_vbe_get_video_ptr (source, x, y);
+      break;
+      
+    case 24:
+      {
+       grub_uint8_t *ptr;
+        ptr = grub_video_vbe_get_video_ptr (source, x, y);
+        color = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
+      }
+      break;
 
-      *ptr = color;
+    case 16:
+    case 15:
+      color = *(grub_uint16_t *)grub_video_vbe_get_video_ptr (source, x, y);
+      break;
+      
+    case 8:
+      color = *(grub_uint8_t *)grub_video_vbe_get_video_ptr (source, x, y);
+      break;
+      
+    default:
+      break;
+    }
+
+  return color;    
+}
+
+static grub_err_t
+grub_video_vbe_init (void)
+{
+  grub_uint16_t *rm_mode_list;
+  grub_uint16_t *p;
+  grub_size_t mode_list_size;
+  struct grub_vbe_info_block info_block;
+
+  /* Check if there is adapter present.
+  
+     Firmware note: There has been a report that some cards store video mode
+     list in temporary memory. So we must first use vbe probe to get
+     refreshed information to receive valid pointers and data, and then
+     copy this information to somewhere safe.  */
+  grub_vbe_probe (&info_block);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+  
+  /* Copy modelist to local memory.  */
+  p = rm_mode_list = real2pm (info_block.video_mode_ptr);
+  while(*p++ != 0xFFFF)
+    ;
+  
+  mode_list_size = (grub_addr_t) p - (grub_addr_t) rm_mode_list;
+  mode_list = grub_malloc (mode_list_size);
+  if (! mode_list)
+    return grub_errno;
+  grub_memcpy (mode_list, rm_mode_list, mode_list_size);
+
+  /* Adapter could be found, figure out initial video mode.  */
+  grub_vbe_get_video_mode (&initial_mode);
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      /* Free allocated resources.  */
+      grub_free (mode_list);
+      mode_list = 0;
+      
+      return grub_errno;
+    }
+
+  /* Reset frame buffer and render target variables.  */
+  grub_memset (&framebuffer, 0, sizeof(framebuffer));  
+  render_target = &framebuffer.render_target;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_fini (void)
+{
+  grub_vbe_status_t status;
+  
+  /* Restore old video mode.  */
+  status = grub_vbe_bios_set_mode (initial_mode, 0);
+  if (status != GRUB_VBE_STATUS_OK)
+    /* TODO: Decide, is this something we want to do.  */
+    return grub_errno;
+  
+  /* TODO: Free any resources allocated by driver.  */
+  grub_free (mode_list);
+  mode_list = 0;
+
+  /* TODO: destroy render targets.  */
+  
+  /* Return success to caller.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_setup (unsigned int width,
+                      unsigned int height,
+                      unsigned int mode_type)
+{
+  grub_uint16_t *p;
+  struct grub_vbe_mode_info_block mode_info;
+  struct grub_vbe_mode_info_block best_mode_info;
+  grub_uint32_t best_mode = 0;
+  unsigned int i;
+  
+  /* Walk thru mode list and try to find matching mode.  */
+  for (p = mode_list; *p != 0xFFFF; p++)
+    {
+      grub_uint32_t mode = *p;
+      
+      grub_vbe_get_video_mode_info (mode, &mode_info);
+      if (grub_errno != GRUB_ERR_NONE)
+        {
+          /* Could not retrieve mode info, retreat.  */
+          grub_errno = GRUB_ERR_NONE;
+          break;
+        }
+
+      if ((mode_info.mode_attributes & 0x001) == 0)
+        /* If not available, skip it.  */
+        continue;
+
+      if ((mode_info.mode_attributes & 0x002) == 0)
+        /* Not enough information.  */
+        continue;
+
+      if ((mode_info.mode_attributes & 0x008) == 0)
+        /* Monochrome is unusable.  */
+        continue;
+
+      if ((mode_info.mode_attributes & 0x080) == 0)
+        /* We support only linear frame buffer modes.  */
+        continue;
+
+      if ((mode_info.mode_attributes & 0x010) == 0)
+        /* We allow only graphical modes.  */
+        continue;
+      
+      if ((mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL)
+          && (mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR))
+        /* Not compatible memory model.  */
+        continue;
+      
+      if ((mode_info.x_resolution != width)
+          || (mode_info.y_resolution != height))
+        /* Non matching resolution.  */
+        continue;
+
+      /* Check if user requested RGB or index color mode.  */
+      if ((mode_type & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0)
+        {
+          if (((mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+              && (mode_info.memory_model != 
GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL))
+            /* Requested only index color modes.  */
+            continue;
+
+          if (((mode_type & GRUB_VIDEO_MODE_TYPE_RGB) != 0)
+              && (mode_info.memory_model != 
GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR))
+            /* Requested only RGB modes.  */
+            continue;
+        }
+      
+      /* Select mode with most number of bits per pixel.  */
+      if (best_mode != 0)
+        if (mode_info.bits_per_pixel < best_mode_info.bits_per_pixel)
+          continue;
+      
+      /* Save so far best mode information for later use.  */
+      best_mode = mode;
+      grub_memcpy (&best_mode_info, &mode_info, sizeof (mode_info));
+    }
+
+  /* Try to initialize best mode found.  */
+  if (best_mode != 0)
+    {
+      /* If this fails, then we have mode selection heuristics problem, 
+         or adapter failure.  */
+      grub_vbe_set_video_mode (best_mode, &active_mode_info);
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;
+      
+      /* Now we are happily in requested video mode. Cache some info
+         in order to fasten later operations.  */
+      mode_in_use = best_mode;
+
+      /* Reset render target to framebuffer one.  */
+      render_target = &framebuffer.render_target;
+      
+      /* Fill mode info details in framebuffer's render target.  */
+      render_target->mode_info.width = active_mode_info.x_resolution;
+      render_target->mode_info.height = active_mode_info.y_resolution;
+
+      if (framebuffer.index_color_mode)
+        render_target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+      else
+        render_target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
+
+      render_target->mode_info.bpp = active_mode_info.bits_per_pixel;
+      render_target->mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel;
+      render_target->mode_info.pitch = framebuffer.bytes_per_scan_line;
+      render_target->mode_info.number_of_colors = 256; /* TODO: fix me.  */
+      render_target->mode_info.red_mask_size = active_mode_info.red_mask_size;
+      render_target->mode_info.red_field_pos = 
active_mode_info.red_field_position;
+      render_target->mode_info.green_mask_size = 
active_mode_info.green_mask_size;
+      render_target->mode_info.green_field_pos = 
active_mode_info.green_field_position;
+      render_target->mode_info.blue_mask_size = 
active_mode_info.blue_mask_size;
+      render_target->mode_info.blue_field_pos = 
active_mode_info.blue_field_position;
+      render_target->mode_info.reserved_mask_size = 
active_mode_info.rsvd_mask_size;
+      render_target->mode_info.reserved_field_pos = 
active_mode_info.rsvd_field_position;
+     
+      /* Reset viewport to match new mode.  */
+      render_target->viewport.x = 0;
+      render_target->viewport.y = 0;
+      render_target->viewport.width = active_mode_info.x_resolution;
+      render_target->viewport.height = active_mode_info.y_resolution;
+
+      /* Set framebuffer pointer and mark it as non allocated.  */
+      render_target->is_allocated = 0;
+      render_target->data = framebuffer.ptr;
+
+      /* Copy default palette to initialize emulated palette.  */
+      for (i = 0; 
+           i < (sizeof (vga_colors) 
+                / sizeof (struct grub_vbe_palette_data));
+           i++)
+        {
+          framebuffer.palette[i].r = vga_colors[i].red;
+          framebuffer.palette[i].g = vga_colors[i].green;
+          framebuffer.palette[i].b = vga_colors[i].blue;
+          framebuffer.palette[i].a = 0xFF;
+        }
+
+      return GRUB_ERR_NONE;
+    }
+
+  /* Couldn't found matching mode.  */
+  return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found.");
+}
+
+static grub_err_t
+grub_video_vbe_get_info (struct grub_video_mode_info *mode_info)
+{
+  /* Copy mode info from active render target.  */
+  grub_memcpy (mode_info, 
+               &render_target->mode_info, 
+               sizeof (struct grub_video_mode_info));
+  
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_palette (unsigned int start,
+                            unsigned int count,
+                            struct grub_video_palette_data *palette_data)
+{
+  unsigned int i;
+  
+  if (framebuffer.index_color_mode)
+    {
+      /* TODO: Implement setting indexed color mode palette to hardware.  */
+      //status = grub_vbe_bios_set_palette_data (sizeof (vga_colors) 
+      //                                         / sizeof (struct 
grub_vbe_palette_data), 
+      //                                         0, 
+      //                                         palette);
+      
+    }
+
+  /* Then set color to emulated palette. */
+  for (i = 0; (i < count) && ((i + start) < 256); i++)
+    framebuffer.palette[start + i] = palette_data[i];
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_get_palette (unsigned int start,
+                            unsigned int count,
+                            struct grub_video_palette_data *palette_data)
+{
+  unsigned int i;
+
+  /* Assume that we know everything from index color palette.  */
+  for (i = 0; (i < count) && ((i + start) < 256); i++)
+    palette_data[i] = framebuffer.palette[start + i];
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_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 reqion, mark its size as zero.  */
+  if (x > active_mode_info.x_resolution)
+    {
+      x = 0;
+      width = 0;
+    }
+  
+  if (y > active_mode_info.y_resolution)
+    {
+      y = 0;
+      height = 0;
+    }
+    
+  if (x + width > active_mode_info.x_resolution)
+    width = active_mode_info.x_resolution - x;
+
+  if (y + height > active_mode_info.y_resolution)
+    height = active_mode_info.y_resolution - y;
+
+  render_target->viewport.x = x;
+  render_target->viewport.y = y;
+  render_target->viewport.width = width;
+  render_target->viewport.height = height;
+  
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_get_viewport (unsigned int *x,
+                             unsigned int *y,
+                             unsigned int *width,
+                             unsigned int *height)
+{
+  if (x) *x = render_target->viewport.x;
+  if (y) *y = render_target->viewport.y;
+  if (width) *width = render_target->viewport.width;
+  if (height) *height = render_target->viewport.height;
+  
+  return GRUB_ERR_NONE;
+}
+
+static grub_video_color_t
+grub_video_vbe_map_color (grub_uint32_t color_name)
+{
+  /* TODO: implement color theme mapping code.  */
+  
+  if (color_name < 256)
+    {
+      if ((render_target->mode_info.mode_type
+           & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+        return color_name;
+      else
+        {
+          grub_video_color_t color;
+          
+          color = grub_video_vbe_map_rgb (framebuffer.palette[color_name].r,
+                                          framebuffer.palette[color_name].g,
+                                          framebuffer.palette[color_name].b);
+          
+          return color;
+        }
+    }
+    
+  return 0;
+}
+
+static grub_video_color_t
+grub_video_vbe_map_rgb (grub_uint8_t red,
+                        grub_uint8_t green,
+                        grub_uint8_t blue)
+{
+  if ((render_target->mode_info.mode_type 
+       & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+    {
+      int minindex = 0;
+      int delta = 0;
+      int tmp;
+      int val;
+      int i;
+      
+      /* Find best matching color.  */
+      for (i = 0; i < 256; i++)
+        {
+          val = framebuffer.palette[i].r - red;
+          tmp = val * val;
+          val = framebuffer.palette[i].g - green;
+          tmp += val * val;
+          val = framebuffer.palette[i].b - blue;
+          tmp += val * val;
+          
+          if (i == 0)
+            delta = tmp;
+          
+          if (tmp < delta)
+            {
+              delta = tmp;
+              minindex = i;
+              if (tmp == 0)
+                break;
+            }
+        }
+      
+      return minindex;
     }
   else
     {
-      color &= 0x0F;
+      grub_uint32_t value;
+      grub_uint8_t alpha = 255; /* Opaque color.  */
       
-      if (color < 16)
-       {
-         grub_vbe_set_pixel_rgb (x,
-                                  y,
-                                  vga_colors[color].red,
-                                  vga_colors[color].green,
-                                  vga_colors[color].blue);
-       }
+      red >>= 8 - render_target->mode_info.red_mask_size;
+      green >>= 8 - render_target->mode_info.green_mask_size;
+      blue >>= 8 - render_target->mode_info.blue_mask_size;
+      alpha >>= 8 - render_target->mode_info.reserved_mask_size;
+
+      value = red << render_target->mode_info.red_field_pos;
+      value |= green << render_target->mode_info.green_field_pos;
+      value |= blue << render_target->mode_info.blue_field_pos;
+      value |= alpha << render_target->mode_info.reserved_field_pos;
+      
+      return value;
+    }
+
+}
+
+static grub_video_color_t
+grub_video_vbe_map_rgba (grub_uint8_t red,
+                         grub_uint8_t green,
+                         grub_uint8_t blue,
+                         grub_uint8_t alpha)
+{
+  if ((render_target->mode_info.mode_type 
+       & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+    /* No alpha available in index color modes, just use
+       same value as in only RGB modes.  */
+    return grub_video_vbe_map_rgb (red, green, blue);
+  else
+    {
+      grub_uint32_t value;
+      
+      red >>= 8 - render_target->mode_info.red_mask_size;
+      green >>= 8 - render_target->mode_info.green_mask_size;
+      blue >>= 8 - render_target->mode_info.blue_mask_size;
+      alpha >>= 8 - render_target->mode_info.reserved_mask_size;
+
+      value = red << render_target->mode_info.red_field_pos;
+      value |= green << render_target->mode_info.green_field_pos;
+      value |= blue << render_target->mode_info.blue_field_pos;
+      value |= alpha << render_target->mode_info.reserved_field_pos;
+      
+      return value;
+    }
+}
+
+static void
+grub_video_vbe_unmap_color (struct grub_video_render_target * source,
+                            grub_video_color_t color,
+                            grub_uint8_t *red,
+                            grub_uint8_t *green,
+                            grub_uint8_t *blue,
+                            grub_uint8_t *alpha)
+{
+  if ((source->mode_info.mode_type 
+       & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+    {
+      /* If we have out of bounds color, return trasnparent black.  */
+      if (color > 255)
+        {
+          *red = 0;
+          *green = 0;
+          *blue = 0;
+          *alpha = 0;
+          return;
+        }
+        
+      *red = framebuffer.palette[color].r;
+      *green = framebuffer.palette[color].g;
+      *blue = framebuffer.palette[color].b;
+      *alpha = framebuffer.palette[color].a;
+      return;
+    }
+  else
+    {      
+      grub_uint32_t tmp;
+      
+      /* Get red component.  */
+      tmp = color >> source->mode_info.red_field_pos;
+      tmp &= (1 << source->mode_info.red_mask_size) - 1;
+      tmp <<= 8 - source->mode_info.red_mask_size;
+      tmp |= (1 << (8 - source->mode_info.red_mask_size)) - 1;
+      *red = tmp & 0xFF;
+
+      /* Get green component.  */
+      tmp = color >> source->mode_info.green_field_pos;
+      tmp &= (1 << source->mode_info.green_mask_size) - 1;
+      tmp <<= 8 - source->mode_info.green_mask_size;
+      tmp |= (1 << (8 - source->mode_info.green_mask_size)) - 1;
+      *green = tmp & 0xFF;
+
+      /* Get blue component.  */
+      tmp = color >> source->mode_info.blue_field_pos;
+      tmp &= (1 << source->mode_info.blue_mask_size) - 1;
+      tmp <<= 8 - source->mode_info.blue_mask_size;
+      tmp |= (1 << (8 - source->mode_info.blue_mask_size)) - 1;
+      *blue = tmp & 0xFF;
+
+      /* Get alpha component.  */
+      if (source->mode_info.reserved_mask_size > 0)
+        {
+          tmp = color >> source->mode_info.reserved_field_pos;
+          tmp &= (1 << source->mode_info.reserved_mask_size) - 1;
+          tmp <<= 8 - source->mode_info.reserved_mask_size;
+          tmp |= (1 << (8 - source->mode_info.reserved_mask_size)) - 1;
+        }
       else
-       {
-         grub_vbe_set_pixel_rgb (x,
-                                  y,
-                                  0,
-                                  0,
-                                  0);
-       }
+        {
+          /* If there is no alpha component, assume it opaque.  */
+          tmp = 255;
+        }
+
+      *alpha = tmp & 0xFF;
+    }
+}
+
+static grub_err_t
+grub_video_vbe_fill_rect (grub_video_color_t color,
+                          int x,
+                          int y,
+                          unsigned int width,
+                          unsigned int height)
+{
+  unsigned int i, j;
+
+  /* Make sure there is something to do.  */
+  if ((x > (int)render_target->viewport.width) || (x + (int)width < 0))
+    return GRUB_ERR_NONE;
+  if ((y > (int)render_target->viewport.height) || (y + (int)height < 0))
+    return GRUB_ERR_NONE;
+
+  /* Do not allow drawing out of viewport.  */
+  if (x < 0)
+    {
+      width += x;
+      x = 0;
+    }
+  if (y < 0)
+    {
+      height += y;
+      y = 0;
+    }
+  
+  if ((x + width) > render_target->viewport.width)
+    width = render_target->viewport.width - x;
+  if ((y + height) > render_target->viewport.height)
+    height = render_target->viewport.height - y;
+
+  /* Add viewport offset.  */
+  x += render_target->viewport.x;
+  y += render_target->viewport.y;
+
+  /* Fill area.  */
+  for (j = 0; j < height; j++)
+    for (i = 0; i < width; i++)
+      grub_video_vbe_draw_pixel (x+i, y+j, color);
+  
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_blit_glyph (struct grub_font_glyph * glyph,
+                           grub_video_color_t color,
+                           int x,
+                           int y)
+{
+  unsigned int width;
+  unsigned int charwidth;
+  unsigned int height;
+  unsigned int i;
+  unsigned int j;
+  unsigned int x_offset = 0;
+  unsigned int y_offset = 0;
+  
+  /* Make sure there is something to do.  */
+  if (x > (int)render_target->viewport.width)
+    return GRUB_ERR_NONE;
+    
+  if (y > (int)render_target->viewport.height)
+    return GRUB_ERR_NONE;
+
+  /* Calculate glyph dimensions.  */
+  width = ((glyph->width + 7) / 8) * 8;
+  charwidth = width;
+  height = glyph->height;
+  
+  if (x + (int)width < 0)
+    return GRUB_ERR_NONE;
+    
+  if (y + (int)height < 0)
+    return GRUB_ERR_NONE;
+
+  /* Do not allow drawing out of viewport.  */
+  if (x < 0)
+    {
+      width += x;
+      x_offset = (unsigned int)-x;
+      x = 0;
+    }
+  if (y < 0)
+    {
+      height += y;
+      y_offset = (unsigned int)-y;
+      y = 0;
+    }
+  
+  if ((x + width) > render_target->viewport.width)
+    width = render_target->viewport.width - x;
+  if ((y + height) > render_target->viewport.height)
+    height = render_target->viewport.height - y;
+
+  /* Add viewport offset.  */
+  x += render_target->viewport.x;
+  y += render_target->viewport.y;
+  
+  /* Draw glyph.  */
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+        {
+          if ((glyph->bitmap[((i + x_offset) / 8) 
+                             + (j + y_offset) * (charwidth / 8)] 
+               & (1 << ((charwidth - (i + x_offset) - 1) % 8))))
+            {
+              grub_video_vbe_draw_pixel (x+i, y+j, color);
+            }
+        }
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_blit_bitmap (struct grub_video_bitmap * bitmap,
+                            int x,
+                            int y,
+                            int offset_x,
+                            int offset_y,
+                            unsigned int width,                            
+                            unsigned int height)
+{
+  /* Make sure there is something to do.  */
+  if ((x > (int)render_target->viewport.width) || (x + (int)width < 0))
+    return GRUB_ERR_NONE;
+  if ((y > (int)render_target->viewport.height) || (y + (int)height < 0))
+    return GRUB_ERR_NONE;
+
+  /* Do not allow drawing out of viewport.  */
+  if (offset_x < 0)
+    {
+      width += offset_x;
+      x -= offset_x;
+      offset_x = 0;
+    }
+    
+  if (offset_y < 0)
+    {
+      height += offset_y;
+      y -= offset_y;
+      offset_y = 0;
+    }
+
+  if (x < 0)
+    {
+      width += x;
+      offset_x += (unsigned int)-x;
+      x = 0;
+    }
+  if (y < 0)
+    {
+      height += y;
+      offset_y += (unsigned int)-y;
+      y = 0;
+    }
+  
+  if ((x + width) > render_target->viewport.width)
+    width = render_target->viewport.width - x;
+  if ((y + height) > render_target->viewport.height)
+    height = render_target->viewport.height - y;
+
+  /* TODO: Limit drawing to bitmap dimensions.  */
+
+  /* Add viewport offset.  */
+  x += render_target->viewport.x;
+  y += render_target->viewport.y;
+
+  /* TODO: Render bitmap.  */
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_blit_render_target (struct grub_video_render_target *source,
+                                   int x,
+                                   int y,
+                                   int offset_x,
+                                   int offset_y,
+                                   unsigned int width,
+                                   unsigned int height)
+{
+  unsigned int i;
+  unsigned int j;
+
+  /* Make sure there is something to do.  */
+  if ((width == 0) || (height == 0))
+    return GRUB_ERR_NONE;
+  if ((x > (int)render_target->viewport.width) || (x + (int)width < 0))
+    return GRUB_ERR_NONE;
+  if ((y > (int)render_target->viewport.height) || (y + (int)height < 0))
+    return GRUB_ERR_NONE;    
+  if ((x + (int)source->mode_info.width) < 0)
+    return GRUB_ERR_NONE;
+  if ((y + (int)source->mode_info.height) < 0)
+    return GRUB_ERR_NONE;    
+  if ((offset_x > (int)source->mode_info.width) 
+      || (offset_x + (int)source->mode_info.width < 0))
+    return GRUB_ERR_NONE;
+  if ((offset_y > (int)source->mode_info.height) 
+      || (offset_y + (int)source->mode_info.height < 0))
+    return GRUB_ERR_NONE;    
+
+  /* If we have negative coordinates, optimize drawing to minimum.  */
+  if (offset_x < 0)
+    {
+      width += offset_x;
+      x -= offset_x;
+      offset_x = 0;
+    }
+    
+  if (offset_y < 0)
+    {
+      height += offset_y;
+      y -= offset_y;
+      offset_y = 0;
+    }
+    
+  if (x < 0)
+    {
+      width += x;
+      offset_x += (unsigned int)-x;
+      x = 0;
+    }
+    
+  if (y < 0)
+    {
+      height += y;
+      offset_y += (unsigned int)-y;
+      y = 0;
+    }
+  
+  /* Do not allow drawing out of viewport.  */
+  if ((x + width) > render_target->viewport.width)
+    width = render_target->viewport.width - x;
+  if ((y + height) > render_target->viewport.height)
+    height = render_target->viewport.height - y;
+  
+  if ((offset_x + width) > source->mode_info.width)
+    width = source->mode_info.width - offset_x;
+  if ((offset_y + height) > source->mode_info.height)
+    height = source->mode_info.height - offset_y;
+  
+  /* Limit drawing to source render target dimensions.  */
+  if (width > source->mode_info.width)
+    width = source->mode_info.width;
+  
+  if (height > source->mode_info.height)
+    height = source->mode_info.height;
+
+  /* Add viewport offset.  */
+  x += render_target->viewport.x;
+  y += render_target->viewport.y;
+
+  /* Render.  */
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+        {              
+          grub_uint8_t src_red;
+          grub_uint8_t src_green;
+          grub_uint8_t src_blue;
+          grub_uint8_t src_alpha;
+          grub_uint8_t dst_red;
+          grub_uint8_t dst_green;
+          grub_uint8_t dst_blue;
+          grub_uint8_t dst_alpha;
+          grub_video_color_t src_color;
+          grub_video_color_t dst_color;
+          
+          src_color = grub_video_vbe_get_pixel (source, i + offset_x, j + 
offset_y);
+          grub_video_vbe_unmap_color (source, 
+                                      src_color, 
+                                      &src_red, 
+                                      &src_green, 
+                                      &src_blue, 
+                                      &src_alpha);
+              
+          if (src_alpha == 0)
+            continue;
+          
+          if (src_alpha == 255)
+            {
+              dst_color = grub_video_vbe_map_rgba (src_red, 
+                                                   src_green,
+                                                   src_blue,
+                                                   src_alpha);
+               grub_video_vbe_draw_pixel (x + i, y + j, dst_color);
+               continue;
+            }
+
+          dst_color = grub_video_vbe_get_pixel (render_target,
+                                                x + i,
+                                                y + j);
+          
+          grub_video_vbe_unmap_color (render_target, 
+                                      dst_color, 
+                                      &dst_red, 
+                                      &dst_green, 
+                                      &dst_blue, 
+                                      &dst_alpha);
+          
+          dst_red = (((src_red * src_alpha)
+                      + (dst_red * (255 - src_alpha))) / 255);
+          dst_green = (((src_green * src_alpha)
+                        + (dst_green * (255 - src_alpha))) / 255);
+          dst_blue = (((src_blue * src_alpha)
+                       + (dst_blue * (255 - src_alpha))) / 255);
+                    
+          dst_alpha = src_alpha;
+          dst_color = grub_video_vbe_map_rgba (dst_red, 
+                                               dst_green,
+                                               dst_blue,
+                                               dst_alpha);
+
+           grub_video_vbe_draw_pixel (x + i, y + j, dst_color);
+        }
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_scroll (grub_video_color_t color,
+                       int dx,
+                       int dy)
+{
+  int width;
+  int height;
+  int src_x;
+  int src_y;
+  int dst_x;
+  int dst_y;
+  
+  /* 1. Check if we have something to do.  */
+  if ((dx == 0) && (dy == 0))
+    return GRUB_ERR_NONE;
+
+  width = render_target->viewport.width - grub_abs (dx);
+  height = render_target->viewport.height - grub_abs (dy);
+  
+  if (dx < 0)
+    {
+      src_x = render_target->viewport.x - dx;
+      dst_x = render_target->viewport.x;
+    }
+  else
+    {
+      src_x = render_target->viewport.x;
+      dst_x = render_target->viewport.x + dx;
+    }
+
+  if (dy < 0)
+    {
+      src_y = render_target->viewport.y - dy;
+      dst_y = render_target->viewport.y;
+    }
+  else
+    {
+      src_y = render_target->viewport.y;
+      dst_y = render_target->viewport.y + dy;
+    }
+
+  /* 2. Check if there is need to copy data.  */
+  if ((grub_abs (dx) < render_target->viewport.width) 
+       && (grub_abs (dy) < render_target->viewport.height))
+    {
+      /* 3. Move data in render target.  */
+      grub_uint8_t *src;
+      grub_uint8_t *dst;
+      int j;
+            
+      for (j = 0; j < height; j++)
+        {
+          dst = grub_video_vbe_get_video_ptr (render_target, dst_x, dst_y + j);
+          src = grub_video_vbe_get_video_ptr (render_target, src_x, src_y + j);
+          grub_memmove (dst, 
+                        src,
+                        width * render_target->mode_info.bytes_per_pixel);
+        }
+    }
+  
+  /* 4. Fill empty space with specified color. In this implementation
+     there might be colliding areas but at the moment there is no need
+     to optimize this.  */
+
+  /* 4a. Fill top & bottom parts.  */
+  if (dy > 0)
+    grub_video_vbe_fill_rect (color,
+                              0, 0,
+                              render_target->viewport.width, dy);
+  else if (dy < 0)
+    {
+      if (render_target->viewport.height < grub_abs (dy))
+        dy = -render_target->viewport.height;
+        
+      grub_video_vbe_fill_rect (color, 
+                                0, render_target->viewport.height + dy, 
+                                render_target->viewport.width, -dy);
+    }
+
+  /* 4b. Fill left & right parts.  */
+  if (dx > 0)
+    grub_video_vbe_fill_rect (color, 
+                              0, 0, 
+                              dx, render_target->viewport.height);
+  else if (dx < 0)
+    {
+      if (render_target->viewport.width < grub_abs (dx))
+        dx = -render_target->viewport.width;
+        
+      grub_video_vbe_fill_rect (color, 
+                                render_target->viewport.width + dx, 0, 
+                                -dx, render_target->viewport.height);
+    }
+  
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t 
+grub_video_vbe_swap_buffers (void)
+{
+  /* TODO: Implement buffer swapping.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_create_render_target (struct grub_video_render_target **result,
+                                     unsigned int mode_type,
+                                     unsigned int width,
+                                     unsigned int height)
+{
+  struct grub_video_render_target *target;
+  unsigned int size;
+  
+  /* Validate arguments.  */
+  if ((! result)
+      || (width == 0)
+      || (height == 0))
+    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                       "invalid argument given.");
+  
+  /* Allocate memory for render target.  */
+  target = grub_malloc (sizeof (struct grub_video_render_target));
+  if (! target)
+    return grub_errno;
+
+  /* TODO: Implement other types too.
+     Currently only 32bit render targets are supported.  */
+  
+  /* Mark render target as allocated.  */
+  target->is_allocated = 1;
+  
+  /* Maximize viewport.  */
+  target->viewport.x = 0;
+  target->viewport.y = 0;
+  target->viewport.width = width;
+  target->viewport.height = height;
+
+  /* Setup render target format.  */
+  target->mode_info.width = width;
+  target->mode_info.height = height;
+  target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB 
+                                | GRUB_VIDEO_MODE_TYPE_ALPHA;
+  target->mode_info.bpp = 32;
+  target->mode_info.bytes_per_pixel = 4;
+  target->mode_info.pitch = target->mode_info.bytes_per_pixel * width;
+  target->mode_info.number_of_colors = 256; /* Emulated paletted.  */
+  target->mode_info.red_mask_size = 8;
+  target->mode_info.red_field_pos = 0;
+  target->mode_info.green_mask_size = 8;
+  target->mode_info.green_field_pos = 8;
+  target->mode_info.blue_mask_size = 8;
+  target->mode_info.blue_field_pos = 16;
+  target->mode_info.reserved_mask_size = 8;
+  target->mode_info.reserved_field_pos = 24;
+
+  /* Calculate size needed for the data.  */
+  size = (width * target->mode_info.bytes_per_pixel) * height;
+  
+  target->data = grub_malloc (size);
+  if (! target->data)
+    {
+      grub_free (target);
+      return grub_errno;
     }
+  
+  /* Clear render target with black and maximum transparency.  */
+  grub_memset (target->data, 0, size);
+
+  /* TODO: Add render target to render target list.  */
+  
+  /* Save result to caller.  */
+  *result = target;
+  
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_delete_render_target (struct grub_video_render_target *target)
+{
+  /* If there is no target, then just return without error.  */
+  if (! target)
+    return GRUB_ERR_NONE;
+    
+  /* TODO: Delist render target fron render target list.  */
+    
+  /* If this is software render target, free it's memory.  */
+  if (target->is_allocated)
+    grub_free (target->data);
+        
+  /* Free render target.  */
+  grub_free (target);
+  
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_active_render_target (struct grub_video_render_target 
*target)
+{
+  if (target == GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER)
+    {
+      render_target = &framebuffer.render_target;
+      
+      return GRUB_ERR_NONE;
+    }
+  
+  if (target == GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER)
+    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, 
+                       "double buffering not implemented yet.");
+    
+  if (! target->data)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, 
+                       "invalid render target given.");
+  
+  render_target = target;
+  
+  return GRUB_ERR_NONE;
+}
+
+static struct grub_video_adapter grub_video_vbe_adapter =
+  {
+    .name = "VESA BIOS Extension Video Driver",
+
+    .init = grub_video_vbe_init,
+    .fini = grub_video_vbe_fini,
+    .setup = grub_video_vbe_setup,
+    .get_info = grub_video_vbe_get_info,
+    .set_palette = grub_video_vbe_set_palette,
+    .get_palette = grub_video_vbe_get_palette,
+    .set_viewport = grub_video_vbe_set_viewport,
+    .get_viewport = grub_video_vbe_get_viewport,
+    .map_color = grub_video_vbe_map_color,
+    .map_rgb = grub_video_vbe_map_rgb,
+    .map_rgba = grub_video_vbe_map_rgba,
+    .fill_rect = grub_video_vbe_fill_rect,
+    .blit_glyph = grub_video_vbe_blit_glyph,
+    .blit_bitmap = grub_video_vbe_blit_bitmap,
+    .blit_render_target = grub_video_vbe_blit_render_target,
+    .scroll = grub_video_vbe_scroll,
+    .swap_buffers = grub_video_vbe_swap_buffers,
+    .create_render_target = grub_video_vbe_create_render_target,
+    .delete_render_target = grub_video_vbe_delete_render_target,
+    .set_active_render_target = grub_video_vbe_set_active_render_target,
+    
+    .next = 0  
+  };
+
+GRUB_MOD_INIT(video_i386_pc_vbe)
+{
+  grub_video_register (&grub_video_vbe_adapter);
+}
+
+GRUB_MOD_FINI(video_i386_pc_ovbe)
+{
+  grub_video_unregister (&grub_video_vbe_adapter);
 }
diff -ruN -x '*CVS*' grub2/video/video.c grub2.new/video/video.c
--- grub2/video/video.c 1970-01-01 02:00:00.000000000 +0200
+++ grub2.new/video/video.c     2006-03-03 16:57:12.779780640 +0200
@@ -0,0 +1,372 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/video.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+
+/* The list of video adapters registerd to system.  */
+static grub_video_adapter_t grub_video_adapter_list;
+
+/* Active video adapter.  */
+static grub_video_adapter_t grub_video_adapter_active;
+
+void
+grub_video_register (grub_video_adapter_t adapter)
+{
+  adapter->next = grub_video_adapter_list;
+  grub_video_adapter_list = adapter;
+}
+
+void
+grub_video_unregister (grub_video_adapter_t adapter)
+{
+  grub_video_adapter_t *p, q;
+  
+  for (p = &grub_video_adapter_list, q = *p; q; p = &(q->next), q = q->next)
+    if (q == adapter)
+      {
+        *p = q->next;
+        break;
+      }                                    
+}
+
+void
+grub_video_iterate (int (*hook) (grub_video_adapter_t adapter))
+{
+  grub_video_adapter_t p;
+  
+  for (p = grub_video_adapter_list; p; p = p->next)
+    if (hook (p))
+      break;
+}
+
+grub_err_t
+grub_video_setup (unsigned int width,
+                  unsigned int height,
+                  unsigned int mode_type)
+{
+  grub_video_adapter_t p;
+
+  /* De-activate last set video adapter.  */
+  if (grub_video_adapter_active)
+    {
+      /* Finalize adapter.  */
+      grub_video_adapter_active->fini ();
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;
+        
+      /* Mark active adapter as not set.  */
+      grub_video_adapter_active = 0;
+    }
+  
+  /* Loop thru all possible video adapter trying to find requested mode.  */
+  for (p = grub_video_adapter_list; p; p = p->next)
+    {
+      /* Try to initialize adapter, if can't skip to next.  */
+      p->init ();
+      if (grub_errno != GRUB_ERR_NONE)
+        {
+          grub_errno = GRUB_ERR_NONE;
+          continue;
+        }
+
+      /* Try to initialize video mode.  */      
+      p->setup (width, height, mode_type);
+      if (grub_errno == GRUB_ERR_NONE)
+        {
+          /* Valid mode found from adapter, and it has been activated.
+             Specify it as active adapter.  */
+          grub_video_adapter_active = p;
+          return GRUB_ERR_NONE;
+        }
+      else
+        {
+          grub_errno = GRUB_ERR_NONE;        
+        }
+
+      /* No valid mode found in this adapter, finalize adapter.  */
+      p->fini ();
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;
+    }
+  
+  /* We couldn't find suitable adapter for specified mode.  */
+  return grub_error (GRUB_ERR_UNKNOWN_DEVICE, 
+                     "Can't locate valid adapter for mode");
+}
+
+grub_err_t
+grub_video_restore (void)
+{
+  if (grub_video_adapter_active)
+    {
+      grub_video_adapter_active->fini ();
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;
+      
+      grub_video_adapter_active = 0;
+    }
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_video_get_info (struct grub_video_mode_info *mode_info)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+  
+  return grub_video_adapter_active->get_info (mode_info);
+}
+
+grub_err_t
+grub_video_set_palette (unsigned int start,
+                        unsigned int count,
+                        struct grub_video_palette_data *palette_data)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+  
+  return grub_video_adapter_active->set_palette (start, count, palette_data);
+}
+
+grub_err_t
+grub_video_get_palette (unsigned int start,
+                        unsigned int count,
+                        struct grub_video_palette_data *palette_data)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+  
+  return grub_video_adapter_active->get_palette (start, count, palette_data);
+}
+
+grub_err_t
+grub_video_set_viewport (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_viewport (x, y, width, height);
+}
+
+grub_err_t
+grub_video_get_viewport (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_viewport (x, y, width, height);
+}
+
+grub_video_color_t
+grub_video_map_color (grub_uint32_t color_name)
+{
+  if (! grub_video_adapter_active)
+    {
+      return 0;
+    }
+
+  return grub_video_adapter_active->map_color (color_name);
+}
+
+grub_video_color_t
+grub_video_map_rgb (grub_uint8_t red,
+                    grub_uint8_t green,
+                    grub_uint8_t blue)
+{
+  if (! grub_video_adapter_active)
+    {
+      return 0;
+    }
+
+  return grub_video_adapter_active->map_rgb (red, green, blue);
+}
+
+grub_video_color_t
+grub_video_map_rgba (grub_uint8_t red,
+                     grub_uint8_t green,
+                     grub_uint8_t blue,
+                     grub_uint8_t alpha)
+{
+  if (! grub_video_adapter_active)
+    {
+      return 0;
+    }
+
+  return grub_video_adapter_active->map_rgba (red, green, blue, alpha);
+}
+
+grub_err_t
+grub_video_fill_rect (grub_video_color_t color,
+                      int x,
+                      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->fill_rect (color, x, y, width, height);
+}
+
+grub_err_t
+grub_video_blit_glyph (struct grub_font_glyph *glyph,
+                       grub_video_color_t color,
+                       int x,
+                       int y)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+
+  return grub_video_adapter_active->blit_glyph (glyph, color, x, y);
+}
+
+grub_err_t
+grub_video_blit_bitmap (struct grub_video_bitmap *bitmap,
+                        int x,
+                        int y,
+                        int offset_x,
+                        int offset_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->blit_bitmap (bitmap, 
+                                                 x, y, 
+                                                 offset_x, offset_y,
+                                                 width, height);
+}
+
+grub_err_t
+grub_video_blit_render_target (struct grub_video_render_target *target,
+                               int x,
+                               int y,
+                               int offset_x,
+                               int offset_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->blit_render_target (target, 
+                                                        x, y,
+                                                        offset_x, offset_y, 
+                                                        width, height);
+}
+
+grub_err_t
+grub_video_scroll (grub_video_color_t color,
+                   int dx,
+                   int dy)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+
+  return grub_video_adapter_active->scroll (color, dx, dy);
+}
+
+grub_err_t
+grub_video_swap_buffers (void)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+
+  return grub_video_adapter_active->swap_buffers ();
+}
+
+grub_err_t
+grub_video_create_render_target (struct grub_video_render_target **result,
+                                 unsigned int mode_type,
+                                 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->create_render_target (result,
+                                                          mode_type,
+                                                          width,
+                                                          height);
+}
+
+grub_err_t
+grub_video_delete_render_target (struct grub_video_render_target *target)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+
+  return grub_video_adapter_active->delete_render_target (target);
+}
+
+grub_err_t
+grub_video_set_active_render_target (struct grub_video_render_target *target)
+{
+  if (! grub_video_adapter_active)
+    {
+      return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+    }
+
+  return grub_video_adapter_active->set_active_render_target (target);
+}
+
+GRUB_MOD_INIT(video_video)
+{
+  grub_video_adapter_active = 0;
+  grub_video_adapter_list = 0;
+}
+
+GRUB_MOD_FINI(video_video)
+{
+}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]