grub-devel
[Top][All Lists]
Advanced

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

[patch] Added bitmap support to Video API


From: Vesa Jääskeläinen
Subject: [patch] Added bitmap support to Video API
Date: Sat, 29 Jul 2006 15:38:18 +0300
User-agent: Thunderbird 1.5.0.5 (Windows/20060719)

Hi,

I have just made a patch to add bitmap support to Video API. It contains
example bitmap loader for .tga files. At this point there is no real
example how to use them, but I have tried to update wiki to reflect
changes (except that bitmap handling is not there yet).

New functionality was introduced to Video API to specify blitting
operator. Now there is only two operators specified, replace and blend.
Replace just uses source pixel data and blits it destination and blend
uses source pixel alpha value to blend source and destination pixels.

Reason why I wanted to give patch before better example how to use is
ready is that I want it to get to next grub release and I don't want to
block other development. And I didn't include that background bitmap
loading to gfxterm in this patch as I would rather like some development
to improve menu system than to stall it :).

Patch is attached to this message, any comments are welcome.

Thanks,
Vesa Jääskeläinen
Index: ChangeLog
===================================================================
RCS file: /sources/grub/grub2/ChangeLog,v
retrieving revision 1.288
diff -u -r1.288 ChangeLog
--- ChangeLog   29 Jul 2006 11:22:52 -0000      1.288
+++ ChangeLog   29 Jul 2006 12:16:52 -0000
@@ -1,5 +1,90 @@
 2006-07-29  Vesa Jaaskelainen  <address@hidden>
 
+       * include/grub/bitmap.h: New file.
+
+       * include/grub/i386/pc/vbeutil.h: Likewise.
+
+       * video/bitmap.c: Likewise.
+
+       * video/readers/tga.c: Likewise.
+
+       * video/i386/pc/vbeutil.c: Likewise.
+
+       * commands/videotest.c: Code cleanup and updated to reflect to new
+       video API.
+
+       * term/gfxterm.c: Likewise.
+
+       * video/video.c: Likewise.
+
+       * conf/i386-pc.rmk (pkgdata_MODULES): Added tga.mod and bitmap.mod.
+       (vbe_mod_SOURCES): Added video/i386/pc/vbeutil.c.
+       (bitmap_mod_SOURCES): New entry.
+       (bitmap_mod_CFLAGS): Likewise.
+       (bitmap_mod_LDFLAGS): Likewise.
+       (tga_mod_SOURCES): Likewise.
+       (tga_mod_CFLAGS): Likewise.
+       (tga_mod_LDFLAGS): Likewise.
+
+       * include/grub/video.h (grub_video_blit_operators): New enum type.
+       (grub_video_render_target): Changed as forward declaration and moved
+       actual definition to be video driver specific.
+       (grub_video_adapter.blit_bitmap): Added blitting operator.
+       (grub_video_adapter.blit_render_target): Likewise.
+       (grub_video_blit_bitmap): Likewise.
+       (grub_video_blit_render_target): Likewise.
+
+       * include/grub/i386/pc/vbe.h (grub_video_render_target): Added
+       driver specific render target definition.
+       (grub_video_vbe_map_rgba): Added driver internal helper.
+       (grub_video_vbe_unmap_color): Updated to use
+       grub_video_i386_vbeblit_info.
+       (grub_video_vbe_get_video_ptr): Likewise.
+
+       * include/grub/i386/pc/vbeblit.h
+       (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8): Updated to use
+       grub_video_i386_vbeblit_info.
+       (grub_video_i386_vbeblit_R8G8B8_R8G8B8A8): Likewise.
+       (grub_video_i386_vbeblit_index_R8G8B8A8): Likewise.
+       (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8): Likewise.
+       (grub_video_i386_vbeblit_R8G8B8_R8G8B8): Likewise.
+       (grub_video_i386_vbeblit_index_R8G8B8): Likewise.
+       (grub_video_i386_vbeblit_index_index): Likewise.
+       (grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8): New blitter function.
+       (grub_video_i386_vbeblit_R8G8B8_R8G8B8X8): Likewise.
+       (grub_video_i386_vbeblit_index_R8G8B8X8): Likewise.
+       (grub_video_i386_vbeblit_blend): Added generic blitter for blend
+       operator.
+       (grub_video_i386_vbeblit_replace): Added generic blitter for replace
+       operator.
+
+       * video/i386/pc/vbeblit.c: Updated to reflect changes on
+       include/grub/i386/pc/vbeblit.h.
+
+       * include/grub/i386/pc/vbefill.h (grub_video_i386_vbefill_R8G8B8A8):
+       Updated to use grub_video_i386_vbeblit_info.
+       (grub_video_i386_vbefill_R8G8B8): Likewise.
+       (grub_video_i386_vbefill_index): Likewise.
+       (grub_video_i386_vbefill): Added generic filler.
+
+       * video/i386/pc/vbefill.c: Updated to reflect changes on
+       include/grub/i386/pc/vbefill.h.
+
+       * video/i386/pc/vbe.c (grub_video_vbe_get_video_ptr): Updated to use
+       grub_video_i386_vbeblit_info.
+       (grub_video_vbe_unmap_color): Likewise.
+       (grub_video_vbe_blit_glyph): Likewise.
+       (grub_video_vbe_scroll): Likewise.
+       (grub_video_vbe_draw_pixel): Removed function.
+       (grub_video_vbe_get_pixel): Likewise.
+       (grub_video_vbe_fill_rect): Moved all blitters to vbefill.c and
+       updated code to use it.
+       (common_blitter): Added common blitter for render target and bitmap.
+       (grub_video_vbe_blit_bitmap): Updated to use common_blitter.
+       (grub_video_vbe_blit_render_target): Likewise.
+
+2006-07-29  Vesa Jaaskelainen  <address@hidden>
+
        * include/grub/video.h: Code cleanup.
 
        * include/grub/i386/pc/vbe.h: Likewise.
Index: commands/videotest.c
===================================================================
RCS file: /sources/grub/grub2/commands/videotest.c,v
retrieving revision 1.1
diff -u -r1.1 videotest.c
--- commands/videotest.c        14 Mar 2006 19:08:33 -0000      1.1
+++ commands/videotest.c        29 Jul 2006 12:16:52 -0000
@@ -36,7 +36,7 @@
   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;
@@ -48,21 +48,21 @@
   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, width, height,
                                    GRUB_VIDEO_MODE_TYPE_RGB
                                    | GRUB_VIDEO_MODE_TYPE_ALPHA);
 
-  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);      
                             
+  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);
 
@@ -73,18 +73,18 @@
                            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_font_get_glyph ('A', &glyph);
   grub_video_blit_glyph (&glyph, color, 16, 16);
-  grub_font_get_glyph ('B', &glyph);  
+  grub_font_get_glyph ('B', &glyph);
   grub_video_blit_glyph (&glyph, color, 16 * 2, 16);
 
-  grub_font_get_glyph ('*', &glyph);  
-  
+  grub_font_get_glyph ('*', &glyph);
+
   for (i = 0; i < 16; i++)
     {
       color = grub_video_map_color (i);
@@ -98,18 +98,19 @@
     {
       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_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, 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;
 }
Index: conf/i386-pc.rmk
===================================================================
RCS file: /sources/grub/grub2/conf/i386-pc.rmk,v
retrieving revision 1.66
diff -u -r1.66 i386-pc.rmk
--- conf/i386-pc.rmk    2 Jul 2006 15:30:43 -0000       1.66
+++ conf/i386-pc.rmk    29 Jul 2006 12:16:52 -0000
@@ -112,7 +112,7 @@
 pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod \
        _multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod      \
        vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
-       videotest.mod play.mod
+       videotest.mod play.mod bitmap.mod tga.mod
 
 # For _chain.mod.
 _chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -171,7 +171,7 @@
 
 # For vbe.mod.
 vbe_mod_SOURCES = video/i386/pc/vbe.c video/i386/pc/vbeblit.c \
-                 video/i386/pc/vbefill.c
+                 video/i386/pc/vbefill.c video/i386/pc/vbeutil.c
 vbe_mod_CFLAGS = $(COMMON_CFLAGS)
 vbe_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
@@ -205,4 +205,14 @@
 videotest_mod_CFLAGS = $(COMMON_CFLAGS)
 videotest_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For bitmap.mod
+bitmap_mod_SOURCES = video/bitmap.c
+bitmap_mod_CFLAGS = $(COMMON_CFLAGS)
+bitmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For tga.mod
+tga_mod_SOURCES = video/readers/tga.c
+tga_mod_CFLAGS = $(COMMON_CFLAGS)
+tga_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
Index: include/grub/bitmap.h
===================================================================
RCS file: include/grub/bitmap.h
diff -N include/grub/bitmap.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ include/grub/bitmap.h       29 Jul 2006 12:16:52 -0000
@@ -0,0 +1,71 @@
+/*
+ *  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_BITMAP_HEADER
+#define GRUB_BITMAP_HEADER     1
+
+#include <grub/err.h>
+#include <grub/symbol.h>
+#include <grub/types.h>
+#include <grub/video.h>
+
+struct grub_video_bitmap
+{
+  /* Bitmap format description.  */
+  struct grub_video_mode_info mode_info;
+
+  /* Pointer to bitmap data formatted according to mode_info.  */
+  void *data;
+};
+
+struct grub_video_bitmap_reader
+{
+  /* File extension for this bitmap type (including dot).  */
+  const char *extension;
+
+  /* Reader function to load bitmap.  */
+  grub_err_t (*reader) (struct grub_video_bitmap **bitmap,
+                        const char *filename);
+
+  /* Next reader.  */
+  struct grub_video_bitmap_reader *next;
+};
+typedef struct grub_video_bitmap_reader *grub_video_bitmap_reader_t;
+
+void grub_video_bitmap_reader_register (grub_video_bitmap_reader_t reader);
+void grub_video_bitmap_reader_unregister (grub_video_bitmap_reader_t reader);
+
+grub_err_t grub_video_bitmap_create (struct grub_video_bitmap **bitmap,
+                                     unsigned int width, unsigned int height,
+                                     enum grub_video_blit_format blit_format);
+
+grub_err_t grub_video_bitmap_destroy (struct grub_video_bitmap *bitmap);
+
+grub_err_t grub_video_bitmap_load (struct grub_video_bitmap **bitmap,
+                                   const char *filename);
+
+unsigned int grub_video_bitmap_get_width (struct grub_video_bitmap *bitmap);
+unsigned int grub_video_bitmap_get_height (struct grub_video_bitmap *bitmap);
+
+void grub_video_bitmap_get_mode_info (struct grub_video_bitmap *bitmap,
+                                      struct grub_video_mode_info *mode_info);
+
+void *grub_video_bitmap_get_data (struct grub_video_bitmap *bitmap);
+
+#endif /* ! GRUB_BITMAP_HEADER */
Index: include/grub/video.h
===================================================================
RCS file: /sources/grub/grub2/include/grub/video.h,v
retrieving revision 1.4
diff -u -r1.4 video.h
--- include/grub/video.h        29 Jul 2006 11:22:52 -0000      1.4
+++ include/grub/video.h        29 Jul 2006 12:16:52 -0000
@@ -23,10 +23,18 @@
 #include <grub/err.h>
 #include <grub/types.h>
 
