diff --git a/ChangeLog b/ChangeLog
index d7f219b..7713e29 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,57 @@
+2009-07-26 Vladimir Serbinenko
+
+ Framebuffer split.
+
+ * commands/i386/pc/vbetest.c (grub_cmd_vbetest): Restore video
+ subsystem at the end.
+ * conf/common.rmk (pkglib_MODULES): Add video_fb.mod.
+ (video_fb_mod_SOURCES): New variable.
+ (video_fb_mod_CFLAGS): Likewise.
+ (video_fb_mod_LDFLAGS): Likewise.
+ * conf/i386-pc.rmk (vbe_mod_SOURCES): Remove video/i386/pc/vbeblit.c,
+ video/i386/pc/vbefill.c and video/i386/pc/vbeutil.c.
+ * video/i386/pc/vbeblit.c: Moved from here ...
+ * video/fb/fbblit.c: ..here. Replaced 'vbe' with 'fb'.
+ * video/i386/pc/vbefill.c: Moved from here ...
+ * video/fb/fbfill.c: ..here. Replaced 'vbe' with 'fb'.
+ * video/i386/pc/vbeutil.c: Moved from here ...
+ * video/fb/fbutil.c: ..here. Replaced 'vbe' with 'fb'.
+ * include/grub/i386/pc/vbeblit.h: Moved from here ...
+ * include/grub/fbblit.h: ... here. Replaced 'vbe' with 'fb'.
+ * include/grub/i386/pc/vbefill.h: Moved from here ...
+ * include/grub/fbfill.h: ... here. Replaced 'vbe' with 'fb'.
+ * include/grub/i386/pc/vbeutil.h: Moved from here ...
+ * include/grub/fbutil.h: ... here. Replaced 'vbe' with 'fb'.
+ * include/grub/i386/pc/vbe.h: Moved framebuffer part ...
+ * include/grub/video_fb.h: ... here. Replaced 'vbe' with 'fb'.
+ * include/grub/video.h (GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER): Removed.
+ (GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER): Likewise.
+ (grub_video_adapter): Added 'get_info_and_fini'.
+ (grub_video_get_info_and_fini): New prototype.
+ (grub_video_set_mode): make modestring const char *.
+ * loader/i386/linux.c (grub_linux_setup_video): Use
+ grub_video_get_info_and_fini.
+ (grub_linux_boot): Move modesetting just before booting.
+ * loader/i386/pc/xnu.c (grub_xnu_set_video): Use
+ grub_video_get_info_and_fini.
+ * video/i386/pc/vbe.c: Moved framebuffer part ...
+ * video/fb/video_fb.c: ... here. Replaced 'vbe' with 'fb'.
+ * video/i386/pc/vbe.c (grub_vbe_set_video_mode): Use
+ grub_video_fbstd_colors and grub_video_fb_set_palette.
+ (grub_video_vbe_init): Clear 'framebuffer' variable and use
+ grub_video_fb_init.
+ (grub_video_vbe_fini): Use grub_video_fb_fini.
+ (grub_video_vbe_setup): Use framebuffer.render_target instead of
+ render_target and use grub_video_fb_set_active_render_target and
+ grub_video_fb_set_palette.
+ (grub_video_vbe_set_palette): Use grub_video_fb_set_palette.
+ (grub_video_vbe_set_viewport): Use grub_video_fb_set_viewport.
+ (grub_video_vbe_adapter): Use framebuffer.
+ * video/video.c (grub_video_get_info_and_fini): New function.
+ (grub_video_set_mode): Make modestring const char *.
+ (GRUB_MOD_INIT(video_video)): Don't set variables to 0 since these
+ values are already initialised.
+
2009-08-01 Vladimir Serbinenko
* util/hostfs.c (grub_hostfs_dir): Don't use DT_DIR: It doesn't work
diff --git a/commands/i386/pc/vbetest.c b/commands/i386/pc/vbetest.c
index 3cbc301..314320d 100644
--- a/commands/i386/pc/vbetest.c
+++ b/commands/i386/pc/vbetest.c
@@ -155,6 +155,8 @@ grub_cmd_vbetest (grub_command_t cmd __attribute__ ((unused)),
grub_getkey ();
+ grub_video_restore ();
+
/* Restore old video mode. */
grub_vbe_set_video_mode (old_mode, 0);
diff --git a/conf/common.rmk b/conf/common.rmk
index 032517f..5e93302 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -535,13 +535,18 @@ lua_mod_LDFLAGS = $(COMMON_LDFLAGS)
# Common Video Subsystem specific modules.
pkglib_MODULES += video.mod videotest.mod bitmap.mod tga.mod jpeg.mod \
- png.mod font.mod gfxterm.mod
+ png.mod font.mod gfxterm.mod video_fb.mod
# For video.mod.
video_mod_SOURCES = video/video.c
video_mod_CFLAGS = $(COMMON_CFLAGS)
video_mod_LDFLAGS = $(COMMON_LDFLAGS)
+video_fb_mod_SOURCES = video/fb/video_fb.c video/fb/fbblit.c \
+ video/fb/fbfill.c video/fb/fbutil.c
+video_fb_mod_CFLAGS = $(COMMON_CFLAGS)
+video_fb_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
# For videotest.mod.
videotest_mod_SOURCES = commands/videotest.c
videotest_mod_CFLAGS = $(COMMON_CFLAGS)
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 798aee2..5b7b8c0 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -273,8 +273,7 @@ multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
multiboot_mod_ASFLAGS = $(COMMON_ASFLAGS)
# For vbe.mod.
-vbe_mod_SOURCES = video/i386/pc/vbe.c video/i386/pc/vbeblit.c \
- video/i386/pc/vbefill.c video/i386/pc/vbeutil.c
+vbe_mod_SOURCES = video/i386/pc/vbe.c
vbe_mod_CFLAGS = $(COMMON_CFLAGS)
vbe_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/include/grub/i386/pc/vbe.h b/include/grub/i386/pc/vbe.h
index bd6ecd7..fb11678 100644
--- a/include/grub/i386/pc/vbe.h
+++ b/include/grub/i386/pc/vbe.h
@@ -19,10 +19,7 @@
#ifndef GRUB_VBE_MACHINE_HEADER
#define GRUB_VBE_MACHINE_HEADER 1
-#include
-#include
-#include
-#include
+#include
/* Default video mode to be used. */
#define GRUB_VBE_DEFAULT_VIDEO_MODE 0x101
@@ -224,54 +221,5 @@ grub_err_t grub_vbe_get_video_mode (grub_uint32_t *mode);
grub_err_t grub_vbe_get_video_mode_info (grub_uint32_t mode,
struct grub_vbe_mode_info_block *mode_info);
-/* VBE module internal prototypes (should not be used from elsewhere). */
-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 whether 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);
-
-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);
-
-grub_err_t grub_video_vbe_unmap_color (grub_video_color_t color,
- grub_uint8_t *red,
- grub_uint8_t *green,
- grub_uint8_t *blue,
- grub_uint8_t *alpha);
-
-void grub_video_vbe_unmap_color_int (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);
#endif /* ! GRUB_VBE_MACHINE_HEADER */
diff --git a/include/grub/video.h b/include/grub/video.h
index c98731d..4145db4 100644
--- a/include/grub/video.h
+++ b/include/grub/video.h
@@ -48,10 +48,8 @@ struct grub_video_bitmap;
#define GRUB_VIDEO_MODE_TYPE_DEPTH_MASK 0x0000ff00
#define GRUB_VIDEO_MODE_TYPE_DEPTH_POS 8
-/* Defined predefined render targets. */
-#define GRUB_VIDEO_RENDER_TARGET_DISPLAY ((struct grub_video_render_target *) 0)
-#define GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER ((struct grub_video_render_target *) 0)
-#define GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER ((struct grub_video_render_target *) 1)
+#define GRUB_VIDEO_RENDER_TARGET_DISPLAY \
+ ((struct grub_video_render_target *) 0)
/* Defined blitting formats. */
enum grub_video_blit_format
@@ -177,6 +175,9 @@ struct grub_video_adapter
grub_err_t (*get_info) (struct grub_video_mode_info *mode_info);
+ grub_err_t (*get_info_and_fini) (struct grub_video_mode_info *mode_info,
+ void **framebuffer);
+
grub_err_t (*set_palette) (unsigned int start, unsigned int count,
struct grub_video_palette_data *palette_data);
@@ -241,6 +242,14 @@ grub_err_t grub_video_restore (void);
grub_err_t grub_video_get_info (struct grub_video_mode_info *mode_info);
+/* Framebuffer address may change as a part of normal operation
+ (e.g. double buffering). That's why you need to stop video subsystem to be
+ sure that framebuffer address doesn't change. To ensure this abstraction
+ grub_video_get_info_and_fini is the only function supplying framebuffer
+ address. */
+grub_err_t grub_video_get_info_and_fini (struct grub_video_mode_info *mode_info,
+ void **framebuffer);
+
enum grub_video_blit_format grub_video_get_blit_format (struct grub_video_mode_info *mode_info);
grub_err_t grub_video_set_palette (unsigned int start, unsigned int count,
@@ -297,7 +306,7 @@ grub_err_t grub_video_set_active_render_target (struct grub_video_render_target
grub_err_t grub_video_get_active_render_target (struct grub_video_render_target **target);
-grub_err_t grub_video_set_mode (char *modestring,
+grub_err_t grub_video_set_mode (const char *modestring,
int NESTED_FUNC_ATTR (*hook) (grub_video_adapter_t p,
struct grub_video_mode_info *mode_info));
diff --git a/include/grub/video_fb.h b/include/grub/video_fb.h
new file mode 100644
index 0000000..9ae4101
--- /dev/null
+++ b/include/grub/video_fb.h
@@ -0,0 +1,137 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005,2006,2007,2008 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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, see .
+ */
+
+#ifndef GRUB_VIDEO_FB_HEADER
+#define GRUB_VIDEO_FB_HEADER 1
+
+#include
+#include
+#include
+#include
+
+/* FB module internal prototype (should not be used from elsewhere). */
+
+struct grub_video_fbblit_info;
+
+struct grub_video_fbrender_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 whether 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;
+};
+
+#define GRUB_VIDEO_FBSTD_NUMCOLORS 16
+extern struct grub_video_palette_data grub_video_fbstd_colors[GRUB_VIDEO_FBSTD_NUMCOLORS];
+
+grub_uint8_t * grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source,
+ grub_uint32_t x, grub_uint32_t y);
+
+grub_err_t
+grub_video_fb_init (void);
+
+grub_err_t
+grub_video_fb_fini (void);
+
+grub_err_t
+grub_video_fb_get_info (struct grub_video_mode_info *mode_info);
+
+grub_err_t
+grub_video_fb_get_palette (unsigned int start, unsigned int count,
+ struct grub_video_palette_data *palette_data);
+grub_err_t
+grub_video_fb_set_palette (unsigned int start, unsigned int count,
+ struct grub_video_palette_data *palette_data);
+grub_err_t
+grub_video_fb_set_viewport (unsigned int x, unsigned int y,
+ unsigned int width, unsigned int height);
+grub_err_t
+grub_video_fb_get_viewport (unsigned int *x, unsigned int *y,
+ unsigned int *width, unsigned int *height);
+
+grub_video_color_t
+grub_video_fb_map_color (grub_uint32_t color_name);
+
+grub_video_color_t
+grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green,
+ grub_uint8_t blue);
+
+grub_video_color_t
+grub_video_fb_map_rgba (grub_uint8_t red, grub_uint8_t green,
+ grub_uint8_t blue, grub_uint8_t alpha);
+
+grub_err_t
+grub_video_fb_unmap_color (grub_video_color_t color,
+ grub_uint8_t *red, grub_uint8_t *green,
+ grub_uint8_t *blue, grub_uint8_t *alpha);
+
+void
+grub_video_fb_unmap_color_int (struct grub_video_fbblit_info * source,
+ grub_video_color_t color,
+ grub_uint8_t *red, grub_uint8_t *green,
+ grub_uint8_t *blue, grub_uint8_t *alpha);
+
+grub_err_t
+grub_video_fb_fill_rect (grub_video_color_t color, int x, int y,
+ unsigned int width, unsigned int height);
+
+grub_err_t
+grub_video_fb_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_fb_blit_render_target (struct grub_video_fbrender_target *source,
+ 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_fb_scroll (grub_video_color_t color, int dx, int dy);
+
+grub_err_t
+grub_video_fb_create_render_target (struct grub_video_fbrender_target **result,
+ unsigned int width, unsigned int height,
+ unsigned int mode_type __attribute__ ((unused)));
+
+grub_err_t
+grub_video_fb_delete_render_target (struct grub_video_fbrender_target *target);
+
+grub_err_t
+grub_video_fb_get_active_render_target (struct grub_video_fbrender_target **target);
+
+grub_err_t
+grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *target);
+
+#endif /* ! GRUB_VIDEO_FB_HEADER */
diff --git a/loader/i386/linux.c b/loader/i386/linux.c
index d76e7fb..238e4cd 100644
--- a/loader/i386/linux.c
+++ b/loader/i386/linux.c
@@ -31,9 +31,7 @@
#include
#include
#include
-/* FIXME: the definition of `struct grub_video_render_target' is
- VBE-specific. */
-#include
+#include
#include
#define GRUB_LINUX_CL_OFFSET 0x1000
@@ -403,14 +401,11 @@ static int
grub_linux_setup_video (struct linux_kernel_params *params)
{
struct grub_video_mode_info mode_info;
- struct grub_video_render_target *render_target;
+ void *framebuffer;
int ret;
- ret = grub_video_get_info (&mode_info);
- if (ret)
- return 1;
+ ret = grub_video_get_info_and_fini (&mode_info, &framebuffer);
- ret = grub_video_get_active_render_target (&render_target);
if (ret)
return 1;
@@ -419,7 +414,7 @@ grub_linux_setup_video (struct linux_kernel_params *params)
params->lfb_depth = mode_info.bpp;
params->lfb_line_len = mode_info.pitch;
- params->lfb_base = (grub_size_t) render_target->data;
+ params->lfb_base = (grub_size_t) framebuffer;
params->lfb_size = (params->lfb_line_len * params->lfb_height + 65535) >> 16;
params->red_mask_size = mode_info.red_mask_size;
@@ -449,41 +444,6 @@ grub_linux_boot (void)
params = real_mode_mem;
- modevar = grub_env_get ("gfxpayload");
-
- /* Now all graphical modes are acceptable.
- May change in future if we have modes without framebuffer. */
- if (modevar && *modevar != 0)
- {
- tmp = grub_malloc (grub_strlen (modevar)
- + sizeof (DEFAULT_VIDEO_MODE) + 1);
- if (! tmp)
- return grub_errno;
- grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
- err = grub_video_set_mode (tmp, 0);
- grub_free (tmp);
- }
-#ifndef GRUB_ASSUME_LINUX_HAS_FB_SUPPORT
- else
- err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0);
-#endif
-
- if (err)
- {
- grub_print_error ();
- grub_printf ("Booting however\n");
- grub_errno = GRUB_ERR_NONE;
- }
-
- if (! grub_linux_setup_video (params))
- params->have_vga = GRUB_VIDEO_TYPE_VLFB;
- else
- {
- params->have_vga = GRUB_VIDEO_TYPE_TEXT;
- params->video_width = 80;
- params->video_height = 25;
- }
-
grub_dprintf ("linux", "code32_start = %x, idt_desc = %lx, gdt_desc = %lx\n",
(unsigned) params->code32_start,
(unsigned long) &(idt_desc.limit),
@@ -534,6 +494,41 @@ grub_linux_boot (void)
grub_mmap_iterate (hook);
params->mmap_size = e820_num;
+ modevar = grub_env_get ("gfxpayload");
+
+ /* Now all graphical modes are acceptable.
+ May change in future if we have modes without framebuffer. */
+ if (modevar && *modevar != 0)
+ {
+ tmp = grub_malloc (grub_strlen (modevar)
+ + sizeof (DEFAULT_VIDEO_MODE) + 1);
+ if (! tmp)
+ return grub_errno;
+ grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
+ err = grub_video_set_mode (tmp, 0);
+ grub_free (tmp);
+ }
+#ifndef GRUB_ASSUME_LINUX_HAS_FB_SUPPORT
+ else
+ err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0);
+#endif
+
+ if (err)
+ {
+ grub_print_error ();
+ grub_printf ("Booting however\n");
+ grub_errno = GRUB_ERR_NONE;
+ }
+
+ if (! grub_linux_setup_video (params))
+ params->have_vga = GRUB_VIDEO_TYPE_VLFB;
+ else
+ {
+ params->have_vga = GRUB_VIDEO_TYPE_TEXT;
+ params->video_width = 80;
+ params->video_height = 25;
+ }
+
/* Initialize these last, because terminal position could be affected by printfs above. */
if (params->have_vga == GRUB_VIDEO_TYPE_TEXT)
{
diff --git a/loader/i386/pc/xnu.c b/loader/i386/pc/xnu.c
index 037a713..69a9405 100644
--- a/loader/i386/pc/xnu.c
+++ b/loader/i386/pc/xnu.c
@@ -21,8 +21,7 @@
#include
#include
#include
-#include
-#include
+#include
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))
@@ -43,10 +42,10 @@ grub_err_t
grub_xnu_set_video (struct grub_xnu_boot_params *params)
{
struct grub_video_mode_info mode_info;
- struct grub_video_render_target *render_target;
int ret;
int x,y;
char *tmp, *modevar;
+ void *framebuffer;
grub_err_t err;
modevar = grub_env_get ("gfxpayload");
@@ -67,11 +66,7 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params)
if (err)
return err;
- ret = grub_video_get_info (&mode_info);
- if (ret)
- return grub_error (GRUB_ERR_IO, "couldn't retrieve video parameters");
-
- ret = grub_video_get_active_render_target (&render_target);
+ ret = grub_video_get_info_and_fini (&mode_info, &framebuffer);
if (ret)
return grub_error (GRUB_ERR_IO, "couldn't retrieve video parameters");
@@ -102,7 +97,7 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params)
params->lfb_depth = mode_info.bpp;
params->lfb_line_len = mode_info.pitch;
- params->lfb_base = PTR_TO_UINT32 (render_target->data);
+ params->lfb_base = PTR_TO_UINT32 (framebuffer);
params->lfb_mode = grub_xnu_bitmap
? GRUB_XNU_VIDEO_SPLASH : GRUB_XNU_VIDEO_TEXT_IN_VIDEO;
diff --git a/video/fb/video_fb.c b/video/fb/video_fb.c
new file mode 100644
index 0000000..c80f6ea
--- /dev/null
+++ b/video/fb/video_fb.c
@@ -0,0 +1,1100 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005,2006,2007,2008,2009 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static struct grub_video_fbrender_target *render_target;
+struct grub_video_palette_data *palette;
+static unsigned int palette_size;
+
+/* Specify "standard" VGA palette, some video cards may
+ need this and this will also be used when using RGB modes. */
+struct grub_video_palette_data grub_video_fbstd_colors[GRUB_VIDEO_FBSTD_NUMCOLORS] =
+ {
+ // {R, G, B, A}
+ {0x00, 0x00, 0x00, 0xFF}, // 0 = black
+ {0x00, 0x00, 0xA8, 0xFF}, // 1 = blue
+ {0x00, 0xA8, 0x00, 0xFF}, // 2 = green
+ {0x00, 0xA8, 0xA8, 0xFF}, // 3 = cyan
+ {0xA8, 0x00, 0x00, 0xFF}, // 4 = red
+ {0xA8, 0x00, 0xA8, 0xFF}, // 5 = magenta
+ {0xA8, 0x54, 0x00, 0xFF}, // 6 = brown
+ {0xA8, 0xA8, 0xA8, 0xFF}, // 7 = light gray
+
+ {0x54, 0x54, 0x54, 0xFF}, // 8 = dark gray
+ {0x54, 0x54, 0xFE, 0xFF}, // 9 = bright blue
+ {0x54, 0xFE, 0x54, 0xFF}, // 10 = bright green
+ {0x54, 0xFE, 0xFE, 0xFF}, // 11 = bright cyan
+ {0xFE, 0x54, 0x54, 0xFF}, // 12 = bright red
+ {0xFE, 0x54, 0xFE, 0xFF}, // 13 = bright magenta
+ {0xFE, 0xFE, 0x54, 0xFF}, // 14 = yellow
+ {0xFE, 0xFE, 0xFE, 0xFF} // 15 = white
+ };
+
+grub_err_t
+grub_video_fb_init (void)
+{
+ grub_free (palette);
+ render_target = 0;
+ palette = 0;
+ palette_size = 0;
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_video_fb_fini (void)
+{
+ grub_free (palette);
+ render_target = 0;
+ palette = 0;
+ palette_size = 0;
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_video_fb_get_info (struct grub_video_mode_info *mode_info)
+{
+ /* Copy mode info from active render target. */
+ grub_memcpy (mode_info, &render_target->mode_info,
+ sizeof (struct grub_video_mode_info));
+
+ return GRUB_ERR_NONE;
+}
+
+
+grub_uint8_t *
+grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source,
+ grub_uint32_t x, grub_uint32_t 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_err_t
+grub_video_fb_get_palette (unsigned int start, unsigned int count,
+ struct grub_video_palette_data *palette_data)
+{
+ unsigned int i;
+
+ /* Assume that we know everything from index color palette. */
+ for (i = 0; (i < count) && ((i + start) < palette_size); i++)
+ palette_data[i] = palette[start + i];
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_video_fb_set_palette (unsigned int start, unsigned int count,
+ struct grub_video_palette_data *palette_data)
+{
+ unsigned i;
+ if (start + count > palette_size)
+ {
+ palette_size = start + count;
+ palette = grub_realloc (palette, sizeof (palette[0]) * palette_size);
+ if (!palette)
+ {
+ grub_video_fb_fini ();
+ return grub_errno;
+ }
+ }
+ for (i = 0; (i < count) && ((i + start) < palette_size); i++)
+ palette[start + i] = palette_data[i];
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_video_fb_set_viewport (unsigned int x, unsigned int y,
+ unsigned int width, unsigned int height)
+{
+ render_target->viewport.x = x;
+ render_target->viewport.y = y;
+ render_target->viewport.width = width;
+ render_target->viewport.height = height;
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_video_fb_get_viewport (unsigned int *x, unsigned int *y,
+ unsigned int *width, unsigned int *height)
+{
+ if (x) *x = render_target->viewport.x;
+ if (y) *y = render_target->viewport.y;
+ if (width) *width = render_target->viewport.width;
+ if (height) *height = render_target->viewport.height;
+
+ return GRUB_ERR_NONE;
+}
+
+/* Maps color name to target optimized color format. */
+grub_video_color_t
+grub_video_fb_map_color (grub_uint32_t color_name)
+{
+ /* TODO: implement color theme mapping code. */
+
+ if (color_name < palette_size)
+ {
+ if ((render_target->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ return color_name;
+ else
+ {
+ grub_video_color_t color;
+
+ color = grub_video_fb_map_rgb (palette[color_name].r,
+ palette[color_name].g,
+ palette[color_name].b);
+
+ return color;
+ }
+ }
+
+ return 0;
+}
+
+/* Maps RGB to target optimized color format. */
+grub_video_color_t
+grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green,
+ grub_uint8_t blue)
+{
+ if ((render_target->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ {
+ int minindex = 0;
+ int delta = 0;
+ int tmp;
+ int val;
+ unsigned i;
+
+ /* Find best matching color. */
+ for (i = 0; i < palette_size; i++)
+ {
+ val = palette[i].r - red;
+ tmp = val * val;
+ val = palette[i].g - green;
+ tmp += val * val;
+ val = palette[i].b - blue;
+ tmp += val * val;
+
+ if (i == 0)
+ delta = tmp;
+
+ if (tmp < delta)
+ {
+ delta = tmp;
+ minindex = i;
+ if (tmp == 0)
+ break;
+ }
+ }
+
+ return minindex;
+ }
+ else if ((render_target->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0)
+ {
+ if (red == render_target->mode_info.fg_red
+ && green == render_target->mode_info.fg_green
+ && blue == render_target->mode_info.fg_blue)
+ return 1;
+ else
+ return 0;
+ }
+ else
+ {
+ grub_uint32_t value;
+ grub_uint8_t alpha = 255; /* Opaque color. */
+
+ red >>= 8 - render_target->mode_info.red_mask_size;
+ green >>= 8 - render_target->mode_info.green_mask_size;
+ blue >>= 8 - render_target->mode_info.blue_mask_size;
+ alpha >>= 8 - render_target->mode_info.reserved_mask_size;
+
+ value = red << render_target->mode_info.red_field_pos;
+ value |= green << render_target->mode_info.green_field_pos;
+ value |= blue << render_target->mode_info.blue_field_pos;
+ value |= alpha << render_target->mode_info.reserved_field_pos;
+
+ return value;
+ }
+
+}
+
+/* Maps RGBA to target optimized color format. */
+grub_video_color_t
+grub_video_fb_map_rgba (grub_uint8_t red, grub_uint8_t green,
+ grub_uint8_t blue, grub_uint8_t alpha)
+{
+ if ((render_target->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ /* No alpha available in index color modes, just use
+ same value as in only RGB modes. */
+ return grub_video_fb_map_rgb (red, green, blue);
+ else if ((render_target->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0)
+ {
+ if (red == render_target->mode_info.fg_red
+ && green == render_target->mode_info.fg_green
+ && blue == render_target->mode_info.fg_blue
+ && alpha == render_target->mode_info.fg_alpha)
+ return 1;
+ else
+ return 0;
+ }
+ else
+ {
+ grub_uint32_t value;
+
+ red >>= 8 - render_target->mode_info.red_mask_size;
+ green >>= 8 - render_target->mode_info.green_mask_size;
+ blue >>= 8 - render_target->mode_info.blue_mask_size;
+ alpha >>= 8 - render_target->mode_info.reserved_mask_size;
+
+ value = red << render_target->mode_info.red_field_pos;
+ value |= green << render_target->mode_info.green_field_pos;
+ value |= blue << render_target->mode_info.blue_field_pos;
+ value |= alpha << render_target->mode_info.reserved_field_pos;
+
+ return value;
+ }
+}
+
+/* Splits target optimized format to components. */
+grub_err_t
+grub_video_fb_unmap_color (grub_video_color_t color,
+ grub_uint8_t *red, grub_uint8_t *green,
+ grub_uint8_t *blue, grub_uint8_t *alpha)
+{
+ struct grub_video_fbblit_info target_info;
+
+ target_info.mode_info = &render_target->mode_info;
+ target_info.data = render_target->data;
+
+ grub_video_fb_unmap_color_int (&target_info, color, red, green, blue, alpha);
+
+ return GRUB_ERR_NONE;
+}
+
+/* Splits color in source format to components. */
+void
+grub_video_fb_unmap_color_int (struct grub_video_fbblit_info * source,
+ grub_video_color_t color,
+ grub_uint8_t *red, grub_uint8_t *green,
+ grub_uint8_t *blue, grub_uint8_t *alpha)
+{
+ 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 an out-of-bounds color, return transparent black. */
+ if (color > 255)
+ {
+ *red = 0;
+ *green = 0;
+ *blue = 0;
+ *alpha = 0;
+ return;
+ }
+
+ *red = palette[color].r;
+ *green = palette[color].g;
+ *blue = palette[color].b;
+ *alpha = palette[color].a;
+ return;
+ }
+ else if ((mode_info->mode_type
+ & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0)
+ {
+ if (color & 1)
+ {
+ *red = mode_info->fg_red;
+ *green = mode_info->fg_green;
+ *blue = mode_info->fg_blue;
+ *alpha = mode_info->fg_alpha;
+ }
+ else
+ {
+ *red = mode_info->bg_red;
+ *green = mode_info->bg_green;
+ *blue = mode_info->bg_blue;
+ *alpha = mode_info->bg_alpha;
+ }
+ }
+ else
+ {
+ grub_uint32_t tmp;
+
+ /* Get red component. */
+ 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 >> 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 >> 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)
+ {
+ 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. */
+ tmp = 255;
+
+ *alpha = tmp & 0xFF;
+ }
+}
+
+grub_err_t
+grub_video_fb_fill_rect (grub_video_color_t color, int x, int y,
+ unsigned int width, unsigned int height)
+{
+ struct grub_video_fbblit_info target;
+
+ /* Make sure there is something to do. */
+ if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0))
+ return GRUB_ERR_NONE;
+ if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0))
+ return GRUB_ERR_NONE;
+
+ /* Do not allow drawing out of viewport. */
+ if (x < 0)
+ {
+ width += x;
+ x = 0;
+ }
+ if (y < 0)
+ {
+ height += y;
+ y = 0;
+ }
+
+ if ((x + width) > render_target->viewport.width)
+ width = render_target->viewport.width - x;
+ if ((y + height) > render_target->viewport.height)
+ height = render_target->viewport.height - y;
+
+ /* Add viewport offset. */
+ x += render_target->viewport.x;
+ y += render_target->viewport.y;
+
+ /* Use fbblit_info to encapsulate rendering. */
+ target.mode_info = &render_target->mode_info;
+ target.data = render_target->data;
+
+ /* Try to figure out more optimized version. Note that color is already
+ mapped to target format so we can make assumptions based on that. */
+ if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
+ {
+ grub_video_fbfill_direct32 (&target, color, x, y,
+ width, height);
+ return GRUB_ERR_NONE;
+ }
+ else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
+ {
+ grub_video_fbfill_direct32 (&target, color, x, y,
+ width, height);
+ return GRUB_ERR_NONE;
+ }
+ else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
+ {
+ grub_video_fbfill_direct24 (&target, color, x, y,
+ width, height);
+ return GRUB_ERR_NONE;
+ }
+ else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_565)
+ {
+ grub_video_fbfill_direct16 (&target, color, x, y,
+ width, height);
+ return GRUB_ERR_NONE;
+ }
+ else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_565)
+ {
+ grub_video_fbfill_direct16 (&target, color, x, y,
+ width, height);
+ return GRUB_ERR_NONE;
+ }
+ else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+ {
+ grub_video_fbfill_direct8 (&target, color, x, y,
+ width, height);
+ return GRUB_ERR_NONE;
+ }
+
+ /* No optimized version found, use default (slow) filler. */
+ grub_video_fbfill (&target, color, x, y, width, height);
+
+ return GRUB_ERR_NONE;
+}
+
+/* NOTE: This function assumes that given coordinates are within bounds of
+ handled data. */
+static void
+common_blitter (struct grub_video_fbblit_info *target,
+ struct grub_video_fbblit_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_RGBA_8888)
+ {
+ if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
+ {
+ grub_video_fbblit_replace_directN (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
+ {
+ grub_video_fbblit_replace_BGRX8888_RGBX8888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888)
+ {
+ grub_video_fbblit_replace_BGR888_RGBX8888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
+ {
+ grub_video_fbblit_replace_RGB888_RGBX8888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+ {
+ grub_video_fbblit_replace_index_RGBX8888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ }
+ else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
+ {
+ if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
+ {
+ grub_video_fbblit_replace_BGRX8888_RGB888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
+ {
+ grub_video_fbblit_replace_RGBX8888_RGB888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888)
+ {
+ grub_video_fbblit_replace_BGR888_RGB888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
+ {
+ grub_video_fbblit_replace_directN (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+ {
+ grub_video_fbblit_replace_index_RGB888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ }
+ else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
+ {
+ if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
+ {
+ grub_video_fbblit_replace_directN (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ }
+ else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+ {
+ if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+ {
+ grub_video_fbblit_replace_directN (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ }
+
+ /* No optimized replace operator found, use default (slow) blitter. */
+ grub_video_fbblit_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_RGBA_8888)
+ {
+ if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
+ {
+ grub_video_fbblit_blend_BGRA8888_RGBA8888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
+ {
+ grub_video_fbblit_blend_RGBA8888_RGBA8888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888)
+ {
+ grub_video_fbblit_blend_BGR888_RGBA8888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
+ {
+ grub_video_fbblit_blend_RGB888_RGBA8888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+ {
+ grub_video_fbblit_blend_index_RGBA8888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ }
+ else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
+ {
+ /* Note: There is really no alpha information here, so blend is
+ changed to replace. */
+
+ if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
+ {
+ grub_video_fbblit_replace_BGRX8888_RGB888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
+ {
+ grub_video_fbblit_replace_RGBX8888_RGB888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888)
+ {
+ grub_video_fbblit_replace_BGR888_RGB888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
+ {
+ grub_video_fbblit_replace_directN (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+ {
+ grub_video_fbblit_replace_index_RGB888 (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ }
+
+ /* No optimized blend operation found, use default (slow) blitter. */
+ grub_video_fbblit_blend (target, source, x, y, width, height,
+ offset_x, offset_y);
+ }
+}
+
+grub_err_t
+grub_video_fb_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_fbblit_info source;
+ struct grub_video_fbblit_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;
+
+ /* If we have negative coordinates, optimize drawing to minimum. */
+ if (offset_x < 0)
+ {
+ width += offset_x;
+ x -= offset_x;
+ offset_x = 0;
+ }
+
+ if (offset_y < 0)
+ {
+ height += offset_y;
+ y -= offset_y;
+ offset_y = 0;
+ }
+
+ if (x < 0)
+ {
+ width += x;
+ offset_x -= x;
+ x = 0;
+ }
+
+ if (y < 0)
+ {
+ height += 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;
+
+ 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;
+
+ /* Use fbblit_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;
+}
+
+grub_err_t
+grub_video_fb_blit_render_target (struct grub_video_fbrender_target *source,
+ 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_fbblit_info source_info;
+ struct grub_video_fbblit_info target_info;
+
+ /* Make sure there is something to do. */
+ if ((width == 0) || (height == 0))
+ return GRUB_ERR_NONE;
+ if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0))
+ return GRUB_ERR_NONE;
+ if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0))
+ return GRUB_ERR_NONE;
+ if ((x + (int)source->mode_info.width) < 0)
+ return GRUB_ERR_NONE;
+ if ((y + (int)source->mode_info.height) < 0)
+ return GRUB_ERR_NONE;
+ if ((offset_x >= (int)source->mode_info.width)
+ || (offset_x + (int)width < 0))
+ return GRUB_ERR_NONE;
+ if ((offset_y >= (int)source->mode_info.height)
+ || (offset_y + (int)height < 0))
+ return GRUB_ERR_NONE;
+
+ /* If we have negative coordinates, optimize drawing to minimum. */
+ if (offset_x < 0)
+ {
+ width += offset_x;
+ x -= offset_x;
+ offset_x = 0;
+ }
+
+ if (offset_y < 0)
+ {
+ height += offset_y;
+ y -= offset_y;
+ offset_y = 0;
+ }
+
+ if (x < 0)
+ {
+ width += x;
+ offset_x -= x;
+ x = 0;
+ }
+
+ if (y < 0)
+ {
+ height += 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;
+
+ if ((offset_x + width) > source->mode_info.width)
+ width = source->mode_info.width - offset_x;
+ if ((offset_y + height) > source->mode_info.height)
+ height = source->mode_info.height - offset_y;
+
+ /* Limit drawing to source render target dimensions. */
+ if (width > source->mode_info.width)
+ width = source->mode_info.width;
+
+ if (height > source->mode_info.height)
+ height = source->mode_info.height;
+
+ /* Add viewport offset. */
+ x += render_target->viewport.x;
+ y += render_target->viewport.y;
+
+ /* Use fbblit_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;
+}
+
+grub_err_t
+grub_video_fb_scroll (grub_video_color_t color, int dx, int dy)
+{
+ int width;
+ int height;
+ int src_x;
+ int src_y;
+ int dst_x;
+ int dst_y;
+
+ /* 1. Check if we have something to do. */
+ if ((dx == 0) && (dy == 0))
+ return GRUB_ERR_NONE;
+
+ width = render_target->viewport.width - grub_abs (dx);
+ height = render_target->viewport.height - grub_abs (dy);
+
+ if (dx < 0)
+ {
+ src_x = render_target->viewport.x - dx;
+ dst_x = render_target->viewport.x;
+ }
+ else
+ {
+ src_x = render_target->viewport.x;
+ dst_x = render_target->viewport.x + dx;
+ }
+
+ if (dy < 0)
+ {
+ src_y = render_target->viewport.y - dy;
+ dst_y = render_target->viewport.y;
+ }
+ else
+ {
+ src_y = render_target->viewport.y;
+ dst_y = render_target->viewport.y + dy;
+ }
+
+ /* 2. Check if there is need to copy data. */
+ if ((grub_abs (dx) < render_target->viewport.width)
+ && (grub_abs (dy) < render_target->viewport.height))
+ {
+ /* 3. Move data in render target. */
+ struct grub_video_fbblit_info target;
+ grub_uint8_t *src;
+ grub_uint8_t *dst;
+ int j;
+
+ target.mode_info = &render_target->mode_info;
+ target.data = render_target->data;
+
+ /* Check vertical direction of the move. */
+ if (dy <= 0)
+ /* 3a. Move data upwards. */
+ for (j = 0; j < height; j++)
+ {
+ dst = grub_video_fb_get_video_ptr (&target, dst_x, dst_y + j);
+ src = grub_video_fb_get_video_ptr (&target, src_x, src_y + j);
+ grub_memmove (dst, src,
+ width * target.mode_info->bytes_per_pixel);
+ }
+ else
+ /* 3b. Move data downwards. */
+ for (j = (height - 1); j >= 0; j--)
+ {
+ dst = grub_video_fb_get_video_ptr (&target, dst_x, dst_y + j);
+ src = grub_video_fb_get_video_ptr (&target, src_x, src_y + j);
+ grub_memmove (dst, src,
+ width * target.mode_info->bytes_per_pixel);
+ }
+ }
+
+ /* 4. Fill empty space with specified color. In this implementation
+ there might be colliding areas but at the moment there is no need
+ to optimize this. */
+
+ /* 4a. Fill top & bottom parts. */
+ if (dy > 0)
+ grub_video_fb_fill_rect (color, 0, 0, render_target->viewport.width, dy);
+ else if (dy < 0)
+ {
+ if (render_target->viewport.height < grub_abs (dy))
+ dy = -render_target->viewport.height;
+
+ grub_video_fb_fill_rect (color, 0, render_target->viewport.height + dy,
+ render_target->viewport.width, -dy);
+ }
+
+ /* 4b. Fill left & right parts. */
+ if (dx > 0)
+ grub_video_fb_fill_rect (color, 0, 0,
+ dx, render_target->viewport.height);
+ else if (dx < 0)
+ {
+ if (render_target->viewport.width < grub_abs (dx))
+ dx = -render_target->viewport.width;
+
+ grub_video_fb_fill_rect (color, render_target->viewport.width + dx, 0,
+ -dx, render_target->viewport.height);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+
+grub_err_t
+grub_video_fb_create_render_target (struct grub_video_fbrender_target **result,
+ unsigned int width, unsigned int height,
+ unsigned int mode_type __attribute__ ((unused)))
+{
+ struct grub_video_fbrender_target *target;
+ unsigned int size;
+
+ /* Validate arguments. */
+ if ((! result)
+ || (width == 0)
+ || (height == 0))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "invalid argument given.");
+
+ /* Allocate memory for render target. */
+ target = grub_malloc (sizeof (struct grub_video_fbrender_target));
+ if (! target)
+ return grub_errno;
+
+ /* TODO: Implement other types too.
+ Currently only 32bit render targets are supported. */
+
+ /* Mark render target as allocated. */
+ target->is_allocated = 1;
+
+ /* Maximize viewport. */
+ target->viewport.x = 0;
+ target->viewport.y = 0;
+ target->viewport.width = width;
+ target->viewport.height = height;
+
+ /* Setup render target format. */
+ target->mode_info.width = width;
+ target->mode_info.height = height;
+ target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB
+ | GRUB_VIDEO_MODE_TYPE_ALPHA;
+ target->mode_info.bpp = 32;
+ target->mode_info.bytes_per_pixel = 4;
+ target->mode_info.pitch = target->mode_info.bytes_per_pixel * width;
+ target->mode_info.number_of_colors = palette_size; /* Emulated palette. */
+ target->mode_info.red_mask_size = 8;
+ target->mode_info.red_field_pos = 0;
+ target->mode_info.green_mask_size = 8;
+ target->mode_info.green_field_pos = 8;
+ target->mode_info.blue_mask_size = 8;
+ target->mode_info.blue_field_pos = 16;
+ target->mode_info.reserved_mask_size = 8;
+ target->mode_info.reserved_field_pos = 24;
+
+ target->mode_info.blit_format = grub_video_get_blit_format (&target->mode_info);
+
+ /* Calculate size needed for the data. */
+ size = (width * target->mode_info.bytes_per_pixel) * height;
+
+ target->data = grub_malloc (size);
+ if (! target->data)
+ {
+ grub_free (target);
+ return grub_errno;
+ }
+
+ /* Clear render target with black and maximum transparency. */
+ grub_memset (target->data, 0, size);
+
+ /* TODO: Add render target to render target list. */
+
+ /* Save result to caller. */
+ *result = target;
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_video_fb_delete_render_target (struct grub_video_fbrender_target *target)
+{
+ /* If there is no target, then just return without error. */
+ if (! target)
+ return GRUB_ERR_NONE;
+
+ /* TODO: Delist render target from render target list. */
+
+ /* If this is software render target, free it's memory. */
+ if (target->is_allocated)
+ grub_free (target->data);
+
+ /* Free render target. */
+ grub_free (target);
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *target)
+{
+ if (! target->data)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "invalid render target given.");
+
+ render_target = target;
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_video_fb_get_active_render_target (struct grub_video_fbrender_target **target)
+{
+ *target = render_target;
+
+ return GRUB_ERR_NONE;
+}
diff --git a/video/i386/pc/vbe.c b/video/i386/pc/vbe.c
index ae08402..67b724c 100644
--- a/video/i386/pc/vbe.c
+++ b/video/i386/pc/vbe.c
@@ -16,43 +16,17 @@
* along with GRUB. If not, see .
*/
+#define grub_video_render_target grub_video_fbrender_target
+
#include
#include
#include
#include
-#include
-#include
-#include
#include
#include
#include
#include
#include
-#include
-
-/* Specify "standard" VGA palette, some video cards may
- need this and this will also be used when using RGB modes. */
-static struct grub_vbe_palette_data vga_colors[16] =
- {
- // {B, G, R, A}
- {0x00, 0x00, 0x00, 0x00}, // 0 = black
- {0xA8, 0x00, 0x00, 0x00}, // 1 = blue
- {0x00, 0xA8, 0x00, 0x00}, // 2 = green
- {0xA8, 0xA8, 0x00, 0x00}, // 3 = cyan
- {0x00, 0x00, 0xA8, 0x00}, // 4 = red
- {0xA8, 0x00, 0xA8, 0x00}, // 5 = magenta
- {0x00, 0x54, 0xA8, 0x00}, // 6 = brown
- {0xA8, 0xA8, 0xA8, 0x00}, // 7 = light gray
-
- {0x54, 0x54, 0x54, 0x00}, // 8 = dark gray
- {0xFE, 0x54, 0x54, 0x00}, // 9 = bright blue
- {0x54, 0xFE, 0x54, 0x00}, // 10 = bright green
- {0xFE, 0xFE, 0x54, 0x00}, // 11 = bright cyan
- {0x54, 0x54, 0xFE, 0x00}, // 12 = bright red
- {0xFE, 0x54, 0xFE, 0x00}, // 13 = bright magenta
- {0x54, 0xFE, 0xFE, 0x00}, // 14 = yellow
- {0xFE, 0xFE, 0xFE, 0x00} // 15 = white
- };
static int vbe_detected = -1;
@@ -68,10 +42,8 @@ static struct
grub_uint32_t active_mode;
grub_uint8_t *ptr;
int index_color_mode;
- struct grub_video_palette_data palette[256];
} framebuffer;
-static struct grub_video_render_target *render_target;
static grub_uint32_t initial_mode;
static grub_uint32_t mode_in_use = 0x55aa;
static grub_uint16_t *mode_list;
@@ -142,6 +114,7 @@ grub_vbe_set_video_mode (grub_uint32_t mode,
{
grub_vbe_status_t status;
grub_uint32_t old_mode;
+ grub_err_t err;
/* Make sure that VBE is supported. */
grub_vbe_probe (0);
@@ -239,15 +212,26 @@ grub_vbe_set_video_mode (grub_uint32_t mode,
{
struct grub_vbe_palette_data *palette
= (struct grub_vbe_palette_data *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+ unsigned i;
/* Make sure that the BIOS can reach the palette. */
- grub_memcpy (palette, vga_colors, sizeof (vga_colors));
- status = grub_vbe_bios_set_palette_data (sizeof (vga_colors)
- / sizeof (struct grub_vbe_palette_data),
- 0,
- palette);
+ for (i = 0; i < GRUB_VIDEO_FBSTD_NUMCOLORS; i++)
+ {
+ palette[i].red = grub_video_fbstd_colors[i].r;
+ palette[i].green = grub_video_fbstd_colors[i].g;
+ palette[i].blue = grub_video_fbstd_colors[i].b;
+ palette[i].alignment = 0;
+ }
+
+ status = grub_vbe_bios_set_palette_data (GRUB_VIDEO_FBSTD_NUMCOLORS,
+ 0, palette);
/* Just ignore the status. */
+ err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
+ grub_video_fbstd_colors);
+ if (err)
+ return err;
+
}
}
@@ -308,43 +292,6 @@ grub_vbe_get_video_mode_info (grub_uint32_t mode,
return GRUB_ERR_NONE;
}
-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_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;
-}
-
static grub_err_t
grub_video_vbe_init (void)
{
@@ -385,11 +332,10 @@ grub_video_vbe_init (void)
return grub_errno;
}
- /* Reset frame buffer and render target variables. */
+ /* Reset frame buffer. */
grub_memset (&framebuffer, 0, sizeof(framebuffer));
- render_target = &framebuffer.render_target;
- return GRUB_ERR_NONE;
+ return grub_video_fb_init ();
}
static grub_err_t
@@ -409,8 +355,7 @@ grub_video_vbe_fini (void)
/* TODO: destroy render targets. */
- /* Return success to caller. */
- return GRUB_ERR_NONE;
+ return grub_video_fb_fini ();
}
static grub_err_t
@@ -422,7 +367,6 @@ grub_video_vbe_setup (unsigned int width, unsigned int height,
struct grub_vbe_mode_info_block best_mode_info;
grub_uint32_t best_mode = 0;
int depth;
- unsigned int i;
/* Decode depth from mode_type. If it is zero, then autodetect. */
depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
@@ -502,6 +446,7 @@ grub_video_vbe_setup (unsigned int width, unsigned int height,
/* Try to initialize best mode found. */
if (best_mode != 0)
{
+ grub_err_t err;
/* If this fails, then we have mode selection heuristics problem,
or adapter failure. */
grub_vbe_set_video_mode (best_mode, &active_mode_info);
@@ -512,56 +457,48 @@ grub_video_vbe_setup (unsigned int width, unsigned int height,
in order to fasten later operations. */
mode_in_use = best_mode;
- /* Reset render target to framebuffer one. */
- render_target = &framebuffer.render_target;
-
/* Fill mode info details in framebuffer's render target. */
- render_target->mode_info.width = active_mode_info.x_resolution;
- render_target->mode_info.height = active_mode_info.y_resolution;
+ framebuffer.render_target.data = framebuffer.ptr;
+ framebuffer.render_target.mode_info.width = active_mode_info.x_resolution;
+ framebuffer.render_target.mode_info.height = active_mode_info.y_resolution;
if (framebuffer.index_color_mode)
- render_target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+ framebuffer.render_target.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
else
- render_target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
-
- render_target->mode_info.bpp = active_mode_info.bits_per_pixel;
- render_target->mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel;
- render_target->mode_info.pitch = framebuffer.bytes_per_scan_line;
- render_target->mode_info.number_of_colors = 256; /* TODO: fix me. */
- render_target->mode_info.red_mask_size = active_mode_info.red_mask_size;
- render_target->mode_info.red_field_pos = active_mode_info.red_field_position;
- render_target->mode_info.green_mask_size = active_mode_info.green_mask_size;
- render_target->mode_info.green_field_pos = active_mode_info.green_field_position;
- render_target->mode_info.blue_mask_size = active_mode_info.blue_mask_size;
- render_target->mode_info.blue_field_pos = active_mode_info.blue_field_position;
- render_target->mode_info.reserved_mask_size = active_mode_info.rsvd_mask_size;
- render_target->mode_info.reserved_field_pos = active_mode_info.rsvd_field_position;
-
- render_target->mode_info.blit_format = grub_video_get_blit_format (&render_target->mode_info);
+ framebuffer.render_target.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
+
+ framebuffer.render_target.mode_info.bpp = active_mode_info.bits_per_pixel;
+ framebuffer.render_target.mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel;
+ framebuffer.render_target.mode_info.pitch = framebuffer.bytes_per_scan_line;
+ framebuffer.render_target.mode_info.number_of_colors = 256; /* TODO: fix me. */
+ framebuffer.render_target.mode_info.red_mask_size = active_mode_info.red_mask_size;
+ framebuffer.render_target.mode_info.red_field_pos = active_mode_info.red_field_position;
+ framebuffer.render_target.mode_info.green_mask_size = active_mode_info.green_mask_size;
+ framebuffer.render_target.mode_info.green_field_pos = active_mode_info.green_field_position;
+ framebuffer.render_target.mode_info.blue_mask_size = active_mode_info.blue_mask_size;
+ framebuffer.render_target.mode_info.blue_field_pos = active_mode_info.blue_field_position;
+ framebuffer.render_target.mode_info.reserved_mask_size = active_mode_info.rsvd_mask_size;
+ framebuffer.render_target.mode_info.reserved_field_pos = active_mode_info.rsvd_field_position;
+
+ framebuffer.render_target.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.render_target.mode_info);
/* Reset viewport to match new mode. */
- render_target->viewport.x = 0;
- render_target->viewport.y = 0;
- render_target->viewport.width = active_mode_info.x_resolution;
- render_target->viewport.height = active_mode_info.y_resolution;
+ framebuffer.render_target.viewport.x = 0;
+ framebuffer.render_target.viewport.y = 0;
+ framebuffer.render_target.viewport.width = active_mode_info.x_resolution;
+ framebuffer.render_target.viewport.height = active_mode_info.y_resolution;
- /* Set framebuffer pointer and mark it as non allocated. */
- render_target->is_allocated = 0;
- render_target->data = framebuffer.ptr;
+ /* Mark framebuffer memory as non allocated. */
+ framebuffer.render_target.is_allocated = 0;
/* Copy default palette to initialize emulated palette. */
- for (i = 0;
- i < (sizeof (vga_colors)
- / sizeof (struct grub_vbe_palette_data));
- i++)
- {
- framebuffer.palette[i].r = vga_colors[i].red;
- framebuffer.palette[i].g = vga_colors[i].green;
- framebuffer.palette[i].b = vga_colors[i].blue;
- framebuffer.palette[i].a = 0xFF;
- }
+ err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
+ grub_video_fbstd_colors);
+ if (err)
+ return err;
- return GRUB_ERR_NONE;
+ /* Reset render target to framebuffer one. */
+ return grub_video_fb_set_active_render_target (&framebuffer.render_target);
}
/* Couldn't found matching mode. */
@@ -569,21 +506,9 @@ grub_video_vbe_setup (unsigned int width, unsigned int height,
}
static grub_err_t
-grub_video_vbe_get_info (struct grub_video_mode_info *mode_info)
-{
- /* Copy mode info from active render target. */
- grub_memcpy (mode_info, &render_target->mode_info,
- sizeof (struct grub_video_mode_info));
-
- return GRUB_ERR_NONE;
-}
-
-static grub_err_t
grub_video_vbe_set_palette (unsigned int start, unsigned int count,
struct grub_video_palette_data *palette_data)
{
- unsigned int i;
-
if (framebuffer.index_color_mode)
{
/* TODO: Implement setting indexed color mode palette to hardware. */
@@ -595,28 +520,13 @@ grub_video_vbe_set_palette (unsigned int start, unsigned int count,
}
/* Then set color to emulated palette. */
- for (i = 0; (i < count) && ((i + start) < 256); i++)
- framebuffer.palette[start + i] = palette_data[i];
- return GRUB_ERR_NONE;
-}
-
-static grub_err_t
-grub_video_vbe_get_palette (unsigned int start, unsigned int count,
- struct grub_video_palette_data *palette_data)
-{
- unsigned int i;
-
- /* Assume that we know everything from index color palette. */
- for (i = 0; (i < count) && ((i + start) < 256); i++)
- palette_data[i] = framebuffer.palette[start + i];
-
- return GRUB_ERR_NONE;
+ return grub_video_fb_set_palette (start, count, palette_data);
}
static grub_err_t
grub_video_vbe_set_viewport (unsigned int x, unsigned int y,
- unsigned int width, unsigned int height)
+ unsigned int width, unsigned int height)
{
/* Make sure viewport is withing screen dimensions. If viewport was set
to be out of the region, mark its size as zero. */
@@ -637,832 +547,7 @@ grub_video_vbe_set_viewport (unsigned int x, unsigned int y,
if (y + height > active_mode_info.y_resolution)
height = active_mode_info.y_resolution - y;
-
- render_target->viewport.x = x;
- render_target->viewport.y = y;
- render_target->viewport.width = width;
- render_target->viewport.height = height;
-
- return GRUB_ERR_NONE;
-}
-
-static grub_err_t
-grub_video_vbe_get_viewport (unsigned int *x, unsigned int *y,
- unsigned int *width, unsigned int *height)
-{
- if (x) *x = render_target->viewport.x;
- if (y) *y = render_target->viewport.y;
- if (width) *width = render_target->viewport.width;
- if (height) *height = render_target->viewport.height;
-
- return GRUB_ERR_NONE;
-}
-
-/* Maps color name to target optimized color format. */
-static grub_video_color_t
-grub_video_vbe_map_color (grub_uint32_t color_name)
-{
- /* TODO: implement color theme mapping code. */
-
- if (color_name < 256)
- {
- if ((render_target->mode_info.mode_type
- & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
- return color_name;
- else
- {
- grub_video_color_t color;
-
- color = grub_video_vbe_map_rgb (framebuffer.palette[color_name].r,
- framebuffer.palette[color_name].g,
- framebuffer.palette[color_name].b);
-
- return color;
- }
- }
-
- return 0;
-}
-
-/* Maps RGB to target optimized color format. */
-grub_video_color_t
-grub_video_vbe_map_rgb (grub_uint8_t red, grub_uint8_t green,
- grub_uint8_t blue)
-{
- if ((render_target->mode_info.mode_type
- & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
- {
- int minindex = 0;
- int delta = 0;
- int tmp;
- int val;
- int i;
-
- /* Find best matching color. */
- for (i = 0; i < 256; i++)
- {
- val = framebuffer.palette[i].r - red;
- tmp = val * val;
- val = framebuffer.palette[i].g - green;
- tmp += val * val;
- val = framebuffer.palette[i].b - blue;
- tmp += val * val;
-
- if (i == 0)
- delta = tmp;
-
- if (tmp < delta)
- {
- delta = tmp;
- minindex = i;
- if (tmp == 0)
- break;
- }
- }
-
- return minindex;
- }
- else if ((render_target->mode_info.mode_type
- & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0)
- {
- if (red == render_target->mode_info.fg_red
- && green == render_target->mode_info.fg_green
- && blue == render_target->mode_info.fg_blue)
- return 1;
- else
- return 0;
- }
- else
- {
- grub_uint32_t value;
- grub_uint8_t alpha = 255; /* Opaque color. */
-
- red >>= 8 - render_target->mode_info.red_mask_size;
- green >>= 8 - render_target->mode_info.green_mask_size;
- blue >>= 8 - render_target->mode_info.blue_mask_size;
- alpha >>= 8 - render_target->mode_info.reserved_mask_size;
-
- value = red << render_target->mode_info.red_field_pos;
- value |= green << render_target->mode_info.green_field_pos;
- value |= blue << render_target->mode_info.blue_field_pos;
- value |= alpha << render_target->mode_info.reserved_field_pos;
-
- return value;
- }
-
-}
-
-/* Maps RGBA to target optimized color format. */
-grub_video_color_t
-grub_video_vbe_map_rgba (grub_uint8_t red, grub_uint8_t green,
- grub_uint8_t blue, grub_uint8_t alpha)
-{
- if ((render_target->mode_info.mode_type
- & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
- /* No alpha available in index color modes, just use
- same value as in only RGB modes. */
- return grub_video_vbe_map_rgb (red, green, blue);
- else if ((render_target->mode_info.mode_type
- & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0)
- {
- if (red == render_target->mode_info.fg_red
- && green == render_target->mode_info.fg_green
- && blue == render_target->mode_info.fg_blue
- && alpha == render_target->mode_info.fg_alpha)
- return 1;
- else
- return 0;
- }
- else
- {
- grub_uint32_t value;
-
- red >>= 8 - render_target->mode_info.red_mask_size;
- green >>= 8 - render_target->mode_info.green_mask_size;
- blue >>= 8 - render_target->mode_info.blue_mask_size;
- alpha >>= 8 - render_target->mode_info.reserved_mask_size;
-
- value = red << render_target->mode_info.red_field_pos;
- value |= green << render_target->mode_info.green_field_pos;
- value |= blue << render_target->mode_info.blue_field_pos;
- value |= alpha << render_target->mode_info.reserved_field_pos;
-
- return value;
- }
-}
-
-/* Splits target optimized format to components. */
-grub_err_t grub_video_vbe_unmap_color (grub_video_color_t color,
- grub_uint8_t *red, grub_uint8_t *green,
- grub_uint8_t *blue, grub_uint8_t *alpha)
-{
- struct grub_video_i386_vbeblit_info target_info;
-
- target_info.mode_info = &render_target->mode_info;
- target_info.data = render_target->data;
-
- grub_video_vbe_unmap_color_int (&target_info, color, red, green, blue, alpha);
-
- return GRUB_ERR_NONE;
-}
-
-/* Splits color in source format to components. */
-void
-grub_video_vbe_unmap_color_int (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)
-{
- 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 an out-of-bounds color, return transparent black. */
- if (color > 255)
- {
- *red = 0;
- *green = 0;
- *blue = 0;
- *alpha = 0;
- return;
- }
-
- *red = framebuffer.palette[color].r;
- *green = framebuffer.palette[color].g;
- *blue = framebuffer.palette[color].b;
- *alpha = framebuffer.palette[color].a;
- return;
- }
- else if ((mode_info->mode_type
- & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0)
- {
- if (color & 1)
- {
- *red = mode_info->fg_red;
- *green = mode_info->fg_green;
- *blue = mode_info->fg_blue;
- *alpha = mode_info->fg_alpha;
- }
- else
- {
- *red = mode_info->bg_red;
- *green = mode_info->bg_green;
- *blue = mode_info->bg_blue;
- *alpha = mode_info->bg_alpha;
- }
- }
- else
- {
- grub_uint32_t tmp;
-
- /* Get red component. */
- 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 >> 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 >> 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)
- {
- 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. */
- tmp = 255;
-
- *alpha = tmp & 0xFF;
- }
-}
-
-static grub_err_t
-grub_video_vbe_fill_rect (grub_video_color_t color, int x, int y,
- unsigned int width, unsigned int height)
-{
- 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))
- return GRUB_ERR_NONE;
- if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0))
- return GRUB_ERR_NONE;
-
- /* Do not allow drawing out of viewport. */
- if (x < 0)
- {
- width += x;
- x = 0;
- }
- if (y < 0)
- {
- height += y;
- y = 0;
- }
-
- if ((x + width) > render_target->viewport.width)
- width = render_target->viewport.width - x;
- if ((y + height) > render_target->viewport.height)
- height = render_target->viewport.height - y;
-
- /* Add viewport offset. */
- x += render_target->viewport.x;
- y += render_target->viewport.y;
-
- /* 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. Note that color is already
- mapped to target format so we can make assumptions based on that. */
- if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
- {
- grub_video_i386_vbefill_direct32 (&target, color, x, y,
- width, height);
- return GRUB_ERR_NONE;
- }
- else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
- {
- grub_video_i386_vbefill_direct32 (&target, color, x, y,
- width, height);
- return GRUB_ERR_NONE;
- }
- else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
- {
- grub_video_i386_vbefill_direct24 (&target, color, x, y,
- width, height);
- return GRUB_ERR_NONE;
- }
- else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_565)
- {
- grub_video_i386_vbefill_direct16 (&target, color, x, y,
- width, height);
- return GRUB_ERR_NONE;
- }
- else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_565)
- {
- grub_video_i386_vbefill_direct16 (&target, color, x, y,
- width, height);
- return GRUB_ERR_NONE;
- }
- else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
- {
- grub_video_i386_vbefill_direct8 (&target, color, x, y,
- width, height);
- return GRUB_ERR_NONE;
- }
-
- /* No optimized version found, use default (slow) filler. */
- grub_video_i386_vbefill (&target, color, x, y, width, height);
-
- return GRUB_ERR_NONE;
-}
-
-/* NOTE: This function assumes that given coordinates 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_RGBA_8888)
- {
- if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
- {
- grub_video_i386_vbeblit_replace_directN (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
- {
- grub_video_i386_vbeblit_replace_BGRX8888_RGBX8888 (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888)
- {
- grub_video_i386_vbeblit_replace_BGR888_RGBX8888 (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
- {
- grub_video_i386_vbeblit_replace_RGB888_RGBX8888 (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
- {
- grub_video_i386_vbeblit_replace_index_RGBX8888 (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- }
- else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
- {
- if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
- {
- grub_video_i386_vbeblit_replace_BGRX8888_RGB888 (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
- {
- grub_video_i386_vbeblit_replace_RGBX8888_RGB888 (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888)
- {
- grub_video_i386_vbeblit_replace_BGR888_RGB888 (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
- {
- grub_video_i386_vbeblit_replace_directN (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
- {
- grub_video_i386_vbeblit_replace_index_RGB888 (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- }
- else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
- {
- if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
- {
- grub_video_i386_vbeblit_replace_directN (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- }
- else 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_replace_directN (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_RGBA_8888)
- {
- if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
- {
- grub_video_i386_vbeblit_blend_BGRA8888_RGBA8888 (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
- {
- grub_video_i386_vbeblit_blend_RGBA8888_RGBA8888 (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888)
- {
- grub_video_i386_vbeblit_blend_BGR888_RGBA8888 (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
- {
- grub_video_i386_vbeblit_blend_RGB888_RGBA8888 (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
- {
- grub_video_i386_vbeblit_blend_index_RGBA8888 (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- }
- else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
- {
- /* Note: There is really no alpha information here, so blend is
- changed to replace. */
-
- if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
- {
- grub_video_i386_vbeblit_replace_BGRX8888_RGB888 (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
- {
- grub_video_i386_vbeblit_replace_RGBX8888_RGB888 (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888)
- {
- grub_video_i386_vbeblit_replace_BGR888_RGB888 (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
- {
- grub_video_i386_vbeblit_replace_directN (target, source,
- x, y, width, height,
- offset_x, offset_y);
- return;
- }
- else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
- {
- grub_video_i386_vbeblit_replace_index_RGB888 (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,
- 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;
-
- /* If we have negative coordinates, optimize drawing to minimum. */
- if (offset_x < 0)
- {
- width += offset_x;
- x -= offset_x;
- offset_x = 0;
- }
-
- if (offset_y < 0)
- {
- height += offset_y;
- y -= offset_y;
- offset_y = 0;
- }
-
- if (x < 0)
- {
- width += x;
- offset_x -= x;
- x = 0;
- }
-
- if (y < 0)
- {
- height += 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;
-
- 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;
-
- /* 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)
-{
- 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))
- return GRUB_ERR_NONE;
- if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0))
- return GRUB_ERR_NONE;
- if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0))
- return GRUB_ERR_NONE;
- if ((x + (int)source->mode_info.width) < 0)
- return GRUB_ERR_NONE;
- if ((y + (int)source->mode_info.height) < 0)
- return GRUB_ERR_NONE;
- if ((offset_x >= (int)source->mode_info.width)
- || (offset_x + (int)width < 0))
- return GRUB_ERR_NONE;
- if ((offset_y >= (int)source->mode_info.height)
- || (offset_y + (int)height < 0))
- return GRUB_ERR_NONE;
-
- /* If we have negative coordinates, optimize drawing to minimum. */
- if (offset_x < 0)
- {
- width += offset_x;
- x -= offset_x;
- offset_x = 0;
- }
-
- if (offset_y < 0)
- {
- height += offset_y;
- y -= offset_y;
- offset_y = 0;
- }
-
- if (x < 0)
- {
- width += x;
- offset_x -= x;
- x = 0;
- }
-
- if (y < 0)
- {
- height += 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;
-
- if ((offset_x + width) > source->mode_info.width)
- width = source->mode_info.width - offset_x;
- if ((offset_y + height) > source->mode_info.height)
- height = source->mode_info.height - offset_y;
-
- /* Limit drawing to source render target dimensions. */
- if (width > source->mode_info.width)
- width = source->mode_info.width;
-
- if (height > source->mode_info.height)
- height = source->mode_info.height;
-
- /* Add viewport offset. */
- x += render_target->viewport.x;
- y += render_target->viewport.y;
-
- /* 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;
-}
-
-static grub_err_t
-grub_video_vbe_scroll (grub_video_color_t color, int dx, int dy)
-{
- int width;
- int height;
- int src_x;
- int src_y;
- int dst_x;
- int dst_y;
-
- /* 1. Check if we have something to do. */
- if ((dx == 0) && (dy == 0))
- return GRUB_ERR_NONE;
-
- width = render_target->viewport.width - grub_abs (dx);
- height = render_target->viewport.height - grub_abs (dy);
-
- if (dx < 0)
- {
- src_x = render_target->viewport.x - dx;
- dst_x = render_target->viewport.x;
- }
- else
- {
- src_x = render_target->viewport.x;
- dst_x = render_target->viewport.x + dx;
- }
-
- if (dy < 0)
- {
- src_y = render_target->viewport.y - dy;
- dst_y = render_target->viewport.y;
- }
- else
- {
- src_y = render_target->viewport.y;
- dst_y = render_target->viewport.y + dy;
- }
-
- /* 2. Check if there is need to copy data. */
- if ((grub_abs (dx) < render_target->viewport.width)
- && (grub_abs (dy) < render_target->viewport.height))
- {
- /* 3. Move data in render target. */
- 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;
-
- /* Check vertical direction of the move. */
- if (dy <= 0)
- /* 3a. Move data upwards. */
- for (j = 0; j < height; 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 * target.mode_info->bytes_per_pixel);
- }
- else
- /* 3b. Move data downwards. */
- for (j = (height - 1); j >= 0; 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 * target.mode_info->bytes_per_pixel);
- }
- }
-
- /* 4. Fill empty space with specified color. In this implementation
- there might be colliding areas but at the moment there is no need
- to optimize this. */
-
- /* 4a. Fill top & bottom parts. */
- if (dy > 0)
- grub_video_vbe_fill_rect (color, 0, 0, render_target->viewport.width, dy);
- else if (dy < 0)
- {
- if (render_target->viewport.height < grub_abs (dy))
- dy = -render_target->viewport.height;
-
- grub_video_vbe_fill_rect (color, 0, render_target->viewport.height + dy,
- render_target->viewport.width, -dy);
- }
-
- /* 4b. Fill left & right parts. */
- if (dx > 0)
- grub_video_vbe_fill_rect (color, 0, 0,
- dx, render_target->viewport.height);
- else if (dx < 0)
- {
- if (render_target->viewport.width < grub_abs (dx))
- dx = -render_target->viewport.width;
-
- grub_video_vbe_fill_rect (color, render_target->viewport.width + dx, 0,
- -dx, render_target->viewport.height);
- }
-
- return GRUB_ERR_NONE;
+ return grub_video_fb_set_viewport (x, y, width, height);
}
static grub_err_t
@@ -1473,128 +558,28 @@ grub_video_vbe_swap_buffers (void)
}
static grub_err_t
-grub_video_vbe_create_render_target (struct grub_video_render_target **result,
- unsigned int width, unsigned int height,
- unsigned int mode_type __attribute__ ((unused)))
-{
- struct grub_video_render_target *target;
- unsigned int size;
-
- /* Validate arguments. */
- if ((! result)
- || (width == 0)
- || (height == 0))
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
- "invalid argument given.");
-
- /* Allocate memory for render target. */
- target = grub_malloc (sizeof (struct grub_video_render_target));
- if (! target)
- return grub_errno;
-
- /* TODO: Implement other types too.
- Currently only 32bit render targets are supported. */
-
- /* Mark render target as allocated. */
- target->is_allocated = 1;
-
- /* Maximize viewport. */
- target->viewport.x = 0;
- target->viewport.y = 0;
- target->viewport.width = width;
- target->viewport.height = height;
-
- /* Setup render target format. */
- target->mode_info.width = width;
- target->mode_info.height = height;
- target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB
- | GRUB_VIDEO_MODE_TYPE_ALPHA;
- target->mode_info.bpp = 32;
- target->mode_info.bytes_per_pixel = 4;
- target->mode_info.pitch = target->mode_info.bytes_per_pixel * width;
- target->mode_info.number_of_colors = 256; /* Emulated palette. */
- target->mode_info.red_mask_size = 8;
- target->mode_info.red_field_pos = 0;
- target->mode_info.green_mask_size = 8;
- target->mode_info.green_field_pos = 8;
- target->mode_info.blue_mask_size = 8;
- target->mode_info.blue_field_pos = 16;
- target->mode_info.reserved_mask_size = 8;
- target->mode_info.reserved_field_pos = 24;
-
- target->mode_info.blit_format = grub_video_get_blit_format (&target->mode_info);
-
- /* Calculate size needed for the data. */
- size = (width * target->mode_info.bytes_per_pixel) * height;
-
- target->data = grub_malloc (size);
- if (! target->data)
- {
- grub_free (target);
- return grub_errno;
- }
-
- /* Clear render target with black and maximum transparency. */
- grub_memset (target->data, 0, size);
-
- /* TODO: Add render target to render target list. */
-
- /* Save result to caller. */
- *result = target;
-
- return GRUB_ERR_NONE;
-}
-
-static grub_err_t
-grub_video_vbe_delete_render_target (struct grub_video_render_target *target)
-{
- /* If there is no target, then just return without error. */
- if (! target)
- return GRUB_ERR_NONE;
-
- /* TODO: Delist render target from render target list. */
-
- /* If this is software render target, free it's memory. */
- if (target->is_allocated)
- grub_free (target->data);
-
- /* Free render target. */
- grub_free (target);
-
- return GRUB_ERR_NONE;
-}
-
-static grub_err_t
grub_video_vbe_set_active_render_target (struct grub_video_render_target *target)
{
- if (target == GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER)
- {
- render_target = &framebuffer.render_target;
-
- return GRUB_ERR_NONE;
- }
+ if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY)
+ target = &framebuffer.render_target;
- if (target == GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER)
- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
- "double buffering not implemented yet.");
-
- if (! target->data)
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
- "invalid render target given.");
-
- render_target = target;
-
- return GRUB_ERR_NONE;
+ return grub_video_fb_set_active_render_target (target);
}
static grub_err_t
-grub_video_vbe_get_active_render_target (struct grub_video_render_target **target)
+grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info,
+ void **framebuf)
{
- *target = render_target;
+ grub_err_t err;
+ err = grub_video_fb_get_info (mode_info);
+ if (err)
+ return err;
+ *framebuf = (char *) framebuffer.ptr;
return GRUB_ERR_NONE;
}
+
static struct grub_video_adapter grub_video_vbe_adapter =
{
.name = "VESA BIOS Extension Video Driver",
@@ -1602,24 +587,25 @@ static struct grub_video_adapter grub_video_vbe_adapter =
.init = grub_video_vbe_init,
.fini = grub_video_vbe_fini,
.setup = grub_video_vbe_setup,
- .get_info = grub_video_vbe_get_info,
+ .get_info = grub_video_fb_get_info,
+ .get_info_and_fini = grub_video_vbe_get_info_and_fini,
.set_palette = grub_video_vbe_set_palette,
- .get_palette = grub_video_vbe_get_palette,
+ .get_palette = grub_video_fb_get_palette,
.set_viewport = grub_video_vbe_set_viewport,
- .get_viewport = grub_video_vbe_get_viewport,
- .map_color = grub_video_vbe_map_color,
- .map_rgb = grub_video_vbe_map_rgb,
- .map_rgba = grub_video_vbe_map_rgba,
- .unmap_color = grub_video_vbe_unmap_color,
- .fill_rect = grub_video_vbe_fill_rect,
- .blit_bitmap = grub_video_vbe_blit_bitmap,
- .blit_render_target = grub_video_vbe_blit_render_target,
- .scroll = grub_video_vbe_scroll,
+ .get_viewport = grub_video_fb_get_viewport,
+ .map_color = grub_video_fb_map_color,
+ .map_rgb = grub_video_fb_map_rgb,
+ .map_rgba = grub_video_fb_map_rgba,
+ .unmap_color = grub_video_fb_unmap_color,
+ .fill_rect = grub_video_fb_fill_rect,
+ .blit_bitmap = grub_video_fb_blit_bitmap,
+ .blit_render_target = grub_video_fb_blit_render_target,
+ .scroll = grub_video_fb_scroll,
.swap_buffers = grub_video_vbe_swap_buffers,
- .create_render_target = grub_video_vbe_create_render_target,
- .delete_render_target = grub_video_vbe_delete_render_target,
+ .create_render_target = grub_video_fb_create_render_target,
+ .delete_render_target = grub_video_fb_delete_render_target,
.set_active_render_target = grub_video_vbe_set_active_render_target,
- .get_active_render_target = grub_video_vbe_get_active_render_target,
+ .get_active_render_target = grub_video_fb_get_active_render_target,
.next = 0
};
diff --git a/video/video.c b/video/video.c
index c22947b..36ebfd1 100644
--- a/video/video.c
+++ b/video/video.c
@@ -93,6 +93,24 @@ grub_video_get_info (struct grub_video_mode_info *mode_info)
return grub_video_adapter_active->get_info (mode_info);
}
+/* Get information about active video mode. */
+grub_err_t
+grub_video_get_info_and_fini (struct grub_video_mode_info *mode_info,
+ void **framebuffer)
+{
+ grub_err_t err;
+
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ err = grub_video_adapter_active->get_info_and_fini (mode_info, framebuffer);
+ if (err)
+ return err;
+
+ grub_video_adapter_active = 0;
+ return GRUB_ERR_NONE;
+}
+
/* Determine optimized blitting formation for specified video mode info. */
enum grub_video_blit_format
grub_video_get_blit_format (struct grub_video_mode_info *mode_info)
@@ -380,7 +398,7 @@ grub_video_get_active_render_target (struct grub_video_render_target **target)
}
grub_err_t
-grub_video_set_mode (char *modestring,
+grub_video_set_mode (const char *modestring,
int NESTED_FUNC_ATTR (*hook) (grub_video_adapter_t p,
struct grub_video_mode_info *mode_info))
{
@@ -695,8 +713,6 @@ grub_video_set_mode (char *modestring,
/* Initialize Video API module. */
GRUB_MOD_INIT(video_video)
{
- grub_video_adapter_active = 0;
- grub_video_adapter_list = 0;
}
/* Finalize Video API module. */