+/* Video color in hardware dependant format.  Users should not assume any
+   specific coding format.  */
 typedef grub_uint32_t grub_video_color_t;
 
+/* This structure is driver specific and should not be accessed directly by 
+   outside code.  */
 struct grub_video_render_target;
 
+/* Forward declarations for used data structures.  */
+struct grub_font_glyph;
+struct grub_video_bitmap;
+
 /* Defines used to describe video mode or rendering target.  */
 #define GRUB_VIDEO_MODE_TYPE_ALPHA             0x00000008
 #define GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED   0x00000004
@@ -60,6 +68,15 @@
     GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR
   };
 
+/* Define blitting operators.  */
+enum grub_video_blit_operators
+  {
+    /* Replace target bitmap data with source.  */
+    GRUB_VIDEO_BLIT_REPLACE,
+    /* Blend target and source based on source's alpha value.  */
+    GRUB_VIDEO_BLIT_BLEND
+  };
+
 struct grub_video_mode_info
 {
   /* Width of the screen.  */
@@ -113,29 +130,6 @@
   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).  */
@@ -144,9 +138,6 @@
   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.  */
@@ -190,10 +181,12 @@
                             grub_video_color_t color, int x, int y);
 
   grub_err_t (*blit_bitmap) (struct grub_video_bitmap *bitmap,
+                             enum grub_video_blit_operators oper,
                              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,
+                                    enum grub_video_blit_operators oper,
                                     int x, int y, int offset_x, int offset_y,
                                     unsigned int width, unsigned int height);
 
@@ -254,10 +247,12 @@
                                   grub_video_color_t color, int x, int y);
 
 grub_err_t grub_video_blit_bitmap (struct grub_video_bitmap *bitmap,
+                                   enum grub_video_blit_operators oper,
                                    int x, int y, int offset_x, int offset_y,
                                    unsigned int width, unsigned int height);
 
 grub_err_t grub_video_blit_render_target (struct grub_video_render_target 
*source,
+                                          enum grub_video_blit_operators oper,
                                           int x, int y,
                                           int offset_x, int offset_y,
                                           unsigned int width,
Index: include/grub/i386/pc/vbe.h
===================================================================
RCS file: /sources/grub/grub2/include/grub/i386/pc/vbe.h,v
retrieving revision 1.6
diff -u -r1.6 vbe.h
--- include/grub/i386/pc/vbe.h  29 Jul 2006 11:22:52 -0000      1.6
+++ include/grub/i386/pc/vbe.h  29 Jul 2006 12:16:52 -0000
@@ -205,13 +205,43 @@
                                          struct grub_vbe_mode_info_block 
*mode_info);
 
 /* VBE module internal prototypes (should not be used from elsewhere).  */
-grub_uint8_t * grub_video_vbe_get_video_ptr (struct grub_video_render_target 
*source,
+struct grub_video_i386_vbeblit_info;
+
+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;
+};
+
+grub_uint8_t * grub_video_vbe_get_video_ptr (struct 
grub_video_i386_vbeblit_info *source,
                                              grub_uint32_t x, grub_uint32_t y);
 
 grub_video_color_t grub_video_vbe_map_rgb (grub_uint8_t red, grub_uint8_t 
green,
                                            grub_uint8_t blue);
 
-void grub_video_vbe_unmap_color (struct grub_video_render_target * source,
+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);
+
+void grub_video_vbe_unmap_color (struct grub_video_i386_vbeblit_info *source,
                                  grub_video_color_t color, grub_uint8_t *red,
                                  grub_uint8_t *green, grub_uint8_t *blue,
                                  grub_uint8_t *alpha);
Index: include/grub/i386/pc/vbeblit.h
===================================================================
RCS file: /sources/grub/grub2/include/grub/i386/pc/vbeblit.h,v
retrieving revision 1.1
diff -u -r1.1 vbeblit.h
--- include/grub/i386/pc/vbeblit.h      31 Mar 2006 14:26:34 -0000      1.1
+++ include/grub/i386/pc/vbeblit.h      29 Jul 2006 12:16:52 -0000
@@ -20,47 +20,81 @@
 #ifndef GRUB_VBEBLIT_MACHINE_HEADER
 #define GRUB_VBEBLIT_MACHINE_HEADER    1
 
+/* NOTE: This header is private header for vbe driver and should not be used
+   in other parts of the code.  */
+
+struct grub_video_i386_vbeblit_info;
+
 void
-grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8 (struct grub_video_render_target 
*dst,
-                                           struct grub_video_render_target 
*src,
+grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8 (struct grub_video_i386_vbeblit_info 
*dst,
+                                           struct grub_video_i386_vbeblit_info 
*src,
                                            int x, int y, int width, int height,
                                            int offset_x, int offset_y);
 
 void
-grub_video_i386_vbeblit_R8G8B8_R8G8B8A8 (struct grub_video_render_target *dst,
-                                         struct grub_video_render_target *src,
+grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8 (struct grub_video_i386_vbeblit_info 
*dst,
+                                           struct grub_video_i386_vbeblit_info 
*src,
+                                           int x, int y, int width, int height,
+                                           int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_R8G8B8_R8G8B8A8 (struct grub_video_i386_vbeblit_info 
*dst,
+                                         struct grub_video_i386_vbeblit_info 
*src,
                                          int x, int y, int width, int height,
                                          int offset_x, int offset_y);
 
 void
-grub_video_i386_vbeblit_index_R8G8B8A8 (struct grub_video_render_target *dst,
-                                        struct grub_video_render_target *src,
+grub_video_i386_vbeblit_R8G8B8_R8G8B8X8 (struct grub_video_i386_vbeblit_info 
*dst,
+                                         struct grub_video_i386_vbeblit_info 
*src,
+                                         int x, int y, int width, int height,
+                                         int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_index_R8G8B8A8 (struct grub_video_i386_vbeblit_info 
*dst,
+                                        struct grub_video_i386_vbeblit_info 
*src,
                                         int x, int y, int width, int height,
                                         int offset_x, int offset_y);
 
+void
+grub_video_i386_vbeblit_index_R8G8B8X8 (struct grub_video_i386_vbeblit_info 
*dst,
+                                        struct grub_video_i386_vbeblit_info 
*src,
+                                        int x, int y, int width, int height,
+                                        int offset_x, int offset_y);
 
 void
-grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (struct grub_video_render_target *dst,
-                                         struct grub_video_render_target *src,
+grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (struct grub_video_i386_vbeblit_info 
*dst,
+                                         struct grub_video_i386_vbeblit_info 
*src,
                                          int x, int y, int width, int height,
                                          int offset_x, int offset_y);
 
 void
-grub_video_i386_vbeblit_R8G8B8_R8G8B8 (struct grub_video_render_target *dst,
-                                       struct grub_video_render_target *src,
+grub_video_i386_vbeblit_R8G8B8_R8G8B8 (struct grub_video_i386_vbeblit_info 
*dst,
+                                       struct grub_video_i386_vbeblit_info 
*src,
                                        int x, int y, int width, int height,
                                        int offset_x, int offset_y);
 
 void
-grub_video_i386_vbeblit_index_R8G8B8 (struct grub_video_render_target *dst,
-                                      struct grub_video_render_target *src,
+grub_video_i386_vbeblit_index_R8G8B8 (struct grub_video_i386_vbeblit_info *dst,
+                                      struct grub_video_i386_vbeblit_info *src,
                                       int x, int y, int width, int height,
                                       int offset_x, int offset_y);
 
 void
-grub_video_i386_vbeblit_index_index (struct grub_video_render_target *dst,
-                                     struct grub_video_render_target *src,
+grub_video_i386_vbeblit_index_index (struct grub_video_i386_vbeblit_info *dst,
+                                     struct grub_video_i386_vbeblit_info *src,
                                      int x, int y, int width, int height,
                                      int offset_x, int offset_y);
 
+void
+grub_video_i386_vbeblit_blend (struct grub_video_i386_vbeblit_info *dst,
+                               struct grub_video_i386_vbeblit_info *src,
+                               int x, int y, int width, int height,
+                               int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_replace (struct grub_video_i386_vbeblit_info *dst,
+                                 struct grub_video_i386_vbeblit_info *src,
+                                 int x, int y, int width, int height,
+                                 int offset_x, int offset_y);
+
 #endif /* ! GRUB_VBEBLIT_MACHINE_HEADER */
Index: include/grub/i386/pc/vbefill.h
===================================================================
RCS file: /sources/grub/grub2/include/grub/i386/pc/vbefill.h,v
retrieving revision 1.1
diff -u -r1.1 vbefill.h
--- include/grub/i386/pc/vbefill.h      31 Mar 2006 14:26:34 -0000      1.1
+++ include/grub/i386/pc/vbefill.h      29 Jul 2006 12:16:52 -0000
@@ -20,21 +20,29 @@
 #ifndef GRUB_VBEFILL_MACHINE_HEADER
 #define GRUB_VBEFILL_MACHINE_HEADER    1
 
-#include <grub/video.h>
+/* NOTE: This header is private header for vbe driver and should not be used
+   in other parts of the code.  */
+
+struct grub_video_i386_vbeblit_info;
 
 void
-grub_video_i386_vbefill_R8G8B8A8 (struct grub_video_render_target *dst,
+grub_video_i386_vbefill_R8G8B8A8 (struct grub_video_i386_vbeblit_info *dst,
                                   grub_video_color_t color,  int x, int y,
                                   int width, int height);
 
 void
-grub_video_i386_vbefill_R8G8B8 (struct grub_video_render_target *dst,
+grub_video_i386_vbefill_R8G8B8 (struct grub_video_i386_vbeblit_info *dst,
                                 grub_video_color_t color, int x, int y,
                                 int width, int height);
 
 void
-grub_video_i386_vbefill_index (struct grub_video_render_target *dst,
+grub_video_i386_vbefill_index (struct grub_video_i386_vbeblit_info *dst,
                                grub_video_color_t color, int x, int y,
                                int width, int height);
 
+void
+grub_video_i386_vbefill (struct grub_video_i386_vbeblit_info *dst,
+                         grub_video_color_t color, int x, int y,
+                         int width, int height);
+
 #endif /* ! GRUB_VBEFILL_MACHINE_HEADER */
Index: include/grub/i386/pc/vbeutil.h
===================================================================
RCS file: include/grub/i386/pc/vbeutil.h
diff -N include/grub/i386/pc/vbeutil.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ include/grub/i386/pc/vbeutil.h      29 Jul 2006 12:16:52 -0000
@@ -0,0 +1,44 @@
+/*
+ *  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.
+ */
+
+/* NOTE: This header is private header for vbe driver and should not be used
+   in other parts of the code.  */
+
+#ifndef GRUB_VBEUTIL_MACHINE_HEADER
+#define GRUB_VBEUTIL_MACHINE_HEADER    1
+
+#include <grub/types.h>
+#include <grub/video.h>
+
+struct grub_video_i386_vbeblit_info
+{
+  struct grub_video_mode_info *mode_info;
+  void *data;
+};
+
+grub_uint8_t *get_data_ptr (struct grub_video_i386_vbeblit_info *source,
+                            unsigned int x, unsigned int y);
+
+grub_video_color_t get_pixel (struct grub_video_i386_vbeblit_info *source,
+                              unsigned int x, unsigned int y);
+
+void set_pixel (struct grub_video_i386_vbeblit_info *source,
+                unsigned int x, unsigned int y, grub_video_color_t color);
+
+#endif /* ! GRUB_VBEUTIL_MACHINE_HEADER */
Index: term/gfxterm.c
===================================================================
RCS file: /sources/grub/grub2/term/gfxterm.c,v
retrieving revision 1.2
diff -u -r1.2 gfxterm.c
--- term/gfxterm.c      20 Apr 2006 15:19:01 -0000      1.2
+++ term/gfxterm.c      29 Jul 2006 12:16:52 -0000
@@ -89,7 +89,7 @@
   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;
@@ -127,7 +127,7 @@
 
   /* 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;
@@ -158,8 +158,8 @@
   /* 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));
+                                              * virtual_screen.rows
+                                              * sizeof 
(*virtual_screen.text_buffer));
   if (grub_errno != GRUB_ERR_NONE)
     return grub_errno;
 
@@ -171,19 +171,19 @@
                                    | GRUB_VIDEO_MODE_TYPE_ALPHA);
   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.  */    
+     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;
 }
 
@@ -196,7 +196,7 @@
   int depth = -1;
   int flags = DEFAULT_VIDEO_FLAGS;
   grub_video_color_t color;
-  
+
   /* Parse gfxmode environment variable if set.  */
   modevar = grub_env_get ("gfxmode");
   if (modevar)
@@ -204,18 +204,18 @@
       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;        
-      
+        return grub_errno;
+
       /* Skip whitespace.  */
       while (grub_isspace (*tmp))
         tmp++;
-      
+
       /* Initialize token holders.  */
       param = tmp;
       value = NULL;
@@ -233,10 +233,10 @@
                              "Invalid argument: %s\n",
                              param);
         }
-      
+
       *param = 0;
       param++;
-      
+
       width = grub_strtoul (value, 0, 0);
       if (grub_errno != GRUB_ERR_NONE)
         {
@@ -267,7 +267,7 @@
           /* We have optional color depth value.  */
           *param = 0;
           param++;
-          
+
           height = grub_strtoul (value, 0, 0);
           if (grub_errno != GRUB_ERR_NONE)
             {
@@ -277,7 +277,7 @@
                                  "Invalid argument: %s\n",
                                  param);
             }
-          
+
           /* Convert color depth value.  */
           value = param;
           depth = grub_strtoul (value, 0, 0);
@@ -290,7 +290,7 @@
                                  param);
             }
         }
-      
+
       /* Free memory.  */
       grub_free (modevar);
     }
@@ -323,7 +323,7 @@
   /* Leave borders for virtual screen.  */
   width = mode_info.width - (2 * DEFAULT_BORDER_WIDTH);
   height = mode_info.height - (2 * DEFAULT_BORDER_WIDTH);
-  
+
   /* Create virtual screen.  */
   if (grub_virtual_screen_setup (DEFAULT_BORDER_WIDTH, DEFAULT_BORDER_WIDTH,
                                  width, height) != GRUB_ERR_NONE)
@@ -333,7 +333,7 @@
     }
 
   /* Mark whole screen as dirty.  */
-  dirty_region_reset ();  
+  dirty_region_reset ();
   dirty_region_add (0, 0, mode_info.width, mode_info.height);
 
   return (grub_errno = GRUB_ERR_NONE);
@@ -354,15 +354,15 @@
                     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,
+  grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, x, y,
                                  x - virtual_screen.offset_x,
                                  y - virtual_screen.offset_y,
                                  width, height);
@@ -393,7 +393,7 @@
 {
   if ((width == 0) || (height == 0))
     return;
-    
+
   if (dirty_region_is_empty ())
     {
       dirty_region.top_left_x = x;
@@ -430,18 +430,18 @@
   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 ();
 }
 
@@ -451,7 +451,7 @@
   struct grub_colored_char *p;
   struct grub_font_glyph glyph;
   grub_video_color_t color;
-  grub_video_color_t bgcolor;    
+  grub_video_color_t bgcolor;
   unsigned int x;
   unsigned int y;
 
@@ -474,7 +474,7 @@
   /* 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_blit_glyph (&glyph, color, x, y);
   grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
 
   /* Mark character to be drawn.  */
@@ -517,7 +517,7 @@
 
   /* Scroll text buffer with one line to up.  */
   grub_memmove (virtual_screen.text_buffer,
-               virtual_screen.text_buffer + virtual_screen.columns,
+                virtual_screen.text_buffer + virtual_screen.columns,
                 sizeof (*virtual_screen.text_buffer)
                 * virtual_screen.columns
                 * (virtual_screen.rows - 1));
@@ -533,13 +533,13 @@
       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 ();
 }
@@ -555,47 +555,47 @@
     {
       /* Erase current cursor, if any.  */
       if (virtual_screen.cursor_state)
-       write_char ();
+        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;
-       }
+        {
+        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 ();
+        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');
+        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);
+           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;
@@ -604,35 +604,35 @@
 
       /* If we have large glyph, add fixup info.  */
       if (glyph.char_width > 1)
-       {
-         unsigned i;
+        {
+          unsigned i;
+
+          for (i = 1; i < glyph.char_width; i++)
+            {
+              p[i].code = ' ';
+              p[i].width = glyph.char_width - 1;
+              p[i].index = 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++;
-       }
+        {
+          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 ();
+        write_cursor ();
     }
 }
 
@@ -640,7 +640,7 @@
 grub_gfxterm_getcharwidth (grub_uint32_t c)
 {
   struct grub_font_glyph glyph;
-  
+
   grub_font_get_glyph (c, &glyph);
 
   return glyph.char_width;
@@ -663,7 +663,7 @@
 {
   if (x >= virtual_screen.columns)
     x = virtual_screen.columns - 1;
-  
+
   if (y >= virtual_screen.rows)
     y = virtual_screen.rows - 1;
 
@@ -701,13 +701,13 @@
 
   /* 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 ();
 }
@@ -745,9 +745,9 @@
   if (virtual_screen.cursor_state != on)
     {
       if (virtual_screen.cursor_state)
-       write_char ();
+        write_char ();
       else
-       write_cursor ();
+        write_cursor ();
 
       virtual_screen.cursor_state = on;
     }
@@ -776,7 +776,7 @@
     .setcolorstate = grub_virtual_screen_setcolorstate,
     .setcolor = grub_virtual_screen_setcolor,
     .setcursor = grub_gfxterm_setcursor,
-    .refresh = grub_gfxterm_refresh,    
+    .refresh = grub_gfxterm_refresh,
     .flags = 0,
     .next = 0
   };
Index: video/bitmap.c
===================================================================
RCS file: video/bitmap.c
diff -N video/bitmap.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ video/bitmap.c      29 Jul 2006 12:16:52 -0000
@@ -0,0 +1,257 @@
+/*
+ *  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/bitmap.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+
+/* List of bitmap readers registered to system.  */
+static grub_video_bitmap_reader_t bitmap_readers_list;
+
+/* Register bitmap reader.  */
+void
+grub_video_bitmap_reader_register (grub_video_bitmap_reader_t reader)
+{
+  reader->next = bitmap_readers_list;
+  bitmap_readers_list = reader;
+}
+
+/* Unregister bitmap reader.  */
+void
+grub_video_bitmap_reader_unregister (grub_video_bitmap_reader_t reader)
+{
+  grub_video_bitmap_reader_t *p, q;
+
+  for (p = &bitmap_readers_list, q = *p; q; p = &(q->next), q = q->next)
+    if (q == reader)
+      {
+        *p = q->next;
+        break;
+      }
+}
+
+/* Creates new bitmap, saves created bitmap on success to *bitmap.  */
+grub_err_t
+grub_video_bitmap_create (struct grub_video_bitmap **bitmap, 
+                          unsigned int width, unsigned int height,
+                          enum grub_video_blit_format blit_format)
+{
+  struct grub_video_mode_info *mode_info;
+  unsigned int size;
+
+  if (!bitmap)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument.");
+
+  *bitmap = 0;
+
+  if (width == 0 || height == 0)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument.");
+
+  *bitmap = (struct grub_video_bitmap *)grub_malloc (sizeof (struct 
grub_video_bitmap));
+  if (! *bitmap)
+    return grub_errno;
+
+  mode_info = &((*bitmap)->mode_info);
+
+  /* Populate mode_info.  */
+  mode_info->width = width;
+  mode_info->height = height;
+  mode_info->blit_format = blit_format;
+
+  switch (blit_format)
+    {
+      case GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8:
+        mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_RGB 
+                               | GRUB_VIDEO_MODE_TYPE_ALPHA;
+        mode_info->bpp = 32;
+        mode_info->bytes_per_pixel = 4;
+        mode_info->number_of_colors = 256;
+        mode_info->red_mask_size = 8;
+        mode_info->red_field_pos = 0;
+        mode_info->green_mask_size = 8;
+        mode_info->green_field_pos = 8;
+        mode_info->blue_mask_size = 8;
+        mode_info->blue_field_pos = 16;
+        mode_info->reserved_mask_size = 8;
+        mode_info->reserved_field_pos = 24;
+        break;
+
+      case GRUB_VIDEO_BLIT_FORMAT_R8G8B8:
+        mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
+        mode_info->bpp = 24;
+        mode_info->bytes_per_pixel = 3;
+        mode_info->number_of_colors = 256;
+        mode_info->red_mask_size = 8;
+        mode_info->red_field_pos = 0;
+        mode_info->green_mask_size = 8;
+        mode_info->green_field_pos = 8;
+        mode_info->blue_mask_size = 8;
+        mode_info->blue_field_pos = 16;
+        mode_info->reserved_mask_size = 0;
+        mode_info->reserved_field_pos = 0;
+        break;
+
+      case GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR:
+        mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+        mode_info->bpp = 8;
+        mode_info->bytes_per_pixel = 1;
+        mode_info->number_of_colors = 256;
+        mode_info->red_mask_size = 0;
+        mode_info->red_field_pos = 0;
+        mode_info->green_mask_size = 0;
+        mode_info->green_field_pos = 0;
+        mode_info->blue_mask_size = 0;
+        mode_info->blue_field_pos = 0;
+        mode_info->reserved_mask_size = 0;
+        mode_info->reserved_field_pos = 0;
+        break;
+
+      default:
+        grub_free (*bitmap);
+        *bitmap = 0;
+
+        return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                           "Unsupported bitmap format");
+    }
+
+  mode_info->pitch = width * mode_info->bytes_per_pixel;
+
+  /* Calculate size needed for the data.  */
+  size = (width * mode_info->bytes_per_pixel) * height;
+
+  (*bitmap)->data = grub_malloc (size);  
+  if (! (*bitmap)->data)
+    {
+      grub_free (*bitmap);
+      *bitmap = 0;
+
+      return grub_errno;
+    }
+
+  /* Clear bitmap.  */
+  grub_memset ((*bitmap)->data, 0, size);
+
+  return GRUB_ERR_NONE;
+}
+
+/* Frees all resources allocated by bitmap.  */
+grub_err_t
+grub_video_bitmap_destroy (struct grub_video_bitmap *bitmap)
+{
+  if (! bitmap)
+    return GRUB_ERR_NONE;
+
+  grub_free (bitmap->data);
+  grub_free (bitmap);
+
+  return GRUB_ERR_NONE;
+}
+
+/* Match extension to filename.  */
+static int
+match_extension (const char *filename, const char *ext)
+{
+  int pos;
+  int ext_len;
+
+  pos = grub_strlen (filename);
+  ext_len = grub_strlen (ext);
+
+  if (! pos || ! ext_len || ext_len > pos)
+    return 0;
+
+  pos -= ext_len;
+
+  return grub_strcmp (filename + pos, ext) == 0;
+}
+
+/* Loads bitmap using registered bitmap readers.  */
+grub_err_t
+grub_video_bitmap_load (struct grub_video_bitmap **bitmap, 
+                        const char *filename)
+{
+  grub_video_bitmap_reader_t reader = bitmap_readers_list;
+
+  if (!bitmap)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument.");
+
+  *bitmap = 0;
+
+  while (reader)
+    {
+      if (match_extension (filename, reader->extension))
+        return reader->reader (bitmap, filename);
+
+      reader = reader->next;
+    }
+
+  return grub_error(GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format");
+}
+
+/* Return bitmap width.  */
+unsigned int
+grub_video_bitmap_get_width (struct grub_video_bitmap *bitmap)
+{
+  if (!bitmap)
+    return 0;
+
+  return bitmap->mode_info.width;
+}
+
+/* Return bitmap height.  */
+unsigned int
+grub_video_bitmap_get_height (struct grub_video_bitmap *bitmap)
+{
+  if (!bitmap)
+    return 0;
+
+  return bitmap->mode_info.height;
+}
+
+/* Return mode info for bitmap.  */
+void grub_video_bitmap_get_mode_info (struct grub_video_bitmap *bitmap,
+                                      struct grub_video_mode_info *mode_info)
+{
+  if (!bitmap)
+    return;
+
+  *mode_info = bitmap->mode_info;
+}
+
+/* Return pointer to bitmap's raw data.  */
+void *grub_video_bitmap_get_data (struct grub_video_bitmap *bitmap)
+{
+  if (!bitmap)
+    return 0;
+
+  return bitmap->data;
+}
+
+/* Initialize bitmap module.  */
+GRUB_MOD_INIT(video_bitmap)
+{
+}
+
+/* Finalize bitmap module.  */
+GRUB_MOD_FINI(video_bitmap)
+{
+}
Index: video/video.c
===================================================================
RCS file: /sources/grub/grub2/video/video.c,v
retrieving revision 1.3
diff -u -r1.3 video.c
--- video/video.c       29 Jul 2006 11:22:52 -0000      1.3
+++ video/video.c       29 Jul 2006 12:16:52 -0000
@@ -82,7 +82,7 @@
   /* 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.  */
+      /* Try to initialize adapter, if it fails, skip to next adapter.  */
       p->init ();
       if (grub_errno != GRUB_ERR_NONE)
         {
@@ -142,7 +142,7 @@
 enum grub_video_blit_format
 grub_video_get_blit_format (struct grub_video_mode_info *mode_info)
 {
-  /* Check if we have any knwon 32 bit modes.  */
+  /* Check if we have any known 32 bit modes.  */
   if (mode_info->bpp == 32)
     {
       if ((mode_info->red_mask_size == 8)
@@ -286,13 +286,14 @@
 /* Blit bitmap to screen.  */
 grub_err_t
 grub_video_blit_bitmap (struct grub_video_bitmap *bitmap,
+                        enum grub_video_blit_operators oper,
                         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,
+  return grub_video_adapter_active->blit_bitmap (bitmap, oper, x, y,
                                                  offset_x, offset_y,
                                                  width, height);
 }
@@ -300,14 +301,15 @@
 /* Blit render target to active render target.  */
 grub_err_t
 grub_video_blit_render_target (struct grub_video_render_target *target,
+                               enum grub_video_blit_operators oper,
                                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, 
+  return grub_video_adapter_active->blit_render_target (target, oper, x, y,
+                                                        offset_x, offset_y,
                                                         width, height);
 }
 
Index: video/i386/pc/vbe.c
===================================================================
RCS file: /sources/grub/grub2/video/i386/pc/vbe.c,v
retrieving revision 1.8
diff -u -r1.8 vbe.c
--- video/i386/pc/vbe.c 29 Jul 2006 11:22:52 -0000      1.8
+++ video/i386/pc/vbe.c 29 Jul 2006 12:16:52 -0000
@@ -22,12 +22,14 @@
 #include <grub/machine/vbe.h>
 #include <grub/machine/vbeblit.h>
 #include <grub/machine/vbefill.h>
+#include <grub/machine/vbeutil.h>
 #include <grub/types.h>
 #include <grub/dl.h>
 #include <grub/misc.h>
 #include <grub/font.h>
 #include <grub/mm.h>
 #include <grub/video.h>
+#include <grub/bitmap.h>
 
 /* Specify "standard" VGA palette, some video cards may
    need this and this will also be used when using RGB modes.  */
@@ -75,10 +77,6 @@
 static grub_uint32_t mode_in_use = 0x55aa;
 static grub_uint16_t *mode_list;
 
-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 *
 real2pm (grub_vbe_farptr_t ptr)
 {
@@ -176,7 +174,7 @@
         default:
           return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
                              "unsupported pixel format 0x%x",
-                            active_mode_info.memory_model);
+                             active_mode_info.memory_model);
         }
     }
 
@@ -220,7 +218,7 @@
     default:
       grub_vbe_bios_set_mode (old_mode, 0);
       return grub_error (GRUB_ERR_BAD_DEVICE, 
-                         "cannot set VBE mode %x", 
+                         "cannot set VBE mode %x",
                          mode);
       break;
     }
@@ -238,7 +236,7 @@
                                                0, 
                                                palette);
 
-      /* Just ignore the status. */
+      /* Just ignore the status.  */
     }
 
   /* Copy mode info for caller.  */
@@ -299,35 +297,35 @@
 }
 
 grub_uint8_t *
-grub_video_vbe_get_video_ptr (struct grub_video_render_target *source,
+grub_video_vbe_get_video_ptr (struct grub_video_i386_vbeblit_info *source,
                               grub_uint32_t x, grub_uint32_t y)
 {
   grub_uint8_t *ptr = 0;
 
-  switch (source->mode_info.bpp)
+  switch (source->mode_info->bpp)
     {
     case 32:
       ptr = (grub_uint8_t *)source->data
-            + y * source->mode_info.pitch
+            + y * source->mode_info->pitch
             + x * 4;
       break;
 
     case 24:
       ptr = (grub_uint8_t *)source->data
-            + y * source->mode_info.pitch
+            + y * source->mode_info->pitch
             + x * 3;
       break;
 
     case 16:
     case 15:
       ptr = (grub_uint8_t *)source->data
-            + y * source->mode_info.pitch
+            + y * source->mode_info->pitch
             + x * 2;
       break;
 
     case 8:
       ptr = (grub_uint8_t *)source->data
-            + y * source->mode_info.pitch
+            + y * source->mode_info->pitch
             + x;
       break;
     }
@@ -335,112 +333,6 @@
   return ptr;
 }
 
-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 (render_target->mode_info.bpp)
-    {
-    case 32:
-      {
-        grub_uint32_t *ptr;
-
-        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 *ptr2 = (grub_uint8_t *) &color;
-
-        ptr = grub_video_vbe_get_video_ptr (render_target, x, y);
-
-        ptr[0] = ptr2[0];
-        ptr[1] = ptr2[1];
-        ptr[2] = ptr2[2];
-      }
-      break;
-
-    case 16:
-    case 15:
-      {
-        grub_uint16_t *ptr;
-
-        ptr = (grub_uint16_t *)grub_video_vbe_get_video_ptr (render_target,
-                                                             x, y);
-
-        *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;
-
-    default:
-      break;
-    }
-}
-
-static grub_video_color_t
-grub_video_vbe_get_pixel (struct grub_video_render_target *source,
-                          grub_uint32_t x, grub_uint32_t y)
-{
-  grub_video_color_t color = 0;
-
-  if (x >= source->mode_info.width)
-    return 0;
-
-  if (y >= source->mode_info.height)
-    return 0;
-
-  switch (source->mode_info.bpp)
-    {
-    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;
-
-    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)
 {
@@ -482,7 +374,7 @@
     }
 
   /* Reset frame buffer and render target variables.  */
-  grub_memset (&framebuffer, 0, sizeof(framebuffer));  
+  grub_memset (&framebuffer, 0, sizeof(framebuffer));
   render_target = &framebuffer.render_target;
 
   return GRUB_ERR_NONE;
@@ -738,7 +630,7 @@
   render_target->viewport.y = y;
   render_target->viewport.width = width;
   render_target->viewport.height = height;
-  
+
   return GRUB_ERR_NONE;
 }
 
@@ -836,7 +728,7 @@
 
 }
 
-static grub_video_color_t
+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)
 {
@@ -864,12 +756,15 @@
 }
 
 void
-grub_video_vbe_unmap_color (struct grub_video_render_target * source,
+grub_video_vbe_unmap_color (struct grub_video_i386_vbeblit_info * 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 
+  struct grub_video_mode_info *mode_info;
+  mode_info = source->mode_info;
+
+  if ((mode_info->mode_type 
        & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
     {
       /* If we have out of bounds color, return trasnparent black.  */
@@ -893,33 +788,33 @@
       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;
+      tmp = color >> mode_info->red_field_pos;
+      tmp &= (1 << mode_info->red_mask_size) - 1;
+      tmp <<= 8 - mode_info->red_mask_size;
+      tmp |= (1 << (8 - 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;
+      tmp = color >> mode_info->green_field_pos;
+      tmp &= (1 << mode_info->green_mask_size) - 1;
+      tmp <<= 8 - mode_info->green_mask_size;
+      tmp |= (1 << (8 - 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;
+      tmp = color >> mode_info->blue_field_pos;
+      tmp &= (1 << mode_info->blue_mask_size) - 1;
+      tmp <<= 8 - mode_info->blue_mask_size;
+      tmp |= (1 << (8 - mode_info->blue_mask_size)) - 1;
       *blue = tmp & 0xFF;
 
       /* Get alpha component.  */
-      if (source->mode_info.reserved_mask_size > 0)
+      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;
+          tmp = color >> mode_info->reserved_field_pos;
+          tmp &= (1 << mode_info->reserved_mask_size) - 1;
+          tmp <<= 8 - mode_info->reserved_mask_size;
+          tmp |= (1 << (8 - mode_info->reserved_mask_size)) - 1;
         }
       else
         /* If there is no alpha component, assume it opaque.  */
@@ -933,7 +828,7 @@
 grub_video_vbe_fill_rect (grub_video_color_t color, int x, int y,
                           unsigned int width, unsigned int height)
 {
-  unsigned int i, j;
+  struct grub_video_i386_vbeblit_info target;
 
   /* Make sure there is something to do.  */
   if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0))
@@ -962,40 +857,44 @@
   x += render_target->viewport.x;
   y += render_target->viewport.y;
 
+  /* Use vbeblit_info to encapsulate rendering.  */
+  target.mode_info = &render_target->mode_info;
+  target.data = render_target->data;
+
   /* Try to figure out more optimized version.  */
-  if (render_target->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8)
+  if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8)
     {
-      grub_video_i386_vbefill_R8G8B8A8 (render_target, color, x, y, 
+      grub_video_i386_vbefill_R8G8B8A8 (&target, color, x, y, 
                                         width, height);
       return GRUB_ERR_NONE;
     }
 
-  if (render_target->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8)
+  if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8)
     {
-      grub_video_i386_vbefill_R8G8B8 (render_target, color, x, y,
+      grub_video_i386_vbefill_R8G8B8 (&target, color, x, y,
                                       width, height);
       return GRUB_ERR_NONE;
     }
 
-  if (render_target->mode_info.blit_format == 
GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+  if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
     {
-      grub_video_i386_vbefill_index (render_target, color, x, y,
+      grub_video_i386_vbefill_index (&target, color, x, y,
                                      width, height);
       return GRUB_ERR_NONE;
     }
 
-  /* Use backup method to fill area.  */
-  for (j = 0; j < height; j++)
-    for (i = 0; i < width; i++)
-      grub_video_vbe_draw_pixel (x+i, y+j, color);
+  /* No optimized version found, use default (slow) filler.  */
+  grub_video_i386_vbefill (&target, color, x, y, width, height);
 
   return GRUB_ERR_NONE;
 }
 
+// TODO: Remove this method and replace with bitmap based glyphs
 static grub_err_t
 grub_video_vbe_blit_glyph (struct grub_font_glyph * glyph,
                            grub_video_color_t color, int x, int y)
 {
+  struct grub_video_i386_vbeblit_info target;
   unsigned int width;
   unsigned int charwidth;
   unsigned int height;
@@ -1045,29 +944,204 @@
   x += render_target->viewport.x;
   y += render_target->viewport.y;
 
+  /* Use vbeblit_info to encapsulate rendering.  */
+  target.mode_info = &render_target->mode_info;
+  target.data = render_target->data;
+
   /* 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);
+        set_pixel (&target, x+i, y+j, color);
 
   return GRUB_ERR_NONE;
 }
 
+/* NOTE: This function assumes that given coordiantes are within bounds of 
+   handled data.  */
+static void
+common_blitter (struct grub_video_i386_vbeblit_info *target,
+                struct grub_video_i386_vbeblit_info *source,
+                enum grub_video_blit_operators oper, int x, int y,
+                unsigned int width, unsigned int height,
+                int offset_x, int offset_y)
+{
+  if (oper == GRUB_VIDEO_BLIT_REPLACE)
+    {
+      /* Try to figure out more optimized version for replace operator.  */
+      if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8)
+        {
+          if (target->mode_info->blit_format == 
GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8)
+            {
+              grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8 (target, source,
+                                                         x, y, width, height,
+                                                         offset_x, offset_y);
+              return;
+            }
+
+          if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8)
+            {
+              grub_video_i386_vbeblit_R8G8B8_R8G8B8X8 (target, source,
+                                                       x, y, width, height,
+                                                       offset_x, offset_y);
+              return;
+            }
+
+          if (target->mode_info->blit_format == 
GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+            {
+              grub_video_i386_vbeblit_index_R8G8B8X8 (target, source,
+                                                      x, y, width, height,
+                                                      offset_x, offset_y);
+              return;
+            }
+        }
+
+      if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8)
+        {
+          if (target->mode_info->blit_format == 
GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8)
+            {
+              grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (target, source,
+                                                       x, y, width, height,
+                                                       offset_x, offset_y);
+              return;
+            }
+
+          if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8)
+            {
+              grub_video_i386_vbeblit_R8G8B8_R8G8B8 (target, source,
+                                                     x, y, width, height,
+                                                     offset_x, offset_y);
+              return;
+            }
+
+          if (target->mode_info->blit_format == 
GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+            {
+              grub_video_i386_vbeblit_index_R8G8B8 (target, source,
+                                                    x, y, width, height,
+                                                    offset_x, offset_y);
+              return;
+            }
+        }
+
+      if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+        {
+          if (target->mode_info->blit_format == 
GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+            {
+              grub_video_i386_vbeblit_index_index (target, source,
+                                                   x, y, width, height,
+                                                   offset_x, offset_y);
+              return;
+            }
+        }
+
+      /* No optimized replace operator found, use default (slow) blitter.  */
+      grub_video_i386_vbeblit_replace (target, source, x, y, width, height,
+                                       offset_x, offset_y);
+    }
+  else
+    {
+      /* Try to figure out more optimized blend operator.  */
+      if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8)
+      {
+        if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8)
+        {
+          grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8 (target, source,
+              x, y, width, height,
+              offset_x, offset_y);
+          return;
+        }
+
+        if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8)
+        {
+          grub_video_i386_vbeblit_R8G8B8_R8G8B8A8 (target, source,
+              x, y, width, height,
+              offset_x, offset_y);
+          return;
+        }
+
+        if (target->mode_info->blit_format == 
GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+        {
+          grub_video_i386_vbeblit_index_R8G8B8A8 (target, source,
+              x, y, width, height,
+              offset_x, offset_y);
+          return;
+        }
+      }
+
+      if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8)
+      {
+        if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8)
+        {
+          grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (target, source,
+              x, y, width, height,
+              offset_x, offset_y);
+          return;
+        }
+
+        if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8)
+        {
+          grub_video_i386_vbeblit_R8G8B8_R8G8B8 (target, source,
+              x, y, width, height,
+              offset_x, offset_y);
+          return;
+        }
+
+        if (target->mode_info->blit_format == 
GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+        {
+          grub_video_i386_vbeblit_index_R8G8B8 (target, source,
+              x, y, width, height,
+              offset_x, offset_y);
+          return;
+        }
+      }
+
+      if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+      {
+        if (target->mode_info->blit_format == 
GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+        {
+          grub_video_i386_vbeblit_index_index (target, source,
+                                               x, y, width, height,
+                                               offset_x, offset_y);
+          return;
+        }
+      }
+
+      /* No optimized blend operation found, use default (slow) blitter.  */
+      grub_video_i386_vbeblit_blend (target, source, x, y, width, height,
+                                     offset_x, offset_y);
+    }
+}
+
 static grub_err_t
-grub_video_vbe_blit_bitmap (struct grub_video_bitmap * bitmap,
-                            int x, int y, int offset_x, int offset_y,
+grub_video_vbe_blit_bitmap (struct grub_video_bitmap *bitmap,
+                            enum grub_video_blit_operators oper, int x, int y,
+                            int offset_x, int offset_y,
                             unsigned int width, unsigned int height)
 {
+  struct grub_video_i386_vbeblit_info source;
+  struct grub_video_i386_vbeblit_info target;
+
   /* 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)bitmap->mode_info.width) < 0)
+    return GRUB_ERR_NONE;
+  if ((y + (int)bitmap->mode_info.height) < 0)
+    return GRUB_ERR_NONE;
+  if ((offset_x >= (int)bitmap->mode_info.width) 
+      || (offset_x + (int)width < 0))
+    return GRUB_ERR_NONE;
+  if ((offset_y >= (int)bitmap->mode_info.height) 
+      || (offset_y + (int)height < 0))
+    return GRUB_ERR_NONE;
 
-  /* Do not allow drawing out of viewport.  */
+  /* If we have negative coordinates, optimize drawing to minimum.  */
   if (offset_x < 0)
     {
       width += offset_x;
@@ -1085,39 +1159,60 @@
   if (x < 0)
     {
       width += x;
-      offset_x += (unsigned int)-x;
+      offset_x -= x;
       x = 0;
     }
+
   if (y < 0)
     {
       height += y;
-      offset_y += (unsigned int)-y;
+      offset_y -= 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;
 
-  /* TODO: Limit drawing to bitmap dimensions.  */
+  if ((offset_x + width) > bitmap->mode_info.width)
+    width = bitmap->mode_info.width - offset_x;
+  if ((offset_y + height) > bitmap->mode_info.height)
+    height = bitmap->mode_info.height - offset_y;
+
+  /* Limit drawing to source render target dimensions.  */
+  if (width > bitmap->mode_info.width)
+    width = bitmap->mode_info.width;
+
+  if (height > bitmap->mode_info.height)
+    height = bitmap->mode_info.height;
 
   /* Add viewport offset.  */
   x += render_target->viewport.x;
   y += render_target->viewport.y;
 
-  /* TODO: Render bitmap.  */
+  /* Use vbeblit_info to encapsulate rendering.  */
+  source.mode_info = &bitmap->mode_info;
+  source.data = bitmap->data;
+  target.mode_info = &render_target->mode_info;
+  target.data = render_target->data;
+
+  /* Do actual blitting.  */
+  common_blitter (&target, &source, oper, x, y, width, height,
+                  offset_x, offset_y);
 
   return GRUB_ERR_NONE;
 }
 
 static grub_err_t
 grub_video_vbe_blit_render_target (struct grub_video_render_target *source,
+                                   enum grub_video_blit_operators oper,
                                    int x, int y, int offset_x, int offset_y,
                                    unsigned int width, unsigned int height)
 {
-  unsigned int i;
-  unsigned int j;
+  struct grub_video_i386_vbeblit_info source_info;
+  struct grub_video_i386_vbeblit_info target_info;
 
   /* Make sure there is something to do.  */
   if ((width == 0) || (height == 0))
@@ -1125,17 +1220,17 @@
   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;    
+    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;    
+    return GRUB_ERR_NONE;
   if ((offset_x >= (int)source->mode_info.width) 
       || (offset_x + (int)width < 0))
     return GRUB_ERR_NONE;
   if ((offset_y >= (int)source->mode_info.height) 
       || (offset_y + (int)height < 0))
-    return GRUB_ERR_NONE;    
+    return GRUB_ERR_NONE;
 
   /* If we have negative coordinates, optimize drawing to minimum.  */
   if (offset_x < 0)
@@ -1155,14 +1250,14 @@
   if (x < 0)
     {
       width += x;
-      offset_x += (unsigned int)-x;
+      offset_x -= x;
       x = 0;
     }
 
   if (y < 0)
     {
       height += y;
-      offset_y += (unsigned int)-y;
+      offset_y -= y;
       y = 0;
     }
 
@@ -1188,122 +1283,15 @@
   x += render_target->viewport.x;
   y += render_target->viewport.y;
 
-  /* Try to figure out more optimized version.  */
-  if (source->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8)
-    {
-      if (render_target->mode_info.blit_format == 
GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8)
-        {
-          grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8 (render_target, source,
-                                                     x, y, width, height,
-                                                     offset_x, offset_y);
-          return GRUB_ERR_NONE;
-        }
-
-      if (render_target->mode_info.blit_format == 
GRUB_VIDEO_BLIT_FORMAT_R8G8B8)
-        {
-          grub_video_i386_vbeblit_R8G8B8_R8G8B8A8 (render_target, source,
-                                                   x, y, width, height,
-                                                   offset_x, offset_y);
-          return GRUB_ERR_NONE;
-        }
-
-      if (render_target->mode_info.blit_format == 
GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
-        {
-          grub_video_i386_vbeblit_index_R8G8B8A8 (render_target, source,
-                                                  x, y, width, height,
-                                                  offset_x, offset_y);
-          return GRUB_ERR_NONE;
-        }
-    }
-
-  if (source->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8)
-    {
-      if (render_target->mode_info.blit_format == 
GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8)
-        {
-          grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (render_target, source,
-                                                   x, y, width, height,
-                                                   offset_x, offset_y);
-          return GRUB_ERR_NONE;
-        }
-
-      if (render_target->mode_info.blit_format == 
GRUB_VIDEO_BLIT_FORMAT_R8G8B8)
-        {
-          grub_video_i386_vbeblit_R8G8B8_R8G8B8 (render_target, source,
-                                                 x, y, width, height,
-                                                 offset_x, offset_y);
-          return GRUB_ERR_NONE;
-        }
-
-      if (render_target->mode_info.blit_format == 
GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
-        {
-          grub_video_i386_vbeblit_index_R8G8B8 (render_target, source,
-                                                x, y, width, height,
-                                                offset_x, offset_y);
-          return GRUB_ERR_NONE;
-        }
-    }
-
-  if (source->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
-    {
-      if (render_target->mode_info.blit_format == 
GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
-        {
-          grub_video_i386_vbeblit_index_index (render_target, source,
-                                               x, y, width, height,
-                                               offset_x, offset_y);
-          return GRUB_ERR_NONE;
-        }
-    }
-
-  /* Use backup method to 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);
-        }
-    }
+  /* Use vbeblit_info to encapsulate rendering.  */
+  source_info.mode_info = &source->mode_info;
+  source_info.data = source->data;
+  target_info.mode_info = &render_target->mode_info;
+  target_info.data = render_target->data;
+
+  /* Do actual blitting.  */
+  common_blitter (&target_info, &source_info, oper, x, y, width, height, 
+                  offset_x, offset_y);
 
   return GRUB_ERR_NONE;
 }
@@ -1352,16 +1340,20 @@
        && (grub_abs (dy) < render_target->viewport.height))
     {
       /* 3. Move data in render target.  */
+      struct grub_video_i386_vbeblit_info target;
       grub_uint8_t *src;
       grub_uint8_t *dst;
       int j;
 
+      target.mode_info = &render_target->mode_info;
+      target.data = render_target->data;
+
       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);
+          dst = grub_video_vbe_get_video_ptr (&target, dst_x, dst_y + j);
+          src = grub_video_vbe_get_video_ptr (&target, src_x, src_y + j);
           grub_memmove (dst, src,
-                        width * render_target->mode_info.bytes_per_pixel);
+                        width * target.mode_info->bytes_per_pixel);
         }
     }
 
@@ -1544,7 +1536,7 @@
     .delete_render_target = grub_video_vbe_delete_render_target,
     .set_active_render_target = grub_video_vbe_set_active_render_target,
 
-    .next = 0  
+    .next = 0
   };
 
 GRUB_MOD_INIT(video_i386_pc_vbe)
Index: video/i386/pc/vbeblit.c
===================================================================
RCS file: /sources/grub/grub2/video/i386/pc/vbeblit.c,v
retrieving revision 1.2
diff -u -r1.2 vbeblit.c
--- video/i386/pc/vbeblit.c     29 Jul 2006 11:22:52 -0000      1.2
+++ video/i386/pc/vbeblit.c     29 Jul 2006 12:16:52 -0000
@@ -17,20 +17,27 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <grub/err.h>
-#include <grub/machine/memory.h>
+/* SPECIAL NOTES!
+
+   Please note following when reading the code below:
+
+   - In this driver we assume that every memory can be accessed by same memory
+   bus.  If there are different address spaces do not use this code as a base
+   code for other archs.
+
+   - Every function in this code assumes that bounds checking has been done in
+   previous phase and they are opted out in here.  */
+
 #include <grub/machine/vbe.h>
 #include <grub/machine/vbeblit.h>
-#include <grub/types.h>
-#include <grub/dl.h>
+#include <grub/machine/vbeutil.h>
 #include <grub/misc.h>
-#include <grub/font.h>
-#include <grub/mm.h>
+#include <grub/types.h>
 #include <grub/video.h>
 
 void
-grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8 (struct grub_video_render_target 
*dst,
-                                           struct grub_video_render_target 
*src,
+grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8 (struct grub_video_i386_vbeblit_info 
*dst,
+                                           struct grub_video_i386_vbeblit_info 
*src,
                                            int x, int y, int width, int height,
                                            int offset_x, int offset_y)
 {
@@ -52,10 +59,8 @@
 
   for (j = 0; j < height; j++)
     {
-      srcptr = (grub_uint32_t *)grub_video_vbe_get_video_ptr (src, offset_x,
-                                                              j + offset_y);
-
-      dstptr = (grub_uint32_t *)grub_video_vbe_get_video_ptr (dst, x, y + j);
+      srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y);
+      dstptr = (grub_uint32_t *)get_data_ptr (dst, x, y + j);
 
       for (i = 0; i < width; i++)
         {
@@ -97,8 +102,33 @@
 }
 
 void
-grub_video_i386_vbeblit_R8G8B8_R8G8B8A8 (struct grub_video_render_target *dst,
-                                         struct grub_video_render_target *src,
+grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8 (struct grub_video_i386_vbeblit_info 
*dst,
+                                           struct grub_video_i386_vbeblit_info 
*src,
+                                           int x, int y, int width, int height,
+                                           int offset_x, int offset_y)
+{
+  int j;
+  grub_uint32_t *srcptr;
+  grub_uint32_t *dstptr;
+  int pitch;
+
+  pitch = src->mode_info->bytes_per_pixel;
+
+  /* We do not need to worry about data being out of bounds
+     as we assume that everything has been checked before.  */
+
+  for (j = 0; j < height; j++)
+    {
+      srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y);
+      dstptr = (grub_uint32_t *)get_data_ptr (dst, x, y + j);
+
+      grub_memmove (dstptr, srcptr, width * pitch);
+    }
+}
+
+void
+grub_video_i386_vbeblit_R8G8B8_R8G8B8A8 (struct grub_video_i386_vbeblit_info 
*dst,
+                                         struct grub_video_i386_vbeblit_info 
*src,
                                          int x, int y, int width, int height,
                                          int offset_x, int offset_y)
 {
@@ -120,10 +150,8 @@
 
   for (j = 0; j < height; j++)
     {
-      srcptr = (grub_uint32_t *)grub_video_vbe_get_video_ptr (src, offset_x,
-                                                              j + offset_y);
-
-      dstptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (dst, x, y + j);
+      srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y);
+      dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j);
 
       for (i = 0; i < width; i++)
         {
@@ -166,8 +194,46 @@
 }
 
 void
-grub_video_i386_vbeblit_index_R8G8B8A8 (struct grub_video_render_target *dst,
-                                        struct grub_video_render_target *src,
+grub_video_i386_vbeblit_R8G8B8_R8G8B8X8 (struct grub_video_i386_vbeblit_info 
*dst,
+                                         struct grub_video_i386_vbeblit_info 
*src,
+                                         int x, int y, int width, int height,
+                                         int offset_x, int offset_y)
+{
+  grub_uint32_t color;
+  int i;
+  int j;
+  grub_uint32_t *srcptr;
+  grub_uint8_t *dstptr;
+  unsigned int sr;
+  unsigned int sg;
+  unsigned int sb;
+
+  /* We do not need to worry about data being out of bounds
+     as we assume that everything has been checked before.  */
+
+  for (j = 0; j < height; j++)
+  {
+    srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y);
+    dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j);
+
+    for (i = 0; i < width; i++)
+    {
+      color = *srcptr++;
+
+      sr = (color >> 0) & 0xFF;
+      sg = (color >> 8) & 0xFF;
+      sb = (color >> 16) & 0xFF;
+
+      *dstptr++ = sr;
+      *dstptr++ = sg;
+      *dstptr++ = sb;
+    }
+  }
+}
+
+void
+grub_video_i386_vbeblit_index_R8G8B8A8 (struct grub_video_i386_vbeblit_info 
*dst,
+                                        struct grub_video_i386_vbeblit_info 
*src,
                                         int x, int y, int width, int height,
                                         int offset_x, int offset_y)
 {
@@ -190,10 +256,8 @@
 
   for (j = 0; j < height; j++)
     {
-      srcptr = (grub_uint32_t *)grub_video_vbe_get_video_ptr (src, offset_x,
-                                                              j + offset_y);
-
-      dstptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (dst, x, y + j);
+      srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y);
+      dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j);
 
       for (i = 0; i < width; i++)
         {
@@ -232,8 +296,45 @@
 }
 
 void
-grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (struct grub_video_render_target *dst,
-                                         struct grub_video_render_target *src,
+grub_video_i386_vbeblit_index_R8G8B8X8 (struct grub_video_i386_vbeblit_info 
*dst,
+                                        struct grub_video_i386_vbeblit_info 
*src,
+                                        int x, int y, int width, int height,
+                                        int offset_x, int offset_y)
+{
+  grub_uint32_t color;
+  int i;
+  int j;
+  grub_uint32_t *srcptr;
+  grub_uint8_t *dstptr;
+  unsigned int sr;
+  unsigned int sg;
+  unsigned int sb;
+
+  /* We do not need to worry about data being out of bounds
+  as we assume that everything has been checked before.  */
+
+  for (j = 0; j < height; j++)
+  {
+    srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y);
+    dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j);
+
+    for (i = 0; i < width; i++)
+    {
+      color = *srcptr++;
+
+      sr = (color >> 0) & 0xFF;
+      sg = (color >> 8) & 0xFF;
+      sb = (color >> 16) & 0xFF;
+
+      color = grub_video_vbe_map_rgb(sr, sg, sb);
+      *dstptr++ = color & 0xFF;
+    }
+  }
+}
+
+void
+grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (struct grub_video_i386_vbeblit_info 
*dst,
+                                         struct grub_video_i386_vbeblit_info 
*src,
                                          int x, int y, int width, int height,
                                          int offset_x, int offset_y)
 {
@@ -251,10 +352,8 @@
 
   for (j = 0; j < height; j++)
     {
-      srcptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (src, offset_x,
-                                                             j + offset_y);
-
-      dstptr = (grub_uint32_t *)grub_video_vbe_get_video_ptr (dst, x, y + j);
+      srcptr = (grub_uint8_t *)get_data_ptr (src, offset_x, j + offset_y);
+      dstptr = (grub_uint32_t *)get_data_ptr (dst, x, y + j);
 
       for (i = 0; i < width; i++)
         {
@@ -270,41 +369,33 @@
 }
 
 void
-grub_video_i386_vbeblit_R8G8B8_R8G8B8 (struct grub_video_render_target *dst,
-                                       struct grub_video_render_target *src,
+grub_video_i386_vbeblit_R8G8B8_R8G8B8 (struct grub_video_i386_vbeblit_info 
*dst,
+                                       struct grub_video_i386_vbeblit_info 
*src,
                                        int x, int y, int width, int height,
                                        int offset_x, int offset_y)
 {
-  int i;
   int j;
   grub_uint8_t *srcptr;
   grub_uint8_t *dstptr;
+  int pitch;
+
+  pitch = src->mode_info->bytes_per_pixel;
 
   /* We do not need to worry about data being out of bounds
      as we assume that everything has been checked before.  */
 
   for (j = 0; j < height; j++)
     {
-      srcptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (src, 
-                                                             offset_x,
-                                                             j + offset_y);
-
-      dstptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (dst,
-                                                             x, 
-                                                             y + j);
+      srcptr = (grub_uint8_t *)get_data_ptr (src, offset_x, j + offset_y);
+      dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j);
 
-      for (i = 0; i < width; i++)
-        {
-          *dstptr ++ = *srcptr++;
-          *dstptr ++ = *srcptr++;
-          *dstptr ++ = *srcptr++;
-        }
+      grub_memmove (dstptr, srcptr, width * pitch);
     }
 }
 
 void
-grub_video_i386_vbeblit_index_R8G8B8 (struct grub_video_render_target *dst,
-                                      struct grub_video_render_target *src,
+grub_video_i386_vbeblit_index_R8G8B8 (struct grub_video_i386_vbeblit_info *dst,
+                                      struct grub_video_i386_vbeblit_info *src,
                                       int x, int y, int width, int height,
                                       int offset_x, int offset_y)
 {
@@ -322,10 +413,8 @@
 
   for (j = 0; j < height; j++)
     {
-      srcptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (src, offset_x,
-                                                             j + offset_y);
-
-      dstptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (dst, x, y + j);
+      srcptr = (grub_uint8_t *)get_data_ptr (src, offset_x, j + offset_y);
+      dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j);
 
       for (i = 0; i < width; i++)
         {
@@ -341,27 +430,122 @@
 }
 
 void
-grub_video_i386_vbeblit_index_index (struct grub_video_render_target *dst,
-                                     struct grub_video_render_target *src,
+grub_video_i386_vbeblit_index_index (struct grub_video_i386_vbeblit_info *dst,
+                                     struct grub_video_i386_vbeblit_info *src,
                                      int x, int y, int width, int height,
                                      int offset_x, int offset_y)
 {
-  int i;
   int j;
   grub_uint8_t *srcptr;
   grub_uint8_t *dstptr;
+  int pitch;
+
+  pitch = src->mode_info->bytes_per_pixel;
 
   /* We do not need to worry about data being out of bounds
      as we assume that everything has been checked before.  */
 
   for (j = 0; j < height; j++)
     {
-      srcptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (src, offset_x,
-                                                             j + offset_y);
+      srcptr = (grub_uint8_t *)get_data_ptr (src, offset_x, j + offset_y);
+      dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j);
 
-      dstptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (dst, x, y + j);
+      grub_memmove (dstptr, srcptr, width * pitch);
+    }
+}
+
+void
+grub_video_i386_vbeblit_blend (struct grub_video_i386_vbeblit_info *dst,
+                               struct grub_video_i386_vbeblit_info *src,
+                               int x, int y, int width, int height,
+                               int offset_x, int offset_y)
+{
+  int i;
+  int j;
 
+  /* We do not need to worry about data being out of bounds
+     as we assume that everything has been checked before.  */
+
+  for (j = 0; j < height; j++)
+    {
       for (i = 0; i < width; i++)
-          *dstptr++ = *srcptr++;
+        {
+          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 = get_pixel (src, i + offset_x, j + offset_y);
+          grub_video_vbe_unmap_color (src, 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);
+              set_pixel (dst, x + i, y + j, dst_color);
+              continue;
+            }
+
+          dst_color = get_pixel (dst, x + i, y + j);
+
+          grub_video_vbe_unmap_color (dst, 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);
+
+          set_pixel (dst, x + i, y + j, dst_color);
+        }
+    }
+}
+
+void
+grub_video_i386_vbeblit_replace (struct grub_video_i386_vbeblit_info *dst,
+                                 struct grub_video_i386_vbeblit_info *src,
+                                 int x, int y, int width, int height,
+                                 int offset_x, int offset_y)
+{
+  int i;
+  int j;
+  grub_uint8_t src_red;
+  grub_uint8_t src_green;
+  grub_uint8_t src_blue;
+  grub_uint8_t src_alpha;
+  grub_video_color_t src_color;
+  grub_video_color_t dst_color;
+
+  /* We do not need to worry about data being out of bounds
+     as we assume that everything has been checked before.  */
+
+  for (j = 0; j < height; j++)
+  {
+    for (i = 0; i < width; i++)
+    {
+      src_color = get_pixel (src, i + offset_x, j + offset_y);
+      grub_video_vbe_unmap_color (src, src_color, &src_red, &src_green,
+                                  &src_blue, &src_alpha);
+
+      dst_color = grub_video_vbe_map_rgba (src_red, src_green,
+                                           src_blue, src_alpha);
+      set_pixel (dst, x + i, y + j, dst_color);
     }
+  }
 }
Index: video/i386/pc/vbefill.c
===================================================================
RCS file: /sources/grub/grub2/video/i386/pc/vbefill.c,v
retrieving revision 1.2
diff -u -r1.2 vbefill.c
--- video/i386/pc/vbefill.c     29 Jul 2006 11:22:52 -0000      1.2
+++ video/i386/pc/vbefill.c     29 Jul 2006 12:16:52 -0000
@@ -17,19 +17,25 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <grub/err.h>
-#include <grub/machine/memory.h>
+/* SPECIAL NOTES!
+
+   Please note following when reading the code below:
+
+   - In this driver we assume that every memory can be accessed by same memory
+     bus.  If there are different address spaces do not use this code as a base
+     code for other archs.
+
+   - Every function in this code assumes that bounds checking has been done in
+     previous phase and they are opted out in here.  */
+
 #include <grub/machine/vbe.h>
 #include <grub/machine/vbefill.h>
+#include <grub/machine/vbeutil.h>
 #include <grub/types.h>
-#include <grub/dl.h>
-#include <grub/misc.h>
-#include <grub/font.h>
-#include <grub/mm.h>
 #include <grub/video.h>
 
 void
-grub_video_i386_vbefill_R8G8B8A8 (struct grub_video_render_target *dst,
+grub_video_i386_vbefill_R8G8B8A8 (struct grub_video_i386_vbeblit_info *dst,
                                   grub_video_color_t color, int x, int y,
                                   int width, int height)
 {
@@ -50,7 +56,7 @@
 }
 
 void
-grub_video_i386_vbefill_R8G8B8 (struct grub_video_render_target *dst,
+grub_video_i386_vbefill_R8G8B8 (struct grub_video_i386_vbeblit_info *dst,
                                 grub_video_color_t color, int x, int y,
                                 int width, int height)
 {
@@ -78,7 +84,7 @@
 }
 
 void
-grub_video_i386_vbefill_index (struct grub_video_render_target *dst,
+grub_video_i386_vbefill_index (struct grub_video_i386_vbeblit_info *dst,
                                grub_video_color_t color, int x, int y,
                                int width, int height)
 {
@@ -98,3 +104,19 @@
         *dstptr++ = fill;
     }
 }
+
+void
+grub_video_i386_vbefill (struct grub_video_i386_vbeblit_info *dst,
+                         grub_video_color_t color, int x, int y,
+                         int width, int height)
+{
+  int i;
+  int j;
+
+  /* We do not need to worry about data being out of bounds
+     as we assume that everything has been checked before.  */
+
+  for (j = 0; j < height; j++)
+    for (i = 0; i < width; i++)
+      set_pixel (dst, x+i, y+j, color);
+}
Index: video/i386/pc/vbeutil.c
===================================================================
RCS file: video/i386/pc/vbeutil.c
diff -N video/i386/pc/vbeutil.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ video/i386/pc/vbeutil.c     29 Jul 2006 12:16:52 -0000
@@ -0,0 +1,150 @@
+/*
+ *  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/vbeutil.h>
+#include <grub/types.h>
+#include <grub/video.h>
+
+grub_uint8_t *
+get_data_ptr (struct grub_video_i386_vbeblit_info *source,
+              unsigned int x, unsigned int y)
+{
+  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;
+
+    case 24:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info->pitch
+            + x * 3;
+      break;
+
+    case 16:
+    case 15:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info->pitch
+            + x * 2;
+      break;
+
+    case 8:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info->pitch
+            + x;
+      break;
+    }
+
+  return ptr;
+}
+
+grub_video_color_t
+get_pixel (struct grub_video_i386_vbeblit_info *source,
+           unsigned int x, unsigned int y)
+{
+  grub_video_color_t color = 0;
+
+  switch (source->mode_info->bpp)
+    {
+    case 32:
+      color = *(grub_uint32_t *)get_data_ptr (source, x, y);
+      break;
+
+    case 24:
+      {
+        grub_uint8_t *ptr;
+        ptr = get_data_ptr (source, x, y);
+        color = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
+      }
+      break;
+
+    case 16:
+    case 15:
+      color = *(grub_uint16_t *)get_data_ptr (source, x, y);
+      break;
+
+    case 8:
+      color = *(grub_uint8_t *)get_data_ptr (source, x, y);
+      break;
+
+    default:
+      break;
+    }
+
+  return color;
+}
+
+void
+set_pixel (struct grub_video_i386_vbeblit_info *source,
+           unsigned int x, unsigned int y, grub_video_color_t color)
+{
+  switch (source->mode_info->bpp)
+    {
+    case 32:
+      {
+        grub_uint32_t *ptr;
+
+        ptr = (grub_uint32_t *)get_data_ptr (source, x, y);
+
+        *ptr = color;
+      }
+      break;
+
+    case 24:
+      {
+        grub_uint8_t *ptr;
+        grub_uint8_t *colorptr = (grub_uint8_t *)&color;
+
+        ptr = get_data_ptr (source, x, y);
+
+        ptr[0] = colorptr[0];
+        ptr[1] = colorptr[1];
+        ptr[2] = colorptr[2];
+      }
+      break;
+
+    case 16:
+    case 15:
+      {
+        grub_uint16_t *ptr;
+
+        ptr = (grub_uint16_t *)get_data_ptr (source, x, y);
+
+        *ptr = (grub_uint16_t) (color & 0xFFFF);
+      }
+      break;
+
+    case 8:
+      {
+        grub_uint8_t *ptr;
+
+        ptr = (grub_uint8_t *)get_data_ptr (source, x, y);
+
+        *ptr = (grub_uint8_t) (color & 0xFF);
+      }
+      break;
+
+    default:
+      break;
+    }
+}
Index: video/readers/tga.c
===================================================================
RCS file: video/readers/tga.c
diff -N video/readers/tga.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ video/readers/tga.c 29 Jul 2006 12:16:52 -0000
@@ -0,0 +1,496 @@
+/*
+ *  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/bitmap.h>
+#include <grub/types.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/arg.h>
+#include <grub/file.h>
+
+/* Uncomment following define to enable TGA debug.  */
+//#define TGA_DEBUG
+
+#if defined(TGA_DEBUG)
+#define dump_int_field(x) grub_printf( #x " = %d (0x%04x)\n", x, x);
+#endif
+
+enum
+{
+  GRUB_TGA_IMAGE_TYPE_NONE = 0,
+  GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_INDEXCOLOR = 1,
+  GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR = 2,
+  GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_BLACK_AND_WHITE = 3,
+  GRUB_TGA_IMAGE_TYPE_RLE_INDEXCOLOR = 9,
+  GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR = 10,
+  GRUB_TGA_IMAGE_TYPE_RLE_BLACK_AND_WHITE = 11,
+};
+
+enum
+{
+  GRUB_TGA_COLOR_MAP_TYPE_NONE = 0,
+  GRUB_TGA_COLOR_MAP_TYPE_INCLUDED = 1
+};
+
+enum
+{
+  GRUB_TGA_IMAGE_ORIGIN_RIGHT = 0x10,
+  GRUB_TGA_IMAGE_ORIGIN_TOP   = 0x20
+};
+
+struct grub_tga_header
+{
+  grub_uint8_t id_length;
+  grub_uint8_t color_map_type;
+  grub_uint8_t image_type;
+
+  /* Color Map Specification.  */
+  grub_uint16_t color_map_first_index;
+  grub_uint16_t color_map_length;
+  grub_uint8_t color_map_bpp;
+
+  /* Image Specification.  */
+  grub_uint16_t image_x_origin;
+  grub_uint16_t image_y_origin;
+  grub_uint16_t image_width;
+  grub_uint16_t image_height;
+  grub_uint8_t image_bpp;
+  grub_uint8_t image_descriptor;
+} __attribute__ ((packed));
+
+static grub_err_t
+tga_load_truecolor_rle_R8G8B8 (struct grub_video_bitmap *bitmap,
+                               struct grub_tga_header *header,
+                               grub_file_t file)
+{
+  unsigned int x;
+  unsigned int y;
+  grub_uint8_t type;
+  grub_uint8_t *ptr;
+  grub_uint8_t tmp[4]; /* Size should be max_bpp / 8.  */
+  grub_uint8_t bytes_per_pixel;
+
+  bytes_per_pixel = header->image_bpp / 8;
+
+  for (y = 0; y < header->image_height; y++)
+    {
+      ptr = bitmap->data;
+      if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
+        ptr += y * bitmap->mode_info.pitch;
+      else
+        ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
+
+      for (x = 0; x < header->image_width;)
+        {
+          if (grub_file_read (file, (char *)&type, sizeof (type)) != 
sizeof(type))
+            return grub_errno;
+
+          if (type & 0x80)
+            {
+              /* RLE-encoded packet.  */
+              type &= 0x7f;
+              type++;
+
+              if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel)
+                  != bytes_per_pixel)
+                return grub_errno;
+
+              while (type)
+                {
+                  if (x < header->image_width)
+                    {
+                      ptr[0] = tmp[2];
+                      ptr[1] = tmp[1];
+                      ptr[2] = tmp[0];
+                      ptr += 3;
+                    }
+
+                  type--;
+                  x++;
+                }
+            }
+          else
+            {
+              /* RAW-encoded packet.  */
+              type++;
+
+              while (type)
+                {
+                  if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel)
+                      != bytes_per_pixel)
+                    return grub_errno;
+
+                  if (x < header->image_width)
+                    {
+                      ptr[0] = tmp[2];
+                      ptr[1] = tmp[1];
+                      ptr[2] = tmp[0];
+                      ptr += 3;
+                    }
+
+                  type--;
+                  x++;
+                }
+            }
+        }
+    }
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+tga_load_truecolor_rle_R8G8B8A8 (struct grub_video_bitmap *bitmap,
+                                 struct grub_tga_header *header,
+                                 grub_file_t file)
+{
+  unsigned int x;
+  unsigned int y;
+  grub_uint8_t type;
+  grub_uint8_t *ptr;
+  grub_uint8_t tmp[4]; /* Size should be max_bpp / 8.  */
+  grub_uint8_t bytes_per_pixel;
+
+  bytes_per_pixel = header->image_bpp / 8;
+
+  for (y = 0; y < header->image_height; y++)
+    {
+      ptr = bitmap->data;
+      if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
+        ptr += y * bitmap->mode_info.pitch;
+      else
+        ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
+
+      for (x = 0; x < header->image_width;)
+        {
+          if (grub_file_read (file, (char *)&type, sizeof (type)) != 
sizeof(type))
+            return grub_errno;
+
+          if (type & 0x80)
+            {
+              /* RLE-encoded packet.  */
+              type &= 0x7f;
+              type++;
+
+              if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel)
+                  != bytes_per_pixel)
+                return grub_errno;
+
+              while (type)
+                {
+                  if (x < header->image_width)
+                    {
+                      ptr[0] = tmp[2];
+                      ptr[1] = tmp[1];
+                      ptr[2] = tmp[0];
+                      ptr[3] = tmp[3];
+                      ptr += 4;
+                    }
+
+                  type--;
+                  x++;
+                }
+            }
+          else
+            {
+              /* RAW-encoded packet.  */
+              type++;
+
+              while (type)
+                {
+                  if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel)
+                      != bytes_per_pixel)
+                    return grub_errno;
+
+                  if (x < header->image_width)
+                    {
+                      ptr[0] = tmp[2];
+                      ptr[1] = tmp[1];
+                      ptr[2] = tmp[0];
+                      ptr[3] = tmp[3];
+                      ptr += 4;
+                    }
+
+                  type--;
+                  x++;
+                }
+            }
+        }
+    }
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+tga_load_truecolor_R8G8B8 (struct grub_video_bitmap *bitmap,
+                           struct grub_tga_header *header,
+                           grub_file_t file)
+{
+  unsigned int x;
+  unsigned int y;
+  grub_uint8_t *ptr;
+  grub_uint8_t tmp[4]; /* Size should be max_bpp / 8.  */
+  grub_uint8_t bytes_per_pixel;
+
+  bytes_per_pixel = header->image_bpp / 8;
+
+  for (y = 0; y < header->image_height; y++)
+    {
+      ptr = bitmap->data;
+      if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
+        ptr += y * bitmap->mode_info.pitch;
+      else
+        ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
+
+      for (x = 0; x < header->image_width; x++)
+        {
+          if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel)
+              != bytes_per_pixel)
+            return grub_errno;
+
+          ptr[0] = tmp[2];
+          ptr[1] = tmp[1];
+          ptr[2] = tmp[0];
+
+          ptr += 3;
+        }
+    }
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+tga_load_truecolor_R8G8B8A8 (struct grub_video_bitmap *bitmap,
+                             struct grub_tga_header *header,
+                             grub_file_t file)
+{
+  unsigned int x;
+  unsigned int y;
+  grub_uint8_t *ptr;
+  grub_uint8_t tmp[4]; /* Size should be max_bpp / 8.  */
+  grub_uint8_t bytes_per_pixel;
+
+  bytes_per_pixel = header->image_bpp / 8;
+
+  for (y = 0; y < header->image_height; y++)
+    {
+      ptr = bitmap->data;
+      if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
+        ptr += y * bitmap->mode_info.pitch;
+      else
+        ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
+
+      for (x = 0; x < header->image_width; x++)
+        {
+          if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel)
+              != bytes_per_pixel)
+            return grub_errno;
+
+          ptr[0] = tmp[2];
+          ptr[1] = tmp[1];
+          ptr[2] = tmp[0];
+          ptr[3] = tmp[3];
+
+          ptr += 4;
+        }
+    }
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_reader_tga (struct grub_video_bitmap **bitmap,
+                       const char *filename)
+{
+  grub_file_t file;
+  grub_ssize_t pos;
+  struct grub_tga_header header;
+  int has_alpha;
+
+  file = grub_file_open (filename);
+  if (! file)
+    return grub_errno;
+
+  /* TGA Specification states that we SHOULD start by reading
+     ID from end of file, but we really don't care about that as we are
+     not going to support developer area & extensions at this point.  */
+
+  /* Read TGA header from begining of file.  */
+  if (grub_file_read (file, (char*)&header, sizeof (header)) 
+      != sizeof (header))
+    {
+      grub_file_close (file);
+      return grub_errno;
+    }
+
+  /* Skip ID field.  */
+  pos = grub_file_tell (file);
+  pos += header.id_length;
+  grub_file_seek (file, pos);
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_file_close (file);
+      return grub_errno;
+    }
+
+#if defined(TGA_DEBUG)
+  grub_printf("tga: header\n");
+  dump_int_field(header.id_length);
+  dump_int_field(header.color_map_type);
+  dump_int_field(header.image_type);
+  dump_int_field(header.color_map_first_index);
+  dump_int_field(header.color_map_length);
+  dump_int_field(header.color_map_bpp);
+  dump_int_field(header.image_x_origin);
+  dump_int_field(header.image_y_origin);
+  dump_int_field(header.image_width);
+  dump_int_field(header.image_height);
+  dump_int_field(header.image_bpp);
+  dump_int_field(header.image_descriptor);
+#endif
+
+  /* Check that bitmap encoding is supported.  */
+  switch (header.image_type)
+    {
+      case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR:
+      case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR:
+        break;
+
+      default:
+        grub_file_close (file);
+        return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                           "Unsupported bitmap format (unknown encoding).");
+    }
+
+  /* Check that bitmap depth is supported.  */
+  switch (header.image_bpp)
+    {
+      case 24:
+        has_alpha = 0;
+        break;
+
+      case 32:
+        has_alpha = 1;
+        break;
+
+      default:
+        grub_file_close (file);
+        return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                           "Unsupported bitmap format (bpp=%d).",
+                           header.image_bpp);
+    }
+
+  /* Allocate bitmap.  If there is alpha information store it too.  */
+  if (has_alpha)
+    {
+      grub_video_bitmap_create (bitmap, header.image_width,
+                                header.image_height,
+                                GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8);
+      if (grub_errno != GRUB_ERR_NONE)
+        {
+          grub_file_close (file);
+          return grub_errno;
+        }
+
+      /* Load bitmap data.  */
+      switch (header.image_type)
+        {
+          case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR:
+            tga_load_truecolor_R8G8B8A8 (*bitmap, &header, file);
+            break;
+
+          case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR:
+            tga_load_truecolor_rle_R8G8B8A8 (*bitmap, &header, file);
+            break;
+        }
+    }
+  else
+    {
+      grub_video_bitmap_create (bitmap, header.image_width,
+                                header.image_height,
+                                GRUB_VIDEO_BLIT_FORMAT_R8G8B8);
+      if (grub_errno != GRUB_ERR_NONE)
+        {
+          grub_file_close (file);
+          return grub_errno;
+        }
+
+      /* Load bitmap data.  */
+      switch (header.image_type)
+        {
+          case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR:
+            tga_load_truecolor_R8G8B8 (*bitmap, &header, file);
+            break;
+
+          case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR:
+            tga_load_truecolor_rle_R8G8B8 (*bitmap, &header, file);
+            break;
+        }
+    }
+
+  /* If there were loading proble, destroy bitmap.  */
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_video_bitmap_destroy (*bitmap);
+      *bitmap = 0;
+    }
+
+  grub_file_close (file);
+  return grub_errno;
+}
+
+#if defined(TGA_DEBUG)
+static grub_err_t
+grub_cmd_tgatest (struct grub_arg_list *state __attribute__ ((unused)),
+                  int argc, char **args)
+{
+  struct grub_video_bitmap *bitmap = 0;
+
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
+
+  grub_video_reader_tga (&bitmap, args[0]);  
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+
+  grub_video_bitmap_destroy (bitmap);
+
+  return GRUB_ERR_NONE;
+}
+#endif
+
+static struct grub_video_bitmap_reader tga_reader = {
+  .extension = ".tga",
+  .reader = grub_video_reader_tga,
+  .next = 0
+};
+
+GRUB_MOD_INIT(video_reader_tga)
+{
+  grub_video_bitmap_reader_register (&tga_reader);
+#if defined(TGA_DEBUG)
+  grub_register_command ("tgatest", grub_cmd_tgatest, GRUB_COMMAND_FLAG_BOTH,
+                         "tgatest FILE", "Tests loading of TGA bitmap.", 0);
+#endif
+}
+
+GRUB_MOD_FINI(video_reader_tga)
+{
+#if defined(TGA_DEBUG)
+  grub_unregister_command ("tgatest");
+#endif
+  grub_video_bitmap_reader_unregister (&tga_reader);
+}

reply via email to

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