* New patch for video subsystem...
@ 2006-03-02 19:28 Vesa Jääskeläinen
2006-03-03 11:49 ` Marco Gerards
2006-05-04 22:27 ` Johan Rydberg
0 siblings, 2 replies; 14+ messages in thread
From: Vesa Jääskeläinen @ 2006-03-02 19:28 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 2570 bytes --]
Hi,
Here is the newest modifications to video subsystem.
In short:
This patch adds support for video driver interface, example driver for
VBE, new video terminal (framebuffer terminal) using this video subsystem.
Longer description:
This patch implements most of the functionality described in grub's wiki
(http://grub.enbug.org/VideoSubsystem). There are still some issues left
to be implemented, but in my opinion it would be more important in this
point to get feedback about it and test how well it works on other
systems. Currently speed has not been target, only the functionality, so
some operations will take more time than would be nice. There is support
for index color and RGB modes. Video driver interface consist of video
module (video/video.c) that will forward all queries to active driver
and then interface definition (include/grub/video.h).
There is an example driver that implements VESA Bios Extension 2.0
support, only to framebuffer modes (video/i386/pc/vbe.c). It also
contains some support functionality for MultiBoot standard as it needs
some VBE fields.
There is implementaion for video terminal (term/videoterm.c) that has
basic support for rendering graphical terminal with two layers (actually
background layer is just a plain color, but other source could also be
used). Enhancing functionality the videoterm at this point is quite
easy, we just need to know what we want.
At this stage I think it would be Ok, to start to write drivers for
other architectures so we can have common video terminal.
How to use it:
In order to have graphical console, you need to first load video driver
(that would be vbe module) and then load videoterm module. After that
you will need to tell what video mode you would like to use. And last
you just initialize it with "terminal videoterm".
Example command sequence:
insmod font
font /boot/grub/unifont.pff
insmod terminal
insmod vbe
insmod videoterm
set video_mode=1024x768
terminal videoterm
How to fine tune video mode:
Handling of video_mode environment variable is a flexible one. You can
specify multiple settings at one line. If video_mode is not set, it will
use 1024x768 as a default resolution and will use highes number of
colors available. Supported options are following:
width=<value>
height=<value>
index
rgb
<width>x<height>x<depth>
And you can make combo's of those like:
set video_mode="width=1024 height=768 rgb"
It would tell driver to only look for RGB modes in that size.
Thanks,
Vesa Jääskeläinen
[-- Attachment #2: grub2-video-20060302.diff --]
[-- Type: text/plain, Size: 121402 bytes --]
diff -ruN -x '*CVS*' grub2/ChangeLog grub2.new/ChangeLog
--- grub2/ChangeLog 2006-02-09 00:42:47.000000000 +0200
+++ grub2.new/ChangeLog 2006-03-02 20:40:51.346248120 +0200
@@ -1,3 +1,102 @@
+2006-02-25 Vesa Jaaskelainen <chaac@nic.fi>
+
+ * DISTLIST: Added include/grub/video.h, term/videoterm.c,
+ video/video.c.
+ Removed term/i386/pc/vesafb.c.
+
+ * conf/i386-pc.rmk (pkgdata_MODULES): Added video.mod,
+ videoterm.mod.
+ Removed vga.mod, vesafb.mod.
+ (video_mod_SOURCES): Added.
+ (video_mod_CFLAGS): Added.
+ (video_mod_LDFLAGS): Added.
+ (videoterm_mod_SOURCES): Added.
+ (videoterm_mod_CFLAGS): Added.
+ (videoterm_mod_LDFLAGS): Added.
+ (vesafb_mod_SOURCES): Removed.
+ (vesafb_mod_CFLAGS): Removed.
+ (vesafb_mod_LDFLAGS): Removed.
+ (vga_mod_SOURCES): Removed.
+ (vga_mod_CFLAGS): Removed.
+ (vga_mod_LDFLAGS): Removed.
+
+ * font/manager.c (fill_with_default_glyph): Modified to use
+ grub_font_glyph.
+ (grub_font_get_glyph): Modified to use grub_font_glyph.
+ (fontmanager): Renamed to font_manager.
+
+ * include/grub/font.h (grub_font_glyph): Added.
+ (grub_font_get_glyph) Modified to use grub_font_glyph.
+
+ * include/grub/misc.h (grub_abs): Added as inline function.
+
+ * include/grub/i386/pc/vbe.h (GRUB_VBE_STATUS_OK): Added.
+ (GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL): Likewise.
+ (GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR): Likewise.
+ (grub_vbe_get_controller_info): Renamed to
+ grub_vbe_bios_get_controller_info.
+ (grub_vbe_get_mode_info): Renamed to grub_vbe_bios_get_mode_info.
+ (grub_vbe_set_mode): Renamed to grub_vbe_bios_set_mode.
+ (grub_vbe_get_mode): Renamed to grub_vbe_bios_get_mode.
+ (grub_vbe_set_memory_window): Renamed to
+ grub_vbe_bios_set_memory_window.
+ (grub_vbe_get_memory_window): Renamed to
+ grub_vbe_bios_get_memory_window.
+ (grub_vbe_set_scanline_length): Renamed to
+ grub_vbe_set_scanline_length.
+ (grub_vbe_get_scanline_length): Renamed to
+ grub_vbe_bios_get_scanline_length.
+ (grub_vbe_set_display_start): Renamed to
+ grub_vbe_bios_set_display_start.
+ (grub_vbe_get_display_start): Renamed to
+ grub_vbe_bios_get_display_start.
+ (grub_vbe_set_palette_data): Renamed to
+ grub_vbe_bios_set_palette_data.
+ (grub_vbe_set_pixel_rgb): Removed.
+ (grub_vbe_set_pixel_index): Likewise.
+
+ * include/grub/video.h: Added.
+
+ * kern/i386/pc/startup.S (grub_vbe_get_controller_info): Renamed to
+ grub_vbe_bios_get_controller_info.
+ (grub_vbe_get_mode_info): Renamed to grub_vbe_bios_get_mode_info.
+ (grub_vbe_set_mode): Renamed to grub_vbe_bios_set_mode.
+ (grub_vbe_get_mode): Renamed to grub_vbe_bios_get_mode.
+ (grub_vbe_set_memory_window): Renamed to
+ grub_vbe_bios_set_memory_window.
+ (grub_vbe_get_memory_window): Renamed to
+ grub_vbe_bios_get_memory_window.
+ (grub_vbe_set_scanline_length): Renamed to
+ grub_vbe_set_scanline_length.
+ (grub_vbe_get_scanline_length): Renamed to
+ grub_vbe_bios_get_scanline_length.
+ (grub_vbe_set_display_start): Renamed to
+ grub_vbe_bios_set_display_start.
+ (grub_vbe_get_display_start): Renamed to
+ grub_vbe_bios_get_display_start.
+ (grub_vbe_set_palette_data): Renamed to
+ grub_vbe_bios_set_palette_data.
+ (grub_vbe_bios_get_controller_info): Fixed problem with registers
+ getting corrupted after calling it. Added more pushes and pops.
+ (grub_vbe_bios_set_mode): Likewise.
+ (grub_vbe_bios_get_mode): Likewise.
+ (grub_vbe_bios_get_memory_window): Likewise.
+ (grub_vbe_bios_set_scanline_length): Likewise.
+ (grub_vbe_bios_get_scanline_length): Likewise.
+ (grub_vbe_bios_get_display_start): Likewise.
+ (grub_vbe_bios_set_palette_data): Likewise.
+
+ * normal/cmdline.c (cl_set_pos): Made it refresh screen, to enable
+ better visual experience to video drivers.
+ (cl_insert): Likewise.
+ (cl_delete): Likewise.
+
+ * term/videoterm.c: Added.
+
+ * video/video.c: Added
+
+ * video/i386/pc/vbe.c: Refactored to new video subsystem.
+
2006-02-01 Yoshinori K. Okuji <okuji@enbug.org>
* boot/i386/pc/boot.S (general_error): Before looping, try INT
diff -ruN -x '*CVS*' grub2/DISTLIST grub2.new/DISTLIST
--- grub2/DISTLIST 2005-12-26 01:04:28.000000000 +0200
+++ grub2.new/DISTLIST 2006-02-25 13:29:16.000000000 +0200
@@ -106,6 +106,7 @@
include/grub/terminfo.h
include/grub/tparm.h
include/grub/types.h
+include/grub/video.h
include/grub/i386/setjmp.h
include/grub/i386/types.h
include/grub/i386/pc/biosdisk.h
@@ -208,6 +209,7 @@
partmap/sun.c
term/terminfo.c
term/tparm.c
+term/videoterm.c
term/i386/pc/console.c
term/i386/pc/serial.c
term/i386/pc/vesafb.c
@@ -229,4 +231,5 @@
util/i386/pc/misc.c
util/powerpc/ieee1275/grub-mkimage.c
util/powerpc/ieee1275/misc.c
+video/video.c
video/i386/pc/vbe.c
diff -ruN -x '*CVS*' grub2/conf/i386-pc.rmk grub2.new/conf/i386-pc.rmk
--- grub2/conf/i386-pc.rmk 2005-12-26 01:04:29.000000000 +0200
+++ grub2.new/conf/i386-pc.rmk 2006-02-25 14:23:10.000000000 +0200
@@ -113,9 +113,9 @@
grub_install_SOURCES = util/i386/pc/grub-install.in
# Modules.
-pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod vga.mod \
+pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod \
_multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod \
- vbe.mod vesafb.mod vbetest.mod vbeinfo.mod play.mod
+ vbe.mod vbetest.mod vbeinfo.mod video.mod videoterm.mod play.mod
# For _chain.mod.
_chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -157,11 +157,6 @@
halt_mod_CFLAGS = $(COMMON_CFLAGS)
halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
-# For vga.mod.
-vga_mod_SOURCES = term/i386/pc/vga.c
-vga_mod_CFLAGS = $(COMMON_CFLAGS)
-vga_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
# For serial.mod.
serial_mod_SOURCES = term/i386/pc/serial.c
serial_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -182,11 +177,6 @@
vbe_mod_CFLAGS = $(COMMON_CFLAGS)
vbe_mod_LDFLAGS = $(COMMON_LDFLAGS)
-# For vesafb.mod.
-vesafb_mod_SOURCES = term/i386/pc/vesafb.c
-vesafb_mod_CFLAGS = $(COMMON_CFLAGS)
-vesafb_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
# For vbeinfo.mod.
vbeinfo_mod_SOURCES = commands/i386/pc/vbeinfo.c
vbeinfo_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -202,4 +192,14 @@
play_mod_CFLAGS = $(COMMON_CFLAGS)
play_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For video.mod.
+video_mod_SOURCES = video/video.c
+video_mod_CFLAGS = $(COMMON_CFLAGS)
+video_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For videoterm.mod.
+videoterm_mod_SOURCES = term/videoterm.c
+videoterm_mod_CFLAGS = $(COMMON_CFLAGS)
+videoterm_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff -ruN -x '*CVS*' grub2/font/manager.c grub2.new/font/manager.c
--- grub2/font/manager.c 2005-11-13 17:47:09.000000000 +0200
+++ grub2.new/font/manager.c 2006-02-25 14:16:16.000000000 +0200
@@ -24,6 +24,7 @@
#include <grub/types.h>
#include <grub/mm.h>
#include <grub/font.h>
+//#include <grub/gzio.h>
struct entry
{
@@ -50,6 +51,7 @@
struct font *font = 0;
file = grub_file_open (filename);
+ //file = grub_gzfile_open (filename, 1);
if (! file)
goto fail;
@@ -151,26 +153,27 @@
/* Set the glyph to something stupid. */
static void
-fill_with_default_glyph (unsigned char bitmap[32], unsigned *width)
+fill_with_default_glyph (grub_font_glyph_t glyph)
{
- if (bitmap)
- {
- unsigned i;
+ unsigned i;
- for (i = 0; i < 16; i++)
- bitmap[i] = (i & 1) ? 0x55 : 0xaa;
- }
-
- *width = 1;
+ for (i = 0; i < 16; i++)
+ glyph->bitmap[i] = (i & 1) ? 0x55 : 0xaa;
+
+ glyph->char_width = 1;
+ glyph->width = glyph->char_width * 8;
+ glyph->height = 16;
+ glyph->baseline = (16*3)/4;
}
/* Get a glyph corresponding to the codepoint CODE. Always fill BITMAP
and WIDTH with something, even if no glyph is found. */
int
grub_font_get_glyph (grub_uint32_t code,
- unsigned char bitmap[32], unsigned *width)
+ grub_font_glyph_t glyph)
{
struct font *font;
+ grub_uint8_t bitmap[32];
/* FIXME: It is necessary to cache glyphs! */
@@ -183,12 +186,19 @@
if (offset)
{
grub_uint32_t w;
+ grub_uint8_t x;
+ grub_uint8_t y;
+ grub_uint32_t len;
+
+ /* Make sure we can find glyphs for error messages. Push active
+ error message to error stack and reset error message. */
+ grub_error_push ();
grub_file_seek (font->file, offset);
- if (grub_file_read (font->file, (char *) &w, 4) != 4)
+ if ((len = grub_file_read (font->file, (char *) &w, 4)) != 4)
{
- remove_font (font);
- goto restart;
+ remove_font (font);
+ goto restart;
}
w = grub_le_to_cpu32 (w);
@@ -206,14 +216,30 @@
remove_font (font);
goto restart;
}
-
- *width = w;
+
+ /* Temporary workaround, fix font bitmap. */
+ for (y = 0; y < 16; y++)
+ {
+ for (x = 0; x < w; x++)
+ {
+ glyph->bitmap[y * w + x] = bitmap[x * 16 + y];
+ }
+ }
+
+ glyph->char_width = w;
+ glyph->width = glyph->char_width * 8;
+ glyph->height = 16;
+ glyph->baseline = (16*3)/4;
+
+ /* Restore old error message. */
+ grub_error_pop ();
+
return 1;
}
}
/* Uggh... No font was found. */
- fill_with_default_glyph (bitmap, width);
+ fill_with_default_glyph (glyph);
return 0;
}
@@ -232,7 +258,7 @@
return 0;
}
-GRUB_MOD_INIT(fontmanager)
+GRUB_MOD_INIT(font_manager)
{
(void) mod; /* Stop warning. */
grub_register_command ("font", font_command, GRUB_COMMAND_FLAG_BOTH,
@@ -240,7 +266,7 @@
"Specify one or more font files to display.", 0);
}
-GRUB_MOD_FINI(fontmanager)
+GRUB_MOD_FINI(font_manager)
{
grub_unregister_command ("font");
}
diff -ruN -x '*CVS*' grub2/include/grub/font.h grub2.new/include/grub/font.h
--- grub2/include/grub/font.h 2004-04-04 16:46:00.000000000 +0300
+++ grub2.new/include/grub/font.h 2006-02-25 13:43:08.000000000 +0200
@@ -24,7 +24,31 @@
#define GRUB_FONT_MAGIC "PPF\x7f"
+struct grub_font_glyph
+{
+ /* Glyph width in pixels. */
+ grub_uint8_t width;
+
+ /* Glyph height in pixels. */
+ grub_uint8_t height;
+
+ /* Glyph width in characters. */
+ grub_uint8_t char_width;
+
+ /* Glyph baseline position in pixels (from up). */
+ grub_uint8_t baseline;
+
+ /* Glyph bitmap data array of bytes in ((width + 7) / 8) * height.
+ Bitmap is formulated by height scanlines, each scanline having
+ width number of pixels. Pixels are coded as bits, value 1 meaning
+ of opaque pixel and 0 is transparent. If width does not fit byte
+ boundary, it will be padded with 0 to make it fit. */
+ grub_uint8_t bitmap[32];
+};
+
+typedef struct grub_font_glyph *grub_font_glyph_t;
+
int grub_font_get_glyph (grub_uint32_t code,
- unsigned char bitmap[32], unsigned *width);
+ grub_font_glyph_t glyph);
#endif /* ! GRUB_FONT_HEADER */
diff -ruN -x '*CVS*' grub2/include/grub/i386/pc/vbe.h grub2.new/include/grub/i386/pc/vbe.h
--- grub2/include/grub/i386/pc/vbe.h 2005-08-16 21:34:17.000000000 +0300
+++ grub2.new/include/grub/i386/pc/vbe.h 2006-03-02 17:42:44.342055256 +0200
@@ -27,6 +27,13 @@
/* Default video mode to be used. */
#define GRUB_VBE_DEFAULT_VIDEO_MODE 0x101
+/* VBE status codes. */
+#define GRUB_VBE_STATUS_OK 0x004f
+
+/* VBE memory model types. */
+#define GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL 0x04
+#define GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR 0x06
+
/* Note:
Please refer to VESA BIOS Extension 3.0 Specification for more descriptive
@@ -147,45 +154,45 @@
/* Prototypes for kernel real mode thunks. */
/* Call VESA BIOS 0x4f00 to get VBE Controller Information, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_controller_info) (struct grub_vbe_info_block *controller_info);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_controller_info) (struct grub_vbe_info_block *controller_info);
/* Call VESA BIOS 0x4f01 to get VBE Mode Information, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_mode_info) (grub_uint32_t mode,
- struct grub_vbe_mode_info_block *mode_info);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_mode_info) (grub_uint32_t mode,
+ struct grub_vbe_mode_info_block *mode_info);
/* Call VESA BIOS 0x4f02 to set video mode, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_mode) (grub_uint32_t mode,
- struct grub_vbe_crtc_info_block *crtc_info);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_mode) (grub_uint32_t mode,
+ struct grub_vbe_crtc_info_block *crtc_info);
/* Call VESA BIOS 0x4f03 to return current VBE Mode, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_mode) (grub_uint32_t *mode);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_mode) (grub_uint32_t *mode);
/* Call VESA BIOS 0x4f05 to set memory window, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_memory_window) (grub_uint32_t window,
- grub_uint32_t position);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_memory_window) (grub_uint32_t window,
+ grub_uint32_t position);
/* Call VESA BIOS 0x4f05 to return memory window, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_memory_window) (grub_uint32_t window,
- grub_uint32_t *position);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_memory_window) (grub_uint32_t window,
+ grub_uint32_t *position);
/* Call VESA BIOS 0x4f06 to set scanline length (in bytes), return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_scanline_length) (grub_uint32_t length);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_scanline_length) (grub_uint32_t length);
/* Call VESA BIOS 0x4f06 to return scanline length (in bytes), return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_scanline_length) (grub_uint32_t *length);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_scanline_length) (grub_uint32_t *length);
/* Call VESA BIOS 0x4f07 to set display start, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_display_start) (grub_uint32_t x,
- grub_uint32_t y);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_display_start) (grub_uint32_t x,
+ grub_uint32_t y);
/* Call VESA BIOS 0x4f07 to get display start, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_display_start) (grub_uint32_t *x,
- grub_uint32_t *y);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_display_start) (grub_uint32_t *x,
+ grub_uint32_t *y);
/* Call VESA BIOS 0x4f09 to set palette data, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_palette_data) (grub_uint32_t color_count,
- grub_uint32_t start_index,
- struct grub_vbe_palette_data *palette_data);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_palette_data) (grub_uint32_t color_count,
+ grub_uint32_t start_index,
+ struct grub_vbe_palette_data *palette_data);
/* Prototypes for helper functions. */
@@ -195,13 +202,5 @@
grub_err_t grub_vbe_get_video_mode (grub_uint32_t *mode);
grub_err_t grub_vbe_get_video_mode_info (grub_uint32_t mode,
struct grub_vbe_mode_info_block *mode_info);
-void grub_vbe_set_pixel_rgb (grub_uint32_t x,
- grub_uint32_t y,
- grub_uint8_t red,
- grub_uint8_t green,
- grub_uint8_t blue);
-void grub_vbe_set_pixel_index (grub_uint32_t x,
- grub_uint32_t y,
- grub_uint8_t color);
#endif /* ! GRUB_VBE_MACHINE_HEADER */
diff -ruN -x '*CVS*' grub2/include/grub/misc.h grub2.new/include/grub/misc.h
--- grub2/include/grub/misc.h 2005-10-24 13:23:46.000000000 +0300
+++ grub2.new/include/grub/misc.h 2006-03-02 20:40:08.611744752 +0200
@@ -76,4 +76,14 @@
const grub_uint8_t *src,
grub_size_t size);
+/* Inline functions. */
+static inline unsigned int
+grub_abs (int x)
+{
+ if (x < 0)
+ return (unsigned int)(-x);
+ else
+ return (unsigned int)x;
+}
+
#endif /* ! GRUB_MISC_HEADER */
diff -ruN -x '*CVS*' grub2/include/grub/video.h grub2.new/include/grub/video.h
--- grub2/include/grub/video.h 1970-01-01 02:00:00.000000000 +0200
+++ grub2.new/include/grub/video.h 2006-03-02 15:33:32.650225312 +0200
@@ -0,0 +1,300 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2003,2005 Free Software Foundation, Inc.
+ *
+ * GRUB is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef GRUB_VIDEO_HEADER
+#define GRUB_VIDEO_HEADER 1
+
+#include <grub/err.h>
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+typedef grub_uint32_t grub_color_t;
+struct grub_video_render_target;
+
+/* Defines used to describe video mode or rendering target. */
+#define GRUB_VIDEO_MODE_TYPE_ALPHA 0x00000008
+#define GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED 0x00000004
+#define GRUB_VIDEO_MODE_TYPE_INDEX_COLOR 0x00000002
+#define GRUB_VIDEO_MODE_TYPE_RGB 0x00000001
+
+/* Defines used to mask flags. */
+#define GRUB_VIDEO_MODE_TYPE_COLOR_MASK 0x00000003
+
+/* Defined predefined render targets. */
+#define GRUB_VIDEO_RENDER_TARGET_DISPLAY ((struct grub_video_render_target *) 0)
+#define GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER ((struct grub_video_render_target *) 0)
+#define GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER ((struct grub_video_render_target *) 1)
+
+struct grub_video_mode_info {
+ /* Width of the screen. */
+ grub_uint32_t width;
+
+ /* Height of the screen. */
+ grub_uint32_t height;
+
+ /* Mode type bitmask. Contains information like is it Index color or
+ RGB mode. */
+ grub_uint32_t mode_type;
+
+ /* Bits per pixel. */
+ grub_uint32_t bpp;
+
+ /* Bytes per pixel. */
+ grub_uint32_t bytes_per_pixel;
+
+ /* Pitch of one scanline. How many bytes there are for scanline. */
+ grub_uint32_t pitch;
+
+ /* In index color mode, number of colors. In RGB mode this is 256. */
+ grub_uint32_t number_of_colors;
+
+ /* How many bits are reserved for red color. */
+ grub_uint32_t red_mask_size;
+
+ /* What is location of red color bits. In Index Color mode, this is 0. */
+ grub_uint32_t red_field_pos;
+
+ /* How many bits are reserved for green color. */
+ grub_uint32_t green_mask_size;
+
+ /* What is location of green color bits. In Index Color mode, this is 0. */
+ grub_uint32_t green_field_pos;
+
+ /* How many bits are reserved for blue color. */
+ grub_uint32_t blue_mask_size;
+
+ /* What is location of blue color bits. In Index Color mode, this is 0. */
+ grub_uint32_t blue_field_pos;
+
+ /* How many bits are reserved in color. */
+ grub_uint32_t reserved_mask_size;
+
+ /* What is location of reserved color bits. In Index Color mode,
+ this is 0. */
+ grub_uint32_t reserved_field_pos;
+};
+
+struct grub_video_render_target {
+ /* Copy of the screen's mode info structure, except that width, height and
+ mode_type has been re-adjusted to requested render target settings. */
+ struct grub_video_mode_info mode_info;
+
+ struct {
+ unsigned int x;
+ unsigned int y;
+ unsigned int width;
+ unsigned int height;
+ } viewport;
+
+ /* Indicates wether the data has been allocated by us and must be freed
+ when render target is destroyed. */
+ int is_allocated;
+
+ /* Pointer to data. Can either be in video card memory or in local host's
+ memory. */
+ void *data;
+};
+
+struct grub_video_palette_data {
+ grub_uint8_t r; /* Red color value (0-255). */
+ grub_uint8_t g; /* Green color value (0-255). */
+ grub_uint8_t b; /* Blue color value (0-255). */
+ grub_uint8_t a; /* Reserved bits value (0-255). */
+};
+
+struct grub_font_glyph;
+struct grub_video_bitmap;
+
+struct grub_video_adapter
+{
+ /* The video adapter name. */
+ const char *name;
+
+ /* Initialize the video adapter. */
+ grub_err_t (*init) (void);
+
+ /* Clean up the video adapter. */
+ grub_err_t (*fini) (void);
+
+ grub_err_t (*setup) (unsigned int width,
+ unsigned int height,
+ unsigned int mode_type);
+
+ grub_err_t (*get_info) (struct grub_video_mode_info * mode_info);
+
+ grub_err_t (*set_palette) (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data);
+
+ grub_err_t (*get_palette) (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data);
+
+ grub_err_t (*set_viewport) (unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height);
+
+ grub_err_t (*get_viewport) (unsigned int * x,
+ unsigned int * y,
+ unsigned int * width,
+ unsigned int * height);
+
+ grub_color_t (*map_color) (grub_uint32_t color_name);
+
+ grub_color_t (*map_rgb) (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue);
+
+ grub_color_t (*map_rgba) (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue,
+ grub_uint8_t alpha);
+
+ grub_err_t (*fill_rect) (grub_color_t color,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height);
+
+ grub_err_t (*blit_glyph) (struct grub_font_glyph * glyph,
+ grub_color_t color,
+ int x,
+ int y);
+
+ grub_err_t (*blit_bitmap) (struct grub_video_bitmap * bitmap,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height);
+
+ grub_err_t (*blit_render_target) (struct grub_video_render_target * source,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height);
+
+ grub_err_t (*scroll) (grub_color_t color,
+ int dx,
+ int dy);
+
+ grub_err_t (*swap_buffers) (void);
+
+ grub_err_t (*create_render_target) (struct grub_video_render_target * * result,
+ unsigned int mode_type,
+ unsigned int width,
+ unsigned int height);
+
+ grub_err_t (*delete_render_target) (struct grub_video_render_target * target);
+
+ grub_err_t (*set_active_render_target) (struct grub_video_render_target * target);
+
+ /* The next video adapter. */
+ struct grub_video_adapter *next;
+};
+typedef struct grub_video_adapter *grub_video_adapter_t;
+
+void EXPORT_FUNC(grub_video_register) (grub_video_adapter_t adapter);
+void EXPORT_FUNC(grub_video_unregister) (grub_video_adapter_t adapter);
+void EXPORT_FUNC(grub_video_iterate) (int (*hook) (grub_video_adapter_t adapter));
+
+grub_err_t EXPORT_FUNC(grub_video_setup) (unsigned int width,
+ unsigned int height,
+ unsigned int mode_type);
+
+grub_err_t EXPORT_FUNC(grub_video_restore) (void);
+
+grub_err_t EXPORT_FUNC(grub_video_get_info) (struct grub_video_mode_info * mode_info);
+
+grub_err_t EXPORT_FUNC(grub_video_set_palette) (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data);
+
+grub_err_t EXPORT_FUNC(grub_video_get_palette) (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data);
+
+grub_err_t EXPORT_FUNC(grub_video_set_viewport) (unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_get_viewport) (unsigned int * x,
+ unsigned int * y,
+ unsigned int * width,
+ unsigned int * height);
+
+grub_color_t EXPORT_FUNC(grub_video_map_color) (grub_uint32_t color_name);
+
+grub_color_t EXPORT_FUNC(grub_video_map_rgb) (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue);
+
+grub_color_t EXPORT_FUNC(grub_video_map_rgba) (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue,
+ grub_uint8_t alpha);
+
+grub_err_t EXPORT_FUNC(grub_video_fill_rect) (grub_color_t color,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_blit_glyph) (struct grub_font_glyph * glyph,
+ grub_color_t color,
+ int x,
+ int y);
+
+grub_err_t EXPORT_FUNC(grub_video_blit_bitmap) (struct grub_video_bitmap * bitmap,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_blit_render_target) (struct grub_video_render_target * source,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_scroll) (grub_color_t color,
+ int dx,
+ int dy);
+
+grub_err_t EXPORT_FUNC(grub_video_swap_buffers) (void);
+
+grub_err_t EXPORT_FUNC(grub_video_create_render_target) (struct grub_video_render_target * * result,
+ unsigned int mode_type,
+ unsigned int width,
+ unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_delete_render_target) (struct grub_video_render_target * target);
+
+grub_err_t EXPORT_FUNC(grub_video_set_active_render_target) (struct grub_video_render_target * target);
+
+#endif /* ! GRUB_VIDEO_HEADER */
diff -ruN -x '*CVS*' grub2/kern/i386/pc/startup.S grub2.new/kern/i386/pc/startup.S
--- grub2/kern/i386/pc/startup.S 2005-10-15 20:28:36.000000000 +0300
+++ grub2.new/kern/i386/pc/startup.S 2006-03-02 14:14:06.760358584 +0200
@@ -1758,14 +1758,15 @@
ret
/*
- * grub_vbe_status_t grub_vbe_get_controller_info (struct grub_vbe_info_block *controller_info)
+ * grub_vbe_bios_status_t grub_vbe_get_controller_info (struct grub_vbe_info_block *controller_info)
*
* Register allocations for parameters:
* %eax *controller_info
*/
-FUNCTION(grub_vbe_get_controller_info)
+FUNCTION(grub_vbe_bios_get_controller_info)
pushl %ebp
pushl %edi
+ pushl %edx
movw %ax, %di /* Store *controller_info to %edx:%di. */
xorw %ax, %ax
@@ -1791,19 +1792,20 @@
movl %edx, %eax
andl $0x0FFFF, %eax /* Return value in %eax. */
+ pop %edx
popl %edi
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_get_mode_info (grub_uint32_t mode,
- * struct grub_vbe_mode_info_block *mode_info)
+ * grub_vbe_status_t grub_vbe_bios_get_mode_info (grub_uint32_t mode,
+ * struct grub_vbe_mode_info_block *mode_info)
*
* Register allocations for parameters:
* %eax mode
* %edx *mode_info
*/
-FUNCTION(grub_vbe_get_mode_info)
+FUNCTION(grub_vbe_bios_get_mode_info)
pushl %ebp
pushl %edi
@@ -1837,16 +1839,17 @@
ret
/*
- * grub_vbe_status_t grub_vbe_set_mode (grub_uint32_t mode,
- * struct grub_vbe_crtc_info_block *crtc_info)
+ * grub_vbe_status_t grub_vbe_bios_set_mode (grub_uint32_t mode,
+ * struct grub_vbe_crtc_info_block *crtc_info)
*
* Register allocations for parameters:
* %eax mode
* %edx *crtc_info
*/
-FUNCTION(grub_vbe_set_mode)
+FUNCTION(grub_vbe_bios_set_mode)
pushl %ebp
pushl %ebx
+ pushl %edi
movl %eax, %ebx /* Store mode in %ebx. */
@@ -1874,19 +1877,22 @@
movw %dx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edi
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_get_mode (grub_uint32_t *mode)
+ * grub_vbe_status_t grub_vbe_bios_get_mode (grub_uint32_t *mode)
*
* Register allocations for parameters:
* %eax *mode
*/
-FUNCTION(grub_vbe_get_mode)
+FUNCTION(grub_vbe_bios_get_mode)
pushl %ebp
pushl %ebx
+ pushl %edi
+ pushl %edx
pushl %eax /* Push *mode to stack. */
call prot_to_real
@@ -1907,19 +1913,21 @@
movw %dx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edx
+ popl %edi
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_set_memory_window (grub_uint32_t window,
- * grub_uint32_t position);
+ * grub_vbe_status_t grub_vbe_bios_set_memory_window (grub_uint32_t window,
+ * grub_uint32_t position);
*
* Register allocations for parameters:
* %eax window
* %edx position
*/
-FUNCTION(grub_vbe_set_memory_window)
+FUNCTION(grub_vbe_bios_set_memory_window)
pushl %ebp
pushl %ebx
@@ -1945,16 +1953,17 @@
ret
/*
- * grub_vbe_status_t grub_vbe_get_memory_window (grub_uint32_t window,
- * grub_uint32_t *position);
+ * grub_vbe_status_t grub_vbe_bios_get_memory_window (grub_uint32_t window,
+ * grub_uint32_t *position);
*
* Register allocations for parameters:
* %eax window
* %edx *position
*/
-FUNCTION(grub_vbe_get_memory_window)
+FUNCTION(grub_vbe_bios_get_memory_window)
pushl %ebp
pushl %ebx
+ pushl %edi
pushl %edx /* Push *position to stack. */
movl %eax, %ebx /* Store window in %ebx. */
@@ -1979,19 +1988,21 @@
movw %bx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edi
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_set_scanline_length (grub_uint32_t length)
+ * grub_vbe_status_t grub_vbe_bios_set_scanline_length (grub_uint32_t length)
*
* Register allocations for parameters:
* %eax length
*/
-FUNCTION(grub_vbe_set_scanline_length)
+FUNCTION(grub_vbe_bios_set_scanline_length)
pushl %ebp
pushl %ebx
+ pushl %edx
movl %eax, %ecx /* Store length in %ecx. */
@@ -2010,19 +2021,21 @@
movw %dx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edx
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_get_scanline_length (grub_uint32_t *length)
+ * grub_vbe_status_t grub_vbe_bios_get_scanline_length (grub_uint32_t *length)
*
* Register allocations for parameters:
* %eax *length
*/
-FUNCTION(grub_vbe_get_scanline_length)
+FUNCTION(grub_vbe_bios_get_scanline_length)
pushl %ebp
pushl %ebx
+ pushl %edi
pushl %edx /* Push *length to stack. */
call prot_to_real
@@ -2044,19 +2057,20 @@
movw %dx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edi
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_set_display_start (grub_uint32_t x,
- * grub_uint32_t y)
+ * grub_vbe_status_t grub_vbe_bios_set_display_start (grub_uint32_t x,
+ * grub_uint32_t y)
*
* Register allocations for parameters:
* %eax x
* %edx y
*/
-FUNCTION(grub_vbe_set_display_start)
+FUNCTION(grub_vbe_bios_set_display_start)
pushl %ebp
pushl %ebx
@@ -2083,16 +2097,17 @@
ret
/*
- * grub_vbe_status_t grub_vbe_get_display_start (grub_uint32_t *x,
- * grub_uint32_t *y)
+ * grub_vbe_status_t grub_vbe_bios_get_display_start (grub_uint32_t *x,
+ * grub_uint32_t *y)
*
* Register allocations for parameters:
* %eax *x
* %edx *y
*/
-FUNCTION(grub_vbe_get_display_start)
+FUNCTION(grub_vbe_bios_get_display_start)
pushl %ebp
pushl %ebx
+ pushl %edi
pushl %eax /* Push *x to stack. */
pushl %edx /* Push *y to stack. */
@@ -2119,23 +2134,25 @@
movw %bx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edi
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_set_palette_data (grub_uint32_t color_count,
- * grub_uint32_t start_index,
- * struct grub_vbe_palette_data *palette_data)
+ * grub_vbe_status_t grub_vbe_bios_set_palette_data (grub_uint32_t color_count,
+ * grub_uint32_t start_index,
+ * struct grub_vbe_palette_data *palette_data)
*
* Register allocations for parameters:
* %eax color_count
* %edx start_index
* %ecx *palette_data
*/
-FUNCTION(grub_vbe_set_palette_data)
+FUNCTION(grub_vbe_bios_set_palette_data)
pushl %ebp
pushl %ebx
+ pushl %edi
movl %eax, %ebx /* Store color_count in %ebx. */
@@ -2165,6 +2182,7 @@
movw %dx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edi
popl %ebx
popl %ebp
ret
diff -ruN -x '*CVS*' grub2/normal/cmdline.c grub2.new/normal/cmdline.c
--- grub2/normal/cmdline.c 2005-08-28 20:01:16.000000000 +0300
+++ grub2.new/normal/cmdline.c 2006-02-25 14:50:44.000000000 +0200
@@ -231,6 +231,8 @@
xpos = (plen + lpos) % 79;
ypos = ystart + (plen + lpos) / 79;
grub_gotoxy (xpos, ypos);
+
+ grub_refresh ();
}
void cl_print (int pos, int c)
@@ -271,6 +273,8 @@
cl_print (lpos - len, echo_char);
cl_set_pos ();
}
+
+ grub_refresh ();
}
void cl_delete (unsigned len)
@@ -290,6 +294,8 @@
cl_print (lpos, echo_char);
cl_set_pos ();
}
+
+ grub_refresh ();
}
plen = grub_strlen (prompt);
diff -ruN -x '*CVS*' grub2/term/videoterm.c grub2.new/term/videoterm.c
--- grub2/term/videoterm.c 1970-01-01 02:00:00.000000000 +0200
+++ grub2.new/term/videoterm.c 2006-03-02 15:32:11.991487304 +0200
@@ -0,0 +1,873 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/machine/memory.h>
+#include <grub/machine/console.h>
+#include <grub/term.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/font.h>
+#include <grub/arg.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+#include <grub/video.h>
+
+#define DEFAULT_CHAR_WIDTH 8
+#define DEFAULT_CHAR_HEIGHT 16
+
+#define DEFAULT_FG_COLOR 0x0a
+#define DEFAULT_BG_COLOR 0x00
+#define DEFAULT_CURSOR_COLOR 0x0f
+
+struct grub_dirty_region
+{
+ int top_left_x;
+ int top_left_y;
+ int bottom_right_x;
+ int bottom_right_y;
+};
+
+struct grub_colored_char
+{
+ /* An Unicode codepoint. */
+ grub_uint32_t code;
+
+ /* Color values. */
+ grub_color_t fg_color;
+ grub_color_t bg_color;
+
+ /* The width of this character minus one. */
+ unsigned char width;
+
+ /* The column index of this character. */
+ unsigned char index;
+};
+
+struct grub_virtual_screen
+{
+ /* Dimensions of the virual screen. */
+ grub_uint32_t width;
+ grub_uint32_t height;
+
+ /* Offset in the display. */
+ grub_uint32_t offset_x;
+ grub_uint32_t offset_y;
+
+ /* TTY Character sizes. */
+ grub_uint32_t char_width;
+ grub_uint32_t char_height;
+
+ /* Virtual screen TTY size. */
+ grub_uint32_t columns;
+ grub_uint32_t rows;
+
+ /* Current cursor details. */
+ grub_uint32_t cursor_x;
+ grub_uint32_t cursor_y;
+ grub_uint8_t cursor_state;
+ grub_color_t fg_color_setting;
+ grub_color_t bg_color_setting;
+ grub_color_t fg_color;
+ grub_color_t bg_color;
+ grub_color_t cursor_color;
+
+ /* Text buffer for virual screen. Contains (columns * rows) number
+ of entries. */
+ struct grub_colored_char *text_buffer;
+};
+
+/* Make seure text buffer is not marked as allocated. */
+static struct grub_virtual_screen virtual_screen =
+ {
+ .text_buffer = 0
+ };
+
+static grub_dl_t my_mod;
+static struct grub_video_mode_info mode_info;
+
+static struct grub_video_render_target *text_layer = 0;
+
+static struct grub_dirty_region dirty_region;
+
+static void dirty_region_reset (void);
+
+static int dirty_region_is_empty (void);
+
+static void dirty_region_add (int x,
+ int y,
+ unsigned int width,
+ unsigned int height);
+
+static void
+grub_virtual_screen_free (void)
+{
+ /* If virtual screen has been allocated, free it. */
+ if (virtual_screen.text_buffer != 0)
+ grub_free (virtual_screen.text_buffer);
+
+ /* Reset virtual screen data. */
+ grub_memset (&virtual_screen, 0, sizeof (virtual_screen));
+
+ /* Free render targets. */
+ grub_video_delete_render_target (text_layer);
+ text_layer = 0;
+}
+
+static grub_err_t
+grub_virtual_screen_setup (grub_uint32_t x,
+ grub_uint32_t y,
+ grub_uint32_t width,
+ grub_uint32_t height)
+{
+ /* Free old virtual screen. */
+ grub_virtual_screen_free ();
+
+ /* Initialize with default data. */
+ virtual_screen.width = width;
+ virtual_screen.height = height;
+ virtual_screen.offset_x = x;
+ virtual_screen.offset_y = y;
+ virtual_screen.char_width = DEFAULT_CHAR_WIDTH;
+ virtual_screen.char_height = DEFAULT_CHAR_HEIGHT;
+ virtual_screen.cursor_x = 0;
+ virtual_screen.cursor_y = 0;
+ virtual_screen.cursor_state = 1;
+
+ /* Calculate size of text buffer. */
+ virtual_screen.columns = virtual_screen.width / virtual_screen.char_width;
+ virtual_screen.rows = virtual_screen.height / virtual_screen.char_height;
+
+ /* Allocate memory for text buffer. */
+ virtual_screen.text_buffer =
+ (struct grub_colored_char *) grub_malloc (virtual_screen.columns
+ * virtual_screen.rows
+ * sizeof (*virtual_screen.text_buffer));
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Cleare new render target for text layer. */
+ grub_video_create_render_target (&text_layer,
+ GRUB_VIDEO_MODE_TYPE_RGB
+ | GRUB_VIDEO_MODE_TYPE_ALPHA,
+ virtual_screen.width,
+ virtual_screen.height);
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* As we want to have colors compatible with rendering target,
+ we can only have those after mode is initialized. */
+ grub_video_set_active_render_target (text_layer);
+
+ virtual_screen.fg_color_setting = grub_video_map_color (DEFAULT_FG_COLOR);
+ virtual_screen.bg_color_setting = grub_video_map_color (DEFAULT_BG_COLOR);
+ virtual_screen.fg_color = virtual_screen.fg_color_setting;
+ virtual_screen.bg_color = virtual_screen.bg_color_setting;
+ virtual_screen.cursor_color = grub_video_map_color (DEFAULT_CURSOR_COLOR);
+
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ return grub_errno;
+}
+
+static grub_err_t
+grub_videoterm_init (void)
+{
+ char *modevar;
+ int width = 1024;
+ int height = 768;
+ int flags = 0;
+ grub_color_t color;
+
+ /* Parse video_mode environment variable if set. */
+ modevar = grub_env_get ("video_mode");
+ if (modevar)
+ {
+ char *tmp;
+ char *param;
+ char *value;
+
+ /* Take copy of env.var. as we don't want to modify that. */
+ tmp = grub_strdup (modevar);
+ modevar = tmp;
+
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Skip whitespace. */
+ while (grub_isspace (*tmp))
+ {
+ tmp++;
+ }
+
+ /* Initialize token holders. */
+ param = tmp;
+ value = NULL;
+
+ /* Loop until all characters have been handled. */
+ while (1)
+ {
+ if (grub_isspace (*tmp) || (*tmp == 0))
+ {
+ /* If there are more variables, mark seperator with NUL. */
+ if (*tmp != 0)
+ {
+ *tmp++ = 0;
+ }
+
+ /* Analyze setting. */
+
+ /* Handle width=<number>. */
+ if ((grub_strcmp (param, "width") == 0) && (value != NULL))
+ {
+ width = grub_strtoul (value, 0, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_errno;
+ }
+ }
+
+ /* Handle height=<number>. */
+ if ((grub_strcmp (param, "height") == 0) && (value != NULL))
+ {
+ height = grub_strtoul (value, 0, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_errno;
+ }
+ }
+
+ /* Handle rgb. Used to request RGB mode. */
+ if ((grub_strcmp (param, "rgb") == 0) && (value == NULL))
+ {
+ flags &= ~GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+ flags |= GRUB_VIDEO_MODE_TYPE_RGB;
+ }
+
+ /* Handle index. Used to request index color mode. */
+ if ((grub_strcmp (param, "index") == 0) && (value == NULL))
+ {
+ flags &= ~GRUB_VIDEO_MODE_TYPE_RGB;
+ flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+ }
+
+ /* Handle double. Used to request double buffering mode. */
+ if ((grub_strcmp (param, "double") == 0) && (value == NULL))
+ {
+ flags |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
+ }
+
+ /* Handle <width>x<height>[x<depth>]*/
+ if (grub_isdigit (param[0]))
+ {
+ /* Find width value. */
+ value = param;
+ param = grub_strchr(param, 'x');
+ if (param == NULL)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "Invalid argument: %s\n",
+ param);
+ }
+
+ *param = 0;
+ param++;
+
+ width = grub_strtoul (value, 0, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_errno;
+ }
+
+ /* Find height value. */
+ value = param;
+ param = grub_strchr(param, 'x');
+ if (param == NULL)
+ {
+ height = grub_strtoul (value, 0, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_errno;
+ }
+ }
+ else
+ {
+ /* We have optional color depth value. */
+ *param = 0;
+ param++;
+
+ height = grub_strtoul (value, 0, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_errno;
+ }
+
+ /* Convert color depth value. */
+ value = param;
+#if 0
+ depth = grub_strtoul (value, 0, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_errno;
+ }
+#endif
+ }
+ }
+
+ /* Skip whitespace. */
+ while (grub_isspace (*tmp))
+ {
+ tmp++;
+ }
+
+ /* Check if we are at end of string. */
+ if (*tmp == 0)
+ {
+ break;
+ }
+
+ /* Initialize token holders. */
+ param = tmp;
+ value = NULL;
+ }
+
+ /* Check if there is value seperator. */
+ if (*tmp == '=')
+ {
+ *tmp++ = 0;
+ value = tmp;
+ }
+
+ /* Advance to next character. */
+ tmp++;
+ }
+
+ /* Free memory. */
+ grub_free (modevar);
+ }
+
+ /* Intialize user requested mode. */
+ if (grub_video_setup (width, height, flags) != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Figure out what mode we ended up. */
+ if (grub_video_get_info (&mode_info) != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Make sure screen is black. */
+ color = grub_video_map_rgb (0, 0, 0);
+ grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
+
+ /* Leave borders for virtual screen. */
+ width = mode_info.width - (2 * 10);
+ height = mode_info.height - (2 * 10);
+
+ /* Create virtual screen. */
+ if (grub_virtual_screen_setup (10,
+ 10,
+ width,
+ height) != GRUB_ERR_NONE)
+ {
+ grub_video_restore ();
+ return grub_errno;
+ }
+
+ /* Mark whole screen as dirty. */
+ dirty_region_reset ();
+ dirty_region_add (0, 0, mode_info.width, mode_info.height);
+
+ return (grub_errno = GRUB_ERR_NONE);
+}
+
+static grub_err_t
+grub_videoterm_fini (void)
+{
+ grub_virtual_screen_free ();
+
+ grub_video_restore ();
+
+ return GRUB_ERR_NONE;
+}
+
+static void
+redraw_screen_rect (unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height)
+{
+ grub_color_t color;
+
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ /* Render background layer. */
+ color = virtual_screen.bg_color;
+ grub_video_fill_rect (color, x, y, width, height);
+
+ /* Render text layer. */
+ grub_video_blit_render_target (text_layer,
+ x,
+ y,
+ x - virtual_screen.offset_x,
+ y - virtual_screen.offset_y,
+ width,
+ height);
+}
+
+static void
+dirty_region_reset (void)
+{
+ dirty_region.top_left_x = -1;
+ dirty_region.top_left_y = -1;
+ dirty_region.bottom_right_x = -1;
+ dirty_region.bottom_right_y = -1;
+}
+
+static int
+dirty_region_is_empty (void)
+{
+ if ((dirty_region.top_left_x == -1)
+ || (dirty_region.top_left_y == -1)
+ || (dirty_region.bottom_right_x == -1)
+ || (dirty_region.bottom_right_y == -1))
+ {
+ return 1;
+ }
+ return 0;
+}
+
+static void
+dirty_region_add (int x, int y, unsigned int width, unsigned int height)
+{
+ if ((width == 0) || (height == 0))
+ return;
+
+ if (dirty_region_is_empty ())
+ {
+ dirty_region.top_left_x = x;
+ dirty_region.top_left_y = y;
+ dirty_region.bottom_right_x = x + width - 1;
+ dirty_region.bottom_right_y = y + height - 1;
+ }
+ else
+ {
+ if (x < dirty_region.top_left_x)
+ {
+ dirty_region.top_left_x = x;
+ }
+ if (y < dirty_region.top_left_y)
+ {
+ dirty_region.top_left_y = y;
+ }
+ if ((x + (int)width - 1) > dirty_region.bottom_right_x)
+ {
+ dirty_region.bottom_right_x = x + width - 1;
+ }
+ if ((y + (int)height - 1) > dirty_region.bottom_right_y)
+ {
+ dirty_region.bottom_right_y = y + height - 1;
+ }
+ }
+}
+
+static void
+dirty_region_add_virtualscreen (void)
+{
+ /* Mark virtual screen as dirty. */
+ dirty_region_add (virtual_screen.offset_x, virtual_screen.offset_y,
+ virtual_screen.width, virtual_screen.height);
+}
+
+
+static void
+dirty_region_redraw (void)
+{
+ int x;
+ int y;
+ int width;
+ int height;
+
+ if (dirty_region_is_empty ())
+ return;
+
+ x = dirty_region.top_left_x;
+ y = dirty_region.top_left_y;
+
+ width = dirty_region.bottom_right_x - x + 1;
+ height = dirty_region.bottom_right_y - y + 1;
+
+ redraw_screen_rect (x, y, width, height);
+
+ dirty_region_reset ();
+}
+
+static void
+write_char (void)
+{
+ struct grub_colored_char *p;
+ struct grub_font_glyph glyph;
+ grub_uint32_t x, y;
+
+ grub_video_set_active_render_target (text_layer);
+
+ p = (virtual_screen.text_buffer
+ + virtual_screen.cursor_x
+ + (virtual_screen.cursor_y * virtual_screen.columns));
+
+ p -= p->index;
+
+ grub_uint32_t color, bgcolor;
+
+ grub_font_get_glyph (p->code, &glyph);
+
+ color = p->fg_color;
+ bgcolor = p->bg_color;
+
+ x = virtual_screen.cursor_x * virtual_screen.char_width;
+ y = virtual_screen.cursor_y * virtual_screen.char_height;
+
+ grub_video_fill_rect (bgcolor, x, y, glyph.width, glyph.height);
+
+ grub_video_blit_glyph (&glyph, color, x, y);
+
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ dirty_region_add (virtual_screen.offset_x + x,
+ virtual_screen.offset_y + y,
+ glyph.width,
+ glyph.height);
+}
+
+static void
+write_cursor (void)
+{
+ grub_uint32_t x;
+ grub_uint32_t y;
+ grub_uint32_t width;
+ grub_uint32_t height;
+ grub_uint32_t color;
+
+ grub_video_set_active_render_target (text_layer);
+
+ x = virtual_screen.cursor_x * virtual_screen.char_width;
+ y = ((virtual_screen.cursor_y + 1) * virtual_screen.char_height) - 3;
+ width = virtual_screen.char_width;
+ height = 2;
+
+ color = virtual_screen.cursor_color;
+ grub_video_fill_rect (color, x, y, width, height);
+
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ dirty_region_add (virtual_screen.offset_x + x,
+ virtual_screen.offset_y + y,
+ width,
+ height);
+}
+
+static void
+scroll_up (void)
+{
+ grub_uint32_t i;
+ grub_uint32_t color;
+
+ /* Scroll text buffer with one line to up. */
+ grub_memmove (virtual_screen.text_buffer,
+ virtual_screen.text_buffer + virtual_screen.columns,
+ sizeof (*virtual_screen.text_buffer)
+ * virtual_screen.columns
+ * (virtual_screen.rows - 1));
+
+ /* Clear last line in text buffer. */
+ for (i = virtual_screen.columns * (virtual_screen.rows - 1);
+ i < virtual_screen.columns * virtual_screen.rows;
+ i++)
+ {
+ virtual_screen.text_buffer[i].code = ' ';
+ virtual_screen.text_buffer[i].fg_color = virtual_screen.fg_color;
+ virtual_screen.text_buffer[i].bg_color = virtual_screen.bg_color;
+ virtual_screen.text_buffer[i].width = 0;
+ virtual_screen.text_buffer[i].index = 0;
+ }
+
+ /* Scroll physcal 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);
+
+ dirty_region_add_virtualscreen ();
+}
+
+static void
+grub_videoterm_putchar (grub_uint32_t c)
+{
+ if (c == '\a')
+ /* FIXME */
+ return;
+
+ if (c == '\b' || c == '\n' || c == '\r')
+ {
+ /* Erase current cursor, if any. */
+ if (virtual_screen.cursor_state)
+ write_char ();
+
+ switch (c)
+ {
+ case '\b':
+ if (virtual_screen.cursor_x > 0)
+ virtual_screen.cursor_x--;
+ break;
+
+ case '\n':
+ if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
+ scroll_up ();
+ else
+ virtual_screen.cursor_y++;
+ break;
+
+ case '\r':
+ virtual_screen.cursor_x = 0;
+ break;
+ }
+
+ if (virtual_screen.cursor_state)
+ write_cursor ();
+ }
+ else
+ {
+ struct grub_font_glyph glyph;
+ struct grub_colored_char *p;
+
+ grub_font_get_glyph (c, &glyph);
+
+ if (virtual_screen.cursor_x + glyph.char_width > virtual_screen.columns)
+ grub_putchar ('\n');
+
+ p = (virtual_screen.text_buffer +
+ virtual_screen.cursor_x +
+ virtual_screen.cursor_y * virtual_screen.columns);
+ p->code = c;
+ p->fg_color = virtual_screen.fg_color;
+ p->bg_color = virtual_screen.bg_color;
+ p->width = glyph.char_width - 1;
+ p->index = 0;
+
+ if (glyph.char_width > 1)
+ {
+ unsigned i;
+
+ for (i = 1; i < glyph.char_width; i++)
+ {
+ p[i].code = ' ';
+ p[i].width = glyph.char_width - 1;
+ p[i].index = i;
+ }
+ }
+
+ write_char ();
+
+ 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++;
+ }
+
+ if (virtual_screen.cursor_state)
+ write_cursor ();
+ }
+}
+
+static grub_ssize_t
+grub_videoterm_getcharwidth (grub_uint32_t c)
+{
+ struct grub_font_glyph glyph;
+
+ if (! grub_font_get_glyph (c, &glyph))
+ return 0;
+
+ return glyph.char_width;
+}
+
+static grub_uint16_t
+grub_virtual_screen_getwh (void)
+{
+ return (virtual_screen.columns << 8) | virtual_screen.rows;
+}
+
+static grub_uint16_t
+grub_virtual_screen_getxy (void)
+{
+ return ((virtual_screen.cursor_x << 8) | virtual_screen.cursor_y);
+}
+
+static void
+grub_videoterm_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+ if (x >= virtual_screen.columns || y >= virtual_screen.rows)
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)",
+ (unsigned) x, (unsigned) y);
+ return;
+ }
+
+ if (virtual_screen.cursor_state)
+ write_char ();
+
+ virtual_screen.cursor_x = x;
+ virtual_screen.cursor_y = y;
+
+ if (virtual_screen.cursor_state)
+ write_cursor ();
+}
+
+static void
+grub_virtual_screen_cls (void)
+{
+ grub_uint32_t i;
+
+ for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++)
+ {
+ virtual_screen.text_buffer[i].code = ' ';
+ virtual_screen.text_buffer[i].fg_color = virtual_screen.fg_color;
+ virtual_screen.text_buffer[i].bg_color = virtual_screen.bg_color;
+ virtual_screen.text_buffer[i].width = 0;
+ virtual_screen.text_buffer[i].index = 0;
+ }
+
+ virtual_screen.cursor_x = virtual_screen.cursor_y = 0;
+}
+
+static void
+grub_videoterm_cls (void)
+{
+ grub_uint32_t color;
+
+ grub_video_set_active_render_target (text_layer);
+ grub_virtual_screen_cls ();
+
+ 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);
+
+ /* Redraw only virtual screen. */
+ dirty_region_add_virtualscreen ();
+}
+
+static void
+grub_virtual_screen_setcolorstate (grub_term_color_state state)
+{
+ switch (state)
+ {
+ case GRUB_TERM_COLOR_STANDARD:
+ case GRUB_TERM_COLOR_NORMAL:
+ virtual_screen.fg_color = virtual_screen.fg_color_setting;
+ virtual_screen.bg_color = virtual_screen.bg_color_setting;
+ break;
+ case GRUB_TERM_COLOR_HIGHLIGHT:
+ virtual_screen.fg_color = virtual_screen.bg_color_setting;
+ virtual_screen.bg_color = virtual_screen.fg_color_setting;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+grub_virtual_screen_setcolor (grub_uint8_t normal_color __attribute__ ((unused)),
+ grub_uint8_t highlight_color __attribute__ ((unused)))
+{
+ virtual_screen.fg_color_setting = grub_video_map_color (normal_color);
+ virtual_screen.bg_color_setting = grub_video_map_color (highlight_color);
+}
+
+static void
+grub_videoterm_setcursor (int on)
+{
+ if (virtual_screen.cursor_state != on)
+ {
+ if (virtual_screen.cursor_state)
+ write_char ();
+ else
+ write_cursor ();
+
+ virtual_screen.cursor_state = on;
+ }
+}
+
+static void
+grub_videoterm_refresh (void)
+{
+ /* Redraw only changed regions. */
+ dirty_region_redraw ();
+}
+
+static struct grub_term grub_video_term =
+ {
+ .name = "videoterm",
+ .init = grub_videoterm_init,
+ .fini = grub_videoterm_fini,
+ .putchar = grub_videoterm_putchar,
+ .getcharwidth = grub_videoterm_getcharwidth,
+ .checkkey = grub_console_checkkey,
+ .getkey = grub_console_getkey,
+ .getwh = grub_virtual_screen_getwh,
+ .getxy = grub_virtual_screen_getxy,
+ .gotoxy = grub_videoterm_gotoxy,
+ .cls = grub_videoterm_cls,
+ .setcolorstate = grub_virtual_screen_setcolorstate,
+ .setcolor = grub_virtual_screen_setcolor,
+ .setcursor = grub_videoterm_setcursor,
+ .refresh = grub_videoterm_refresh,
+ .flags = 0,
+ .next = 0
+ };
+
+GRUB_MOD_INIT(term_videoterm)
+{
+ my_mod = mod;
+ grub_term_register (&grub_video_term);
+}
+
+GRUB_MOD_FINI(term_videoterm)
+{
+ grub_term_unregister (&grub_video_term);
+}
Files grub2/unifont.pff and grub2.new/unifont.pff differ
diff -ruN -x '*CVS*' grub2/video/i386/pc/vbe.c grub2.new/video/i386/pc/vbe.c
--- grub2/video/i386/pc/vbe.c 2005-09-19 00:04:41.000000000 +0300
+++ grub2.new/video/i386/pc/vbe.c 2006-03-02 20:35:43.719014568 +0200
@@ -1,6 +1,6 @@
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2005 Free Software Foundation, Inc.
+ * Copyright (C) 2005-2006 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,6 +17,11 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+/* General TODO's:
+ - Implement mode optimized operations and automatically select best
+
+*/
+
#include <grub/err.h>
#include <grub/machine/memory.h>
#include <grub/machine/vga.h>
@@ -31,6 +36,7 @@
#include <grub/arg.h>
#include <grub/mm.h>
#include <grub/env.h>
+#include <grub/video.h>
/* Specify "standard" VGA palette, some video cards may
need this and this will also be used when using RGB modes. */
@@ -57,15 +63,51 @@
};
static int vbe_detected = -1;
-static int index_color_mode = 0;
static struct grub_vbe_info_block controller_info;
static struct grub_vbe_mode_info_block active_mode_info;
-static grub_uint32_t active_mode = 0;
+static struct {
+ struct grub_video_render_target render_target;
+
+ unsigned int bytes_per_scan_line;
+ unsigned int bytes_per_pixel;
+ grub_uint32_t active_mode;
+ grub_uint8_t *ptr;
+ int index_color_mode;
+ struct grub_video_palette_data palette[256];
+} framebuffer;
+
+static struct grub_video_render_target *render_target;
+
+static grub_dl_t my_mod = 0;
+
+static grub_color_t
+grub_video_vbe_map_rgb (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue);
-static grub_uint8_t *framebuffer = 0;
-static grub_uint32_t bytes_per_scan_line = 0;
+static grub_color_t
+grub_video_vbe_map_rgba (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue,
+ grub_uint8_t alpha);
+
+static void
+grub_video_vbe_unmap_color (struct grub_video_render_target * source,
+ grub_color_t color,
+ grub_uint8_t * red,
+ grub_uint8_t * green,
+ grub_uint8_t * blue,
+ grub_uint8_t * alpha);
+
+
+static void *
+real2pm (grub_vbe_farptr_t ptr)
+{
+ return (void *) ((((unsigned long) ptr & 0xFFFF0000) >> 12UL)
+ + ((unsigned long) ptr & 0x0000FFFF));
+}
grub_err_t
grub_vbe_probe (struct grub_vbe_info_block *info_block)
@@ -99,7 +141,7 @@
vbe_ib->signature[3] = '2';
/* Try to get controller info block. */
- status = grub_vbe_get_controller_info (vbe_ib);
+ status = grub_vbe_bios_get_controller_info (vbe_ib);
if (status == 0x004F)
{
/* Copy it for later usage. */
@@ -128,11 +170,13 @@
grub_uint32_t old_mode;
/* Make sure that VBE is supported. */
- if (grub_vbe_probe (0) != GRUB_ERR_NONE)
+ grub_vbe_probe (0);
+ if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* Try to get mode info. */
- if (grub_vbe_get_video_mode_info (mode, &active_mode_info) != GRUB_ERR_NONE)
+ grub_vbe_get_video_mode_info (mode, &active_mode_info);
+ if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* For all VESA BIOS modes, force linear frame buffer. */
@@ -144,12 +188,12 @@
/* Determine frame buffer pixel format. */
switch (active_mode_info.memory_model)
{
- case 0x04:
- index_color_mode = 1;
+ case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL:
+ framebuffer.index_color_mode = 1;
break;
- case 0x06:
- index_color_mode = 0;
+ case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR:
+ framebuffer.index_color_mode = 0;
break;
default:
@@ -160,51 +204,68 @@
}
/* Get current mode. */
- if (grub_vbe_get_video_mode (&old_mode) != GRUB_ERR_NONE)
+ grub_vbe_get_video_mode (&old_mode);
+ if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* Try to set video mode. */
- status = grub_vbe_set_mode (mode, 0);
- if (status != 0x004F)
+ status = grub_vbe_bios_set_mode (mode, 0);
+ if (status != GRUB_VBE_STATUS_OK)
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot set VBE mode %x", mode);
/* Save information for later usage. */
- active_mode = mode;
+ framebuffer.active_mode = mode;
if (mode < 0x100)
{
/* If this is not a VESA mode, guess address. */
- framebuffer = (grub_uint8_t *) 0xA0000;
- index_color_mode = 1;
+ framebuffer.ptr = (grub_uint8_t *) 0xA0000;
+ framebuffer.index_color_mode = 1;
}
else
{
- framebuffer = (grub_uint8_t *) active_mode_info.phys_base_addr;
+ framebuffer.ptr = (grub_uint8_t *) active_mode_info.phys_base_addr;
if (controller_info.version >= 0x300)
- bytes_per_scan_line = active_mode_info.lin_bytes_per_scan_line;
+ framebuffer.bytes_per_scan_line = active_mode_info.lin_bytes_per_scan_line;
else
- bytes_per_scan_line = active_mode_info.bytes_per_scan_line;
+ framebuffer.bytes_per_scan_line = active_mode_info.bytes_per_scan_line;
+ }
+
+ /* Calculate bytes_per_pixel value. */
+ switch(active_mode_info.bits_per_pixel)
+ {
+ case 32: framebuffer.bytes_per_pixel = 4; break;
+ case 24: framebuffer.bytes_per_pixel = 3; break;
+ case 16: framebuffer.bytes_per_pixel = 2; break;
+ case 15: framebuffer.bytes_per_pixel = 2; break;
+ case 8: framebuffer.bytes_per_pixel = 1; break;
+ default:
+ grub_vbe_bios_set_mode (old_mode, 0);
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ "cannot set VBE mode %x",
+ mode);
+ break;
}
/* If video mode is in indexed color, setup default VGA palette. */
- if (index_color_mode)
+ if (framebuffer.index_color_mode)
{
struct grub_vbe_palette_data *palette
= (struct grub_vbe_palette_data *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
/* Make sure that the BIOS can reach the palette. */
grub_memcpy (palette, vga_colors, sizeof (vga_colors));
- status = grub_vbe_set_palette_data (sizeof (vga_colors)
- / sizeof (struct grub_vbe_palette_data),
- 0,
- palette);
+ status = grub_vbe_bios_set_palette_data (sizeof (vga_colors)
+ / sizeof (struct grub_vbe_palette_data),
+ 0,
+ palette);
/* For now, ignore the status. Not sure if this is fatal. */
#if 0
- if (status != 0x004F)
+ if (status != GRUB_VBE_STATUS_OK)
{
- grub_vbe_set_mode (old_mode, 0);
+ grub_vbe_bios_set_mode (old_mode, 0);
return grub_error (GRUB_ERR_BAD_DEVICE,
"cannot set the default VGA palette");
}
@@ -224,12 +285,13 @@
grub_vbe_status_t status;
/* Make sure that VBE is supported. */
- if (grub_vbe_probe (0) != GRUB_ERR_NONE)
+ grub_vbe_probe (0);
+ if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* Try to query current mode from VESA BIOS. */
- status = grub_vbe_get_mode (mode);
- if (status != 0x004F)
+ status = grub_vbe_bios_get_mode (mode);
+ if (status != GRUB_VBE_STATUS_OK)
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot get current VBE mode");
return GRUB_ERR_NONE;
@@ -244,15 +306,16 @@
grub_vbe_status_t status;
/* Make sure that VBE is supported. */
- if (grub_vbe_probe (0) != GRUB_ERR_NONE)
+ grub_vbe_probe (0);
+ if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* If mode is not VESA mode, skip mode info query. */
if (mode >= 0x100)
{
/* Try to get mode info from VESA BIOS. */
- status = grub_vbe_get_mode_info (mode, mi_tmp);
- if (status != 0x004F)
+ status = grub_vbe_bios_get_mode_info (mode, mi_tmp);
+ if (status != GRUB_VBE_STATUS_OK)
return grub_error (GRUB_ERR_BAD_DEVICE,
"cannot get information on the mode %x", mode);
@@ -266,60 +329,75 @@
return GRUB_ERR_NONE;
}
-void
-grub_vbe_set_pixel_rgb (grub_uint32_t x,
- grub_uint32_t y,
- grub_uint8_t red,
- grub_uint8_t green,
- grub_uint8_t blue)
+static grub_uint8_t *
+grub_video_vbe_get_video_ptr (struct grub_video_render_target * source,
+ grub_uint32_t x,
+ grub_uint32_t y)
{
- grub_uint32_t value;
+ grub_uint8_t *ptr = 0;
+
+ switch (source->mode_info.bpp)
+ {
+ case 32:
+ ptr = (grub_uint8_t *)source->data
+ + y * source->mode_info.pitch
+ + x * 4;
+ break;
- if (x >= active_mode_info.x_resolution)
- return;
+ case 24:
+ ptr = (grub_uint8_t *)source->data
+ + y * source->mode_info.pitch
+ + x * 3;
+ break;
- if (y >= active_mode_info.y_resolution)
- return;
+ case 16:
+ case 15:
+ ptr = (grub_uint8_t *)source->data
+ + y * source->mode_info.pitch
+ + x * 2;
+ break;
- if (controller_info.version >= 0x300)
- {
- red >>= 8 - active_mode_info.lin_red_mask_size;
- green >>= 8 - active_mode_info.lin_green_mask_size;
- blue >>= 8 - active_mode_info.lin_blue_mask_size;
-
- value = red << active_mode_info.lin_red_field_position;
- value |= green << active_mode_info.lin_green_field_position;
- value |= blue << active_mode_info.lin_blue_field_position;
+ case 8:
+ ptr = (grub_uint8_t *)source->data
+ + y * source->mode_info.pitch
+ + x;
+ break;
}
- else
- {
- red >>= 8 - active_mode_info.red_mask_size;
- green >>= 8 - active_mode_info.green_mask_size;
- blue >>= 8 - active_mode_info.blue_mask_size;
+
+ return ptr;
+}
- value = red << active_mode_info.red_field_position;
- value |= green << active_mode_info.green_field_position;
- value |= blue << active_mode_info.blue_field_position;
- }
+static void
+grub_video_vbe_draw_pixel (grub_uint32_t x,
+ grub_uint32_t y,
+ grub_color_t color)
+{
+ if (x >= render_target->mode_info.width)
+ return;
+
+ if (y >= render_target->mode_info.height)
+ return;
- switch (active_mode_info.bits_per_pixel)
+ switch (render_target->mode_info.bpp)
{
case 32:
{
- grub_uint32_t *ptr = (grub_uint32_t *) (framebuffer
- + y * bytes_per_scan_line
- + x * 4);
+ grub_uint32_t *ptr;
+
+ ptr = (grub_uint32_t *)grub_video_vbe_get_video_ptr (render_target,
+ x,
+ y);
- *ptr = value;
+ *ptr = color;
}
break;
case 24:
{
- grub_uint8_t *ptr = (grub_uint8_t *) (framebuffer
- + y * bytes_per_scan_line
- + x * 3);
- grub_uint8_t *ptr2 = (grub_uint8_t *) &value;
+ grub_uint8_t *ptr;
+ grub_uint8_t *ptr2 = (grub_uint8_t *) &color;
+
+ ptr = grub_video_vbe_get_video_ptr (render_target, x, y);
ptr[0] = ptr2[0];
ptr[1] = ptr2[1];
@@ -330,11 +408,25 @@
case 16:
case 15:
{
- grub_uint16_t *ptr = (grub_uint16_t *) (framebuffer
- + y * bytes_per_scan_line
- + x * 2);
+ grub_uint16_t *ptr;
+
+ ptr = (grub_uint16_t *)grub_video_vbe_get_video_ptr (render_target,
+ x,
+ y);
- *ptr = (grub_uint16_t) (value & 0xFFFF);
+ *ptr = (grub_uint16_t) (color & 0xFFFF);
+ }
+ break;
+
+ case 8:
+ {
+ grub_uint8_t *ptr;
+
+ ptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (render_target,
+ x,
+ y);
+
+ *ptr = (grub_uint8_t) (color & 0xFF);
}
break;
@@ -343,44 +435,1203 @@
}
}
-void
-grub_vbe_set_pixel_index (grub_uint32_t x,
- grub_uint32_t y,
- grub_uint8_t color)
+static grub_color_t
+grub_video_vbe_get_pixel (struct grub_video_render_target * source,
+ grub_uint32_t x,
+ grub_uint32_t y)
{
- if (x >= active_mode_info.x_resolution)
- return;
+ grub_color_t color = 0;
+
+ if (x >= source->mode_info.width)
+ return 0;
- if (y >= active_mode_info.y_resolution)
- return;
+ if (y >= source->mode_info.height)
+ return 0;
- if (index_color_mode == 1)
+ switch (source->mode_info.bpp)
{
- grub_uint8_t *ptr = (grub_uint8_t *) (framebuffer
- + y * bytes_per_scan_line
- + x);
+ case 32:
+ {
+ color = *(grub_uint32_t *)grub_video_vbe_get_video_ptr (source, x, y);
+ }
+ break;
+
+ case 24:
+ {
+ grub_uint8_t *ptr;
+ ptr = grub_video_vbe_get_video_ptr (source, x, y);
+ color = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
+ }
+ break;
+
+ 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_uint32_t initial_mode = 0;
+static grub_uint32_t mode_in_use = 0x55aa;
+static grub_uint16_t *mode_list = 0;
+
+static grub_err_t
+grub_video_vbe_init (void)
+{
+ grub_uint16_t *rm_mode_list;
+ grub_uint16_t *p;
+ grub_size_t mode_list_size;
+ struct grub_vbe_info_block info_block;
- *ptr = color;
+ /* Check if there is adapter present.
+
+ Firmware note: There has been a report that some cards store video mode
+ list in temporary memory. So we must first use vbe probe to get
+ refreshed information to receive valid pointers and data, and then
+ copy this information to somewhere safe. */
+ grub_vbe_probe (&info_block);
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Copy modelist to local memory. */
+ p = rm_mode_list = real2pm (info_block.video_mode_ptr);
+ while(*p++ != 0xFFFF)
+ ;
+
+ mode_list_size = (grub_addr_t) p - (grub_addr_t) rm_mode_list;
+ mode_list = grub_malloc (mode_list_size);
+ if (! mode_list)
+ return grub_errno;
+ grub_memcpy (mode_list, rm_mode_list, mode_list_size);
+
+ /* Adapter could be found, figure out initial video mode. */
+ grub_vbe_get_video_mode (&initial_mode);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free allocated resources. */
+ grub_free (mode_list);
+ mode_list = 0;
+
+ return grub_errno;
+ }
+
+ /* Reset frame buffer and render target variables. */
+ grub_memset (&framebuffer, 0, sizeof(framebuffer));
+ render_target = &framebuffer.render_target;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_fini (void)
+{
+ grub_vbe_status_t status;
+
+ /* Restore old video mode. */
+ status = grub_vbe_bios_set_mode (initial_mode, 0);
+ if (status != GRUB_VBE_STATUS_OK)
+ {
+ /* TODO: Decide, is this something we want to do. */
+ return grub_errno;
+ }
+
+ /* TODO: Free any resources allocated by driver. */
+ grub_free (mode_list);
+ mode_list = 0;
+
+ /* TODO: destroy render targets. */
+
+ /* Return success to caller. */
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_setup (unsigned int width,
+ unsigned int height,
+ unsigned int mode_type)
+{
+ grub_uint16_t *p;
+ struct grub_vbe_mode_info_block mode_info;
+ struct grub_vbe_mode_info_block best_mode_info;
+ grub_uint32_t best_mode = 0;
+ unsigned int i;
+
+ /* Walk thru mode list and try to find matching mode. */
+ for (p = mode_list; *p != 0xFFFF; p++)
+ {
+ grub_uint32_t mode = *p;
+
+ grub_vbe_get_video_mode_info (mode, &mode_info);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Could not retrieve mode info, retreat. */
+ grub_errno = GRUB_ERR_NONE;
+ break;
+ }
+
+ if ((mode_info.mode_attributes & 0x001) == 0)
+ /* If not available, skip it. */
+ continue;
+
+ if ((mode_info.mode_attributes & 0x002) == 0)
+ /* Not enough information. */
+ continue;
+
+ if ((mode_info.mode_attributes & 0x008) == 0)
+ /* Monochrome is unusable. */
+ continue;
+
+ if ((mode_info.mode_attributes & 0x080) == 0)
+ /* We support only linear frame buffer modes. */
+ continue;
+
+ if ((mode_info.mode_attributes & 0x010) == 0)
+ /* We allow only graphical modes. */
+ continue;
+
+ if ((mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL)
+ && (mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR))
+ /* Not compatible memory model. */
+ continue;
+
+ if ((mode_info.x_resolution != width)
+ || (mode_info.y_resolution != height))
+ /* Non matching resolution. */
+ continue;
+
+ /* Check if user requested RGB or index color mode. */
+ if ((mode_type & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0)
+ {
+ if (((mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ && (mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL))
+ /* Requested only index color modes. */
+ continue;
+
+ if (((mode_type & GRUB_VIDEO_MODE_TYPE_RGB) != 0)
+ && (mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR))
+ /* Requested only RGB modes. */
+ continue;
+ }
+
+ /* Select mode with most number of bits per pixel. */
+ if (best_mode != 0)
+ {
+ if (mode_info.bits_per_pixel < best_mode_info.bits_per_pixel)
+ continue;
+ }
+
+ /* Save so far best mode information for later use. */
+ best_mode = mode;
+ grub_memcpy (&best_mode_info, &mode_info, sizeof (mode_info));
+ }
+
+ /* Try to initialize best mode found. */
+ if (best_mode != 0)
+ {
+ /* If this fails, then we have mode selection heuristics problem,
+ or adapter failure. */
+ grub_vbe_set_video_mode (best_mode, &active_mode_info);
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Now we are happily in requested video mode. Cache some info
+ in order to fasten later operations. */
+ mode_in_use = best_mode;
+
+ /* Reset render target to framebuffer one. */
+ render_target = &framebuffer.render_target;
+
+ /* Fill mode info details in framebuffer's render target. */
+ render_target->mode_info.width = active_mode_info.x_resolution;
+ render_target->mode_info.height = active_mode_info.y_resolution;
+
+ render_target->mode_info.width = active_mode_info.x_resolution;
+ render_target->mode_info.height = active_mode_info.y_resolution;
+
+ if (framebuffer.index_color_mode)
+ {
+ render_target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+ }
+ else
+ {
+ render_target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
+ }
+
+ render_target->mode_info.bpp = active_mode_info.bits_per_pixel;
+ render_target->mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel;
+ render_target->mode_info.pitch = framebuffer.bytes_per_scan_line;
+ render_target->mode_info.number_of_colors = 256; /* TODO: fix me. */
+ render_target->mode_info.red_mask_size = active_mode_info.red_mask_size;
+ render_target->mode_info.red_field_pos = active_mode_info.red_field_position;
+ render_target->mode_info.green_mask_size = active_mode_info.green_mask_size;
+ render_target->mode_info.green_field_pos = active_mode_info.green_field_position;
+ render_target->mode_info.blue_mask_size = active_mode_info.blue_mask_size;
+ render_target->mode_info.blue_field_pos = active_mode_info.blue_field_position;
+ render_target->mode_info.reserved_mask_size = active_mode_info.rsvd_mask_size;
+ render_target->mode_info.reserved_field_pos = active_mode_info.rsvd_field_position;
+
+ /* Reset viewport to match new mode. */
+ render_target->viewport.x = 0;
+ render_target->viewport.y = 0;
+ render_target->viewport.width = active_mode_info.x_resolution;
+ render_target->viewport.height = active_mode_info.y_resolution;
+
+ /* Set framebuffer pointer and mark it as non allocated. */
+ render_target->is_allocated = 0;
+ render_target->data = framebuffer.ptr;
+
+ /* Copy default palette to initialize emulated palette. */
+ for (i = 0;
+ i < (sizeof (vga_colors)
+ / sizeof (struct grub_vbe_palette_data));
+ i++)
+ {
+ framebuffer.palette[i].r = vga_colors[i].red;
+ framebuffer.palette[i].g = vga_colors[i].green;
+ framebuffer.palette[i].b = vga_colors[i].blue;
+ framebuffer.palette[i].a = 0xFF;
+ }
+
+ return GRUB_ERR_NONE;
+ }
+
+ /* Couldn't found matching mode. */
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found.");
+}
+
+static grub_err_t
+grub_video_vbe_get_info (struct grub_video_mode_info * mode_info)
+{
+ /* Copy mode info from active render target. */
+ grub_memcpy (mode_info,
+ &render_target->mode_info,
+ sizeof (struct grub_video_mode_info));
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_palette (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data)
+{
+ unsigned int i;
+
+ if (framebuffer.index_color_mode)
+ {
+ /* TODO: Implement setting indexed color mode palette to hardware. */
+ //status = grub_vbe_bios_set_palette_data (sizeof (vga_colors)
+ // / sizeof (struct grub_vbe_palette_data),
+ // 0,
+ // palette);
+
+ }
+
+ /* Then set color to emulated palette. */
+ for (i = 0; (i < count) && ((i + start) < 256); i++)
+ {
+ framebuffer.palette[start + i] = palette_data[i];
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_get_palette (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data)
+{
+ unsigned int i;
+
+ /* Assume that we know everything from index color palette. */
+ for (i = 0; (i < count) && ((i + start) < 256); i++)
+ {
+ palette_data[i] = framebuffer.palette[start + i];
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_viewport (unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height)
+{
+ /* Make sure viewport is withing screen dimensions. If viewport was set
+ to be out of the reqion, mark its size as zero. */
+ if (x > active_mode_info.x_resolution)
+ {
+ x = 0;
+ width = 0;
+ }
+
+ if (y > active_mode_info.y_resolution)
+ {
+ y = 0;
+ height = 0;
+ }
+
+ if (x + width > active_mode_info.x_resolution)
+ {
+ width = active_mode_info.x_resolution - x;
+ }
+
+ if (y + height > active_mode_info.y_resolution)
+ {
+ height = active_mode_info.y_resolution - y;
+ }
+
+ render_target->viewport.x = x;
+ render_target->viewport.y = y;
+ render_target->viewport.width = width;
+ render_target->viewport.height = height;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_get_viewport (unsigned int * x,
+ unsigned int * y,
+ unsigned int * width,
+ unsigned int * height)
+{
+ if (x) *x = render_target->viewport.x;
+ if (y) *y = render_target->viewport.y;
+ if (width) *width = render_target->viewport.width;
+ if (height) *height = render_target->viewport.height;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_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_color_t color;
+
+ color = grub_video_vbe_map_rgb (framebuffer.palette[color_name].r,
+ framebuffer.palette[color_name].g,
+ framebuffer.palette[color_name].b);
+
+ return color;
+ }
+ }
+
+ return 0;
+}
+
+static grub_color_t
+grub_video_vbe_map_rgb (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue)
+{
+ if ((render_target->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ {
+ int minindex = 0;
+ int delta = 0;
+ int tmp;
+ int val;
+ int i;
+
+ /* Find best matching color. */
+ for (i = 0; i < 256; i++)
+ {
+ val = framebuffer.palette[i].r - red;
+ tmp = val * val;
+ val = framebuffer.palette[i].g - green;
+ tmp += val * val;
+ val = framebuffer.palette[i].b - blue;
+ tmp += val * val;
+
+ if (i == 0)
+ delta = tmp;
+
+ if (tmp < delta)
+ {
+ delta = tmp;
+ minindex = i;
+ if (tmp == 0)
+ break;
+ }
+ }
+
+ return minindex;
}
else
{
- color &= 0x0F;
+ grub_uint32_t value;
+ grub_uint8_t alpha = 255; /* Opaque color. */
- if (color < 16)
- {
- grub_vbe_set_pixel_rgb (x,
- y,
- vga_colors[color].red,
- vga_colors[color].green,
- vga_colors[color].blue);
- }
+ red >>= 8 - render_target->mode_info.red_mask_size;
+ green >>= 8 - render_target->mode_info.green_mask_size;
+ blue >>= 8 - render_target->mode_info.blue_mask_size;
+ alpha >>= 8 - render_target->mode_info.reserved_mask_size;
+
+ value = red << render_target->mode_info.red_field_pos;
+ value |= green << render_target->mode_info.green_field_pos;
+ value |= blue << render_target->mode_info.blue_field_pos;
+ value |= alpha << render_target->mode_info.reserved_field_pos;
+
+ return value;
+ }
+
+}
+
+static grub_color_t
+grub_video_vbe_map_rgba (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue,
+ grub_uint8_t alpha)
+{
+ if ((render_target->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ {
+ /* No alpha available in index color modes, just use
+ same value as in only RGB modes. */
+ return grub_video_vbe_map_rgb (red, green, blue);
+ }
+ else
+ {
+ grub_uint32_t value;
+
+ red >>= 8 - render_target->mode_info.red_mask_size;
+ green >>= 8 - render_target->mode_info.green_mask_size;
+ blue >>= 8 - render_target->mode_info.blue_mask_size;
+ alpha >>= 8 - render_target->mode_info.reserved_mask_size;
+
+ value = red << render_target->mode_info.red_field_pos;
+ value |= green << render_target->mode_info.green_field_pos;
+ value |= blue << render_target->mode_info.blue_field_pos;
+ value |= alpha << render_target->mode_info.reserved_field_pos;
+
+ return value;
+ }
+}
+
+static void
+grub_video_vbe_unmap_color (struct grub_video_render_target * source,
+ grub_color_t color,
+ grub_uint8_t * red,
+ grub_uint8_t * green,
+ grub_uint8_t * blue,
+ grub_uint8_t * alpha)
+{
+ if ((source->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ {
+ /* If we have out of bounds color, return trasnparent black. */
+ if (color > 255)
+ {
+ *red = 0;
+ *green = 0;
+ *blue = 0;
+ *alpha = 0;
+ return;
+ }
+
+ *red = framebuffer.palette[color].r;
+ *green = framebuffer.palette[color].g;
+ *blue = framebuffer.palette[color].b;
+ *alpha = framebuffer.palette[color].a;
+ return;
+ }
+ else
+ {
+ grub_uint32_t tmp;
+
+ /* Get red component. */
+ tmp = color >> source->mode_info.red_field_pos;
+ tmp &= (1 << source->mode_info.red_mask_size) - 1;
+ tmp <<= 8 - source->mode_info.red_mask_size;
+ tmp |= (1 << (8 - source->mode_info.red_mask_size)) - 1;
+ *red = tmp & 0xFF;
+
+ /* Get green component. */
+ tmp = color >> source->mode_info.green_field_pos;
+ tmp &= (1 << source->mode_info.green_mask_size) - 1;
+ tmp <<= 8 - source->mode_info.green_mask_size;
+ tmp |= (1 << (8 - source->mode_info.green_mask_size)) - 1;
+ *green = tmp & 0xFF;
+
+ /* Get blue component. */
+ tmp = color >> source->mode_info.blue_field_pos;
+ tmp &= (1 << source->mode_info.blue_mask_size) - 1;
+ tmp <<= 8 - source->mode_info.blue_mask_size;
+ tmp |= (1 << (8 - source->mode_info.blue_mask_size)) - 1;
+ *blue = tmp & 0xFF;
+
+ /* Get alpha component. */
+ if (source->mode_info.reserved_mask_size > 0)
+ {
+ tmp = color >> source->mode_info.reserved_field_pos;
+ tmp &= (1 << source->mode_info.reserved_mask_size) - 1;
+ tmp <<= 8 - source->mode_info.reserved_mask_size;
+ tmp |= (1 << (8 - source->mode_info.reserved_mask_size)) - 1;
+ }
else
- {
- grub_vbe_set_pixel_rgb (x,
- y,
- 0,
- 0,
- 0);
- }
+ {
+ /* If there is no alpha component, assume it opaque. */
+ tmp = 255;
+ }
+
+ *alpha = tmp & 0xFF;
+ }
+}
+
+static grub_err_t
+grub_video_vbe_fill_rect (grub_color_t color,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height)
+{
+ unsigned int i, j;
+
+ /* Make sure there is something to do. */
+ if ((x > (int)render_target->viewport.width) || (x + (int)width < 0))
+ return GRUB_ERR_NONE;
+ if ((y > (int)render_target->viewport.height) || (y + (int)height < 0))
+ return GRUB_ERR_NONE;
+
+ /* Do not allow drawing out of viewport. */
+ if (x < 0)
+ {
+ width += x;
+ x = 0;
+ }
+ if (y < 0)
+ {
+ height += y;
+ y = 0;
+ }
+
+ if ((x + width) > render_target->viewport.width)
+ {
+ width = render_target->viewport.width - x;
+ }
+ if ((y + height) > render_target->viewport.height)
+ {
+ height = render_target->viewport.height - y;
+ }
+
+ // add viewport offset
+ x += render_target->viewport.x;
+ y += render_target->viewport.y;
+
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ grub_video_vbe_draw_pixel (x+i, y+j, color);
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_blit_glyph (struct grub_font_glyph * glyph,
+ grub_color_t color,
+ int x,
+ int y)
+{
+ unsigned int width;
+ unsigned int charwidth;
+ unsigned int height;
+ unsigned int i;
+ unsigned int j;
+ unsigned int x_offset = 0;
+ unsigned int y_offset = 0;
+
+ /* Make sure there is something to do. */
+ if (x > (int)render_target->viewport.width)
+ return GRUB_ERR_NONE;
+
+ if (y > (int)render_target->viewport.height)
+ return GRUB_ERR_NONE;
+
+ /* Calculate glyph dimensions. */
+ width = ((glyph->width + 7) / 8) * 8;
+ charwidth = width;
+ height = glyph->height;
+
+ if (x + (int)width < 0)
+ return GRUB_ERR_NONE;
+
+ if (y + (int)height < 0)
+ return GRUB_ERR_NONE;
+
+ /* Do not allow drawing out of viewport. */
+ if (x < 0)
+ {
+ width += x;
+ x_offset = (unsigned int)-x;
+ x = 0;
+ }
+ if (y < 0)
+ {
+ height += y;
+ y_offset = (unsigned int)-y;
+ y = 0;
+ }
+
+ if ((x + width) > render_target->viewport.width)
+ {
+ width = render_target->viewport.width - x;
+ }
+ if ((y + height) > render_target->viewport.height)
+ {
+ height = render_target->viewport.height - y;
+ }
+
+ /* Add viewport offset. */
+ x += render_target->viewport.x;
+ y += render_target->viewport.y;
+
+ /* Draw glyph. */
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ if ((glyph->bitmap[((i + x_offset) / 8)
+ + (j + y_offset) * (charwidth / 8)]
+ & (1 << ((charwidth - (i + x_offset) - 1) % 8))))
+ {
+ grub_video_vbe_draw_pixel (x+i, y+j, color);
+ }
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_blit_bitmap (struct grub_video_bitmap * bitmap,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height)
+{
+ /* Make sure there is something to do. */
+ if ((x > (int)render_target->viewport.width) || (x + (int)width < 0))
+ return GRUB_ERR_NONE;
+ if ((y > (int)render_target->viewport.height) || (y + (int)height < 0))
+ return GRUB_ERR_NONE;
+
+ /* Do not allow drawing out of viewport. */
+ if (offset_x < 0)
+ {
+ width += offset_x;
+ x -= offset_x;
+ offset_x = 0;
+ }
+
+ if (offset_y < 0)
+ {
+ height += offset_y;
+ y -= offset_y;
+ offset_y = 0;
+ }
+
+ if (x < 0)
+ {
+ width += x;
+ offset_x += (unsigned int)-x;
+ x = 0;
+ }
+ if (y < 0)
+ {
+ height += y;
+ offset_y += (unsigned int)-y;
+ y = 0;
+ }
+
+ if ((x + width) > render_target->viewport.width)
+ {
+ width = render_target->viewport.width - x;
+ }
+ if ((y + height) > render_target->viewport.height)
+ {
+ height = render_target->viewport.height - y;
+ }
+
+ /* TODO: Limit drawing to bitmap dimensions. */
+
+ /* Add viewport offset. */
+ x += render_target->viewport.x;
+ y += render_target->viewport.y;
+
+ /* TODO: Render bitmap. */
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_blit_render_target (struct grub_video_render_target * source,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height)
+{
+ unsigned int i;
+ unsigned int j;
+
+ /* Make sure there is something to do. */
+ if ((width == 0) || (height == 0))
+ return GRUB_ERR_NONE;
+ if ((x > (int)render_target->viewport.width) || (x + (int)width < 0))
+ return GRUB_ERR_NONE;
+ if ((y > (int)render_target->viewport.height) || (y + (int)height < 0))
+ return GRUB_ERR_NONE;
+ if ((x + (int)source->mode_info.width) < 0)
+ return GRUB_ERR_NONE;
+ if ((y + (int)source->mode_info.height) < 0)
+ return GRUB_ERR_NONE;
+ if ((offset_x > (int)source->mode_info.width)
+ || (offset_x + (int)source->mode_info.width < 0))
+ return GRUB_ERR_NONE;
+ if ((offset_y > (int)source->mode_info.height)
+ || (offset_y + (int)source->mode_info.height < 0))
+ return GRUB_ERR_NONE;
+
+ /* If we have negative coordintes, optimize drawing to minimum. */
+ if (offset_x < 0)
+ {
+ width += offset_x;
+ x -= offset_x;
+ offset_x = 0;
+ }
+
+ if (offset_y < 0)
+ {
+ height += offset_y;
+ y -= offset_y;
+ offset_y = 0;
+ }
+
+ if (x < 0)
+ {
+ width += x;
+ offset_x += (unsigned int)-x;
+ x = 0;
+ }
+
+ if (y < 0)
+ {
+ height += y;
+ offset_y += (unsigned int)-y;
+ y = 0;
+ }
+
+ /* Do not allow drawing out of viewport. */
+ if ((x + width) > render_target->viewport.width)
+ {
+ width = render_target->viewport.width - x;
+ }
+ if ((y + height) > render_target->viewport.height)
+ {
+ height = render_target->viewport.height - y;
+ }
+
+ if ((offset_x + width) > source->mode_info.width)
+ {
+ width = source->mode_info.width - offset_x;
+ }
+ if ((offset_y + height) > source->mode_info.height)
+ {
+ height = source->mode_info.height - offset_y;
+ }
+
+ /* Limit drawing to source render target dimensions. */
+ if (width > source->mode_info.width)
+ {
+ width = source->mode_info.width;
+ }
+
+ if (height > source->mode_info.height)
+ {
+ height = source->mode_info.height;
+ }
+
+ /* Add viewport offset. */
+ x += render_target->viewport.x;
+ y += render_target->viewport.y;
+
+ /* Render. */
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ grub_uint8_t src_red;
+ grub_uint8_t src_green;
+ grub_uint8_t src_blue;
+ grub_uint8_t src_alpha;
+ grub_uint8_t dst_red;
+ grub_uint8_t dst_green;
+ grub_uint8_t dst_blue;
+ grub_uint8_t dst_alpha;
+ grub_color_t src_color;
+ grub_color_t dst_color;
+
+ src_color = grub_video_vbe_get_pixel (source, i + offset_x, j + offset_y);
+ grub_video_vbe_unmap_color (source,
+ src_color,
+ &src_red,
+ &src_green,
+ &src_blue,
+ &src_alpha);
+
+ if (src_alpha == 0) continue;
+
+ if (src_alpha == 255)
+ {
+ dst_color = grub_video_vbe_map_rgba (src_red,
+ src_green,
+ src_blue,
+ src_alpha);
+ grub_video_vbe_draw_pixel (x + i, y + j, dst_color);
+ continue;
+ }
+
+ dst_color = grub_video_vbe_get_pixel (render_target,
+ x + i,
+ y + j);
+
+ grub_video_vbe_unmap_color (render_target,
+ dst_color,
+ &dst_red,
+ &dst_green,
+ &dst_blue,
+ &dst_alpha);
+
+ dst_red = (((src_red * src_alpha)
+ + (dst_red * (255 - src_alpha))) / 255);
+ dst_green = (((src_green * src_alpha)
+ + (dst_green * (255 - src_alpha))) / 255);
+ dst_blue = (((src_blue * src_alpha)
+ + (dst_blue * (255 - src_alpha))) / 255);
+
+ dst_alpha = src_alpha;
+ dst_color = grub_video_vbe_map_rgba (dst_red,
+ dst_green,
+ dst_blue,
+ dst_alpha);
+
+ grub_video_vbe_draw_pixel (x + i, y + j, dst_color);
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_scroll (grub_color_t color,
+ int dx,
+ int dy)
+{
+ int width;
+ int height;
+ int src_x;
+ int src_y;
+ int dst_x;
+ int dst_y;
+
+ /* TODO: Fix x & y handling. */
+
+ /* 1. Check if we have something to do. */
+ if ((dx == 0) && (dy == 0))
+ return GRUB_ERR_NONE;
+
+ width = render_target->viewport.width - grub_abs(dx);
+ height = render_target->viewport.height - grub_abs(dy);
+
+ if (dx < 0)
+ {
+ src_x = render_target->viewport.x - dx;
+ dst_x = render_target->viewport.x;
+ }
+ else
+ {
+ src_x = render_target->viewport.x;
+ dst_x = render_target->viewport.x + dx;
+ }
+
+ if (dy < 0)
+ {
+ src_y = render_target->viewport.y - dy;
+ dst_y = render_target->viewport.y;
+ }
+ else
+ {
+ src_y = render_target->viewport.y;
+ dst_y = render_target->viewport.y + dy;
+ }
+
+ /* 2. Check if there is need to copy data. */
+ if ((grub_abs (dx) < render_target->viewport.width)
+ && (grub_abs (dy) < render_target->viewport.height))
+ {
+ /* 3. Move data in render target. */
+ grub_uint8_t *src;
+ grub_uint8_t *dst;
+ int j;
+
+ for (j = 0; j < height; j++)
+ {
+ dst = grub_video_vbe_get_video_ptr (render_target, dst_x, dst_y + j);
+ src = grub_video_vbe_get_video_ptr (render_target, src_x, src_y + j);
+ grub_memmove (dst,
+ src,
+ width * render_target->mode_info.bytes_per_pixel);
+ }
+ }
+
+ /* 4. Fill empty space with specified color. In this implementation
+ there might be colliding areas but at the moment there is no need
+ to optimize this. */
+
+ // TODO: PROOFREAD THIS!.
+
+ /* 4a. Fill top & bottom parts. */
+ if (dy > 0)
+ {
+ grub_video_vbe_fill_rect (color,
+ 0, 0,
+ render_target->viewport.width, dy);
+ }
+ else if (dy < 0)
+ {
+ if (render_target->viewport.height < grub_abs(dy))
+ dy = -render_target->viewport.height;
+
+ grub_video_vbe_fill_rect (color,
+ 0, render_target->viewport.height + dy,
+ render_target->viewport.width, -dy);
+ }
+
+ /* 4b. Fill left & right parts. */
+ if (dx > 0)
+ {
+ grub_video_vbe_fill_rect (color,
+ 0, 0,
+ dx, render_target->viewport.height);
+ }
+ else if (dx < 0)
+ {
+ if (render_target->viewport.width < grub_abs(dx))
+ dx = -render_target->viewport.width;
+
+ grub_video_vbe_fill_rect (color,
+ render_target->viewport.width + dx, 0,
+ -dx, render_target->viewport.height);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_swap_buffers (void)
+{
+ /* TODO: Implement buffer swapping. */
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_create_render_target (struct grub_video_render_target * * result,
+ unsigned int mode_type,
+ unsigned int width,
+ unsigned int height)
+{
+ struct grub_video_render_target *target;
+ unsigned int size;
+
+ /* Validate arguments. */
+ if ((! result)
+ || (width == 0)
+ || (height == 0))
+ {
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "invalid argument given.");
+ }
+
+ /* Allocate memory for render target. */
+ target = grub_malloc (sizeof (struct grub_video_render_target));
+ if (! target)
+ return grub_errno;
+
+ /* TODO: Implement other types too. */
+ size = (width * 4) * 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);
+
+ /* 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;
+ 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;
+
+ /* TODO: Add render target to render target list. */
+
+ /* Save result to caller. */
+ *result = target;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_delete_render_target (struct grub_video_render_target * target)
+{
+ /* If there is no target, then just return without error. */
+ if (! target)
+ {
+ return GRUB_ERR_NONE;
+ }
+
+ /* TODO: Delist render target fron render target list. */
+
+ /* If this is software render target, free it's memory. */
+ if (target->is_allocated)
+ {
+ grub_free (target->data);
+ }
+
+ /* Free render target. */
+ grub_free (target);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_active_render_target (struct grub_video_render_target * target)
+{
+ if (target == GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER)
+ {
+ render_target = &framebuffer.render_target;
+
+ return GRUB_ERR_NONE;
}
+
+ if (target == GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER)
+ {
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "double buffering not implemented yet.");
+ }
+
+ if (! target->data)
+ {
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "invalid render target given.");
+ }
+
+ render_target = target;
+
+ return GRUB_ERR_NONE;
+}
+
+static struct grub_video_adapter grub_video_vbe_adapter =
+ {
+ .name = "VESA BIOS Extension Video Driver",
+
+ .init = grub_video_vbe_init,
+ .fini = grub_video_vbe_fini,
+ .setup = grub_video_vbe_setup,
+ .get_info = grub_video_vbe_get_info,
+ .set_palette = grub_video_vbe_set_palette,
+ .get_palette = grub_video_vbe_get_palette,
+ .set_viewport = grub_video_vbe_set_viewport,
+ .get_viewport = grub_video_vbe_get_viewport,
+ .map_color = grub_video_vbe_map_color,
+ .map_rgb = grub_video_vbe_map_rgb,
+ .map_rgba = grub_video_vbe_map_rgba,
+ .fill_rect = grub_video_vbe_fill_rect,
+ .blit_glyph = grub_video_vbe_blit_glyph,
+ .blit_bitmap = grub_video_vbe_blit_bitmap,
+ .blit_render_target = grub_video_vbe_blit_render_target,
+ .scroll = grub_video_vbe_scroll,
+ .swap_buffers = grub_video_vbe_swap_buffers,
+ .create_render_target = grub_video_vbe_create_render_target,
+ .delete_render_target = grub_video_vbe_delete_render_target,
+ .set_active_render_target = grub_video_vbe_set_active_render_target,
+
+ .next = 0
+ };
+
+GRUB_MOD_INIT(video_i386_pc_vbe)
+{
+ my_mod = mod;
+ grub_video_register (&grub_video_vbe_adapter);
+}
+
+GRUB_MOD_FINI(video_i386_pc_ovbe)
+{
+ grub_video_unregister (&grub_video_vbe_adapter);
}
diff -ruN -x '*CVS*' grub2/video/video.c grub2.new/video/video.c
--- grub2/video/video.c 1970-01-01 02:00:00.000000000 +0200
+++ grub2.new/video/video.c 2006-03-02 16:49:13.022283256 +0200
@@ -0,0 +1,482 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/machine/memory.h>
+#include <grub/video.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/font.h>
+#include <grub/arg.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+#include <grub/font.h>
+#include <grub/term.h>
+
+/* The list of video adapters registerd to system. */
+static grub_video_adapter_t grub_video_adapter_list;
+
+/* Active video adapter. */
+static grub_video_adapter_t grub_video_adapter_active;
+
+static grub_dl_t my_mod;
+
+void
+grub_video_register (grub_video_adapter_t adapter)
+{
+ adapter->next = grub_video_adapter_list;
+ grub_video_adapter_list = adapter;
+}
+
+void
+grub_video_unregister (grub_video_adapter_t adapter)
+{
+ grub_video_adapter_t *p, q;
+
+ for (p = &grub_video_adapter_list, q = *p; q; p = &(q->next), q = q->next)
+ if (q == adapter)
+ {
+ *p = q->next;
+ break;
+ }
+}
+
+void
+grub_video_iterate (int (*hook) (grub_video_adapter_t adapter))
+{
+ grub_video_adapter_t p;
+
+ for (p = grub_video_adapter_list; p; p = p->next)
+ if (hook (p))
+ break;
+}
+
+grub_err_t
+grub_video_setup (unsigned int width,
+ unsigned int height,
+ unsigned int mode_type)
+{
+ grub_video_adapter_t p;
+
+ /* De-activate last set video adapter. */
+ if (grub_video_adapter_active)
+ {
+ /* Finalize adapter. */
+ grub_video_adapter_active->fini ();
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Mark active adapter as not set. */
+ grub_video_adapter_active = 0;
+ }
+
+ /* Loop thru all possible video adapter trying to find requested mode. */
+ for (p = grub_video_adapter_list; p; p = p->next)
+ {
+ /* Try to initialize adapter, if can't skip to next. */
+ p->init ();
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+
+ /* Try to initialize video mode. */
+ p->setup (width, height, mode_type);
+ if (grub_errno == GRUB_ERR_NONE)
+ {
+ /* Valid mode found from adapter, and it has been activated.
+ Specify it as active adapter. */
+ grub_video_adapter_active = p;
+ return GRUB_ERR_NONE;
+ }
+ else
+ {
+ grub_errno = GRUB_ERR_NONE;
+ }
+
+ /* No valid mode found in this adapter, finalize adapter. */
+ p->fini ();
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+ }
+
+ /* We couldn't find suitable adapter for specified mode. */
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+ "Can't locate valid adapter for mode");
+}
+
+grub_err_t
+grub_video_restore (void)
+{
+ if (grub_video_adapter_active)
+ {
+ grub_video_adapter_active->fini ();
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ grub_video_adapter_active = 0;
+ }
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_video_get_info (struct grub_video_mode_info * mode_info)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->get_info (mode_info);
+}
+
+grub_err_t
+grub_video_set_palette (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->set_palette (start, count, palette_data);
+}
+
+grub_err_t
+grub_video_get_palette (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->get_palette (start, count, palette_data);
+}
+
+grub_err_t
+grub_video_set_viewport (unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->set_viewport (x, y, width, height);
+}
+
+grub_err_t
+grub_video_get_viewport (unsigned int * x,
+ unsigned int * y,
+ unsigned int * width,
+ unsigned int * height)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->get_viewport (x, y, width, height);
+}
+
+grub_color_t
+grub_video_map_color (grub_uint32_t color_name)
+{
+ if (! grub_video_adapter_active)
+ {
+ return 0;
+ }
+
+ return grub_video_adapter_active->map_color (color_name);
+}
+
+grub_color_t
+grub_video_map_rgb (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue)
+{
+ if (! grub_video_adapter_active)
+ {
+ return 0;
+ }
+
+ return grub_video_adapter_active->map_rgb (red, green, blue);
+}
+
+grub_color_t
+grub_video_map_rgba (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue,
+ grub_uint8_t alpha)
+{
+ if (! grub_video_adapter_active)
+ {
+ return 0;
+ }
+
+ return grub_video_adapter_active->map_rgba (red, green, blue, alpha);
+}
+
+grub_err_t
+grub_video_fill_rect (grub_color_t color,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->fill_rect (color, x, y, width, height);
+}
+
+grub_err_t
+grub_video_blit_glyph (struct grub_font_glyph * glyph,
+ grub_color_t color,
+ int x,
+ int y)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->blit_glyph (glyph, color, x, y);
+}
+
+grub_err_t
+grub_video_blit_bitmap (struct grub_video_bitmap * bitmap,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->blit_bitmap (bitmap,
+ x, y,
+ offset_x, offset_y,
+ width, height);
+}
+
+grub_err_t
+grub_video_blit_render_target (struct grub_video_render_target * target,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->blit_render_target (target,
+ x, y,
+ offset_x, offset_y,
+ width, height);
+}
+
+grub_err_t
+grub_video_scroll (grub_color_t color,
+ int dx,
+ int dy)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->scroll (color, dx, dy);
+}
+
+grub_err_t
+grub_video_swap_buffers (void)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->swap_buffers ();
+}
+
+grub_err_t
+grub_video_create_render_target (struct grub_video_render_target * * result,
+ unsigned int mode_type,
+ unsigned int width,
+ unsigned int height)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->create_render_target (result,
+ mode_type,
+ width,
+ height);
+}
+
+grub_err_t
+grub_video_delete_render_target (struct grub_video_render_target * target)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->delete_render_target (target);
+}
+
+grub_err_t
+grub_video_set_active_render_target (struct grub_video_render_target * target)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->set_active_render_target (target);
+}
+
+static grub_err_t
+grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+ if (grub_video_setup (1024,
+ 768,
+ GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != GRUB_ERR_NONE)
+ {
+ return grub_errno;
+ }
+
+ grub_getkey ();
+
+ grub_uint32_t color;
+ grub_uint32_t x, y, width, height;
+ int i;
+ struct grub_font_glyph glyph;
+ struct grub_video_render_target *text_layer;
+ grub_color_t palette[16];
+
+ grub_video_get_viewport (&x, &y, &width, &height);
+
+ grub_video_create_render_target (&text_layer,
+ GRUB_VIDEO_MODE_TYPE_RGB
+ | GRUB_VIDEO_MODE_TYPE_ALPHA,
+ width,
+ height);
+
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ color = grub_video_map_rgb (0, 0, 0);
+ grub_video_fill_rect (color, 0, 0, width, height);
+
+ color = grub_video_map_rgb (255,0,0);
+ grub_video_fill_rect (color, 0, 0, 100, 100);
+
+ color = grub_video_map_rgb (0,255,255);
+ grub_video_fill_rect (color, 100, 100, 100, 100);
+
+ grub_font_get_glyph ('*', &glyph);
+ grub_video_blit_glyph (&glyph, color, 200 ,0);
+
+ grub_video_set_viewport (x + 150, y + 150, width - 150*2, height - 150*2);
+ color = grub_video_map_rgb (77,33,77);
+ grub_video_fill_rect (color, 0, 0, width, height);
+
+ grub_video_set_active_render_target (text_layer);
+
+ color = grub_video_map_rgb (255,255,255);
+
+ grub_font_get_glyph ('A', &glyph);
+ grub_video_blit_glyph (&glyph, color, 16, 16);
+ grub_font_get_glyph ('B', &glyph);
+ grub_video_blit_glyph (&glyph, color, 16*2, 16);
+
+ grub_font_get_glyph ('*', &glyph);
+
+ for (i = 0; i < 16; i++)
+ {
+ color = grub_video_map_color (i);
+ palette[i] = color;
+ grub_video_blit_glyph (&glyph, color, 16 + i * 16, 32);
+ }
+
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ for (i = 0; i < 255; i++)
+ {
+ color = grub_video_map_rgb (i, 33, 77);
+ grub_video_fill_rect (color, 0, 0, width, height);
+ grub_video_blit_render_target (text_layer, 0, 0, 0, 0, width, height);
+ }
+
+ grub_getkey ();
+
+ grub_video_delete_render_target (text_layer);
+
+ grub_video_restore ();
+
+ for (i = 0; i < 16; i++)
+ {
+ grub_printf("color %d: %08x\n", i, palette[i]);
+ }
+
+ grub_errno = GRUB_ERR_NONE;
+ return grub_errno;
+}
+
+GRUB_MOD_INIT(video_video)
+{
+ my_mod = mod;
+
+ grub_video_adapter_active = 0;
+ grub_video_adapter_list = 0;
+
+ grub_register_command ("videotest",
+ grub_cmd_videotest,
+ GRUB_COMMAND_FLAG_BOTH,
+ "videotest",
+ "Test video subsystem",
+ 0);
+}
+
+GRUB_MOD_FINI(video_video)
+{
+ grub_unregister_command ("videotest");
+}
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: New patch for video subsystem...
2006-03-02 19:28 New patch for video subsystem Vesa Jääskeläinen
@ 2006-03-03 11:49 ` Marco Gerards
2006-03-03 15:23 ` Vesa Jääskeläinen
2006-05-04 22:27 ` Johan Rydberg
1 sibling, 1 reply; 14+ messages in thread
From: Marco Gerards @ 2006-03-03 11:49 UTC (permalink / raw)
To: Vesa Jääskeläinen; +Cc: The development of GRUB 2
Vesa Jääskeläinen <chaac@nic.fi> writes:
Hi Vesa,
Thanks for your patch. I have done a review, but you should know that
I am not a graphics expert and don't understand all of the code in
detail. Most issues are GCS related, they don't only apply to the
line I commented on, but in general. Please make sure all the code is
fixed and not this single line.
I hope other people will do a quick review as well, so the code can be
committed soon in a state everyone is happy with.
Thanks,
Marco
> How to use it:
> In order to have graphical console, you need to first load video driver
> (that would be vbe module) and then load videoterm module. After that
> you will need to tell what video mode you would like to use. And last
> you just initialize it with "terminal videoterm".
>
> Example command sequence:
> insmod font
> font /boot/grub/unifont.pff
> insmod terminal
> insmod vbe
> insmod videoterm
> set video_mode=1024x768
> terminal videoterm
>
> How to fine tune video mode:
> Handling of video_mode environment variable is a flexible one. You can
> specify multiple settings at one line. If video_mode is not set, it will
> use 1024x768 as a default resolution and will use highes number of
> colors available. Supported options are following:
Personally I would prefer a VGA compatible default. The reason for
that is that not always videoterm.mod is loaded from grub.cfg. For
example, the module might be added to the (GRUB 2) kernel when loading
GRUB via the network.
As for the name, I do not think videoterm is a good name. For my
feeling something like `fbterm' or so is better. Perhaps someone else
has some good suggestions.
> width=<value>
> height=<value>
> index
> rgb
> <width>x<height>x<depth>
>
> And you can make combo's of those like:
>
> set video_mode="width=1024 height=768 rgb"
I prefer to just use a simplified notation. So 1024x768x24. Most
people understand this notation, it will make scripting easier and
doesn't require that much code for parsing.
> +2006-02-25 Vesa Jaaskelainen <chaac@nic.fi>
> +
> + * DISTLIST: Added include/grub/video.h, term/videoterm.c,
> + video/video.c.
> + Removed term/i386/pc/vesafb.c.
> +
> + * conf/i386-pc.rmk (pkgdata_MODULES): Added video.mod,
> + videoterm.mod.
> + Removed vga.mod, vesafb.mod.
Just put the removed line on the same line as where you say things
were added. It looks a bit nicer and that is what we in general do.
> + * font/manager.c (fill_with_default_glyph): Modified to use
> + grub_font_glyph.
> + (grub_font_get_glyph): Modified to use grub_font_glyph.
> + (fontmanager): Renamed to font_manager.
> +
> + * include/grub/font.h (grub_font_glyph): Added.
Please say `New function.' or `New variable.'. It's in general better
to do that, you can immediatly see what it is.
> + * include/grub/i386/pc/vbe.h (GRUB_VBE_STATUS_OK): Added.
> + (GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL): Likewise.
> + (GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR): Likewise.
`New macro.' would be better.
> + (grub_vbe_get_controller_info): Renamed to
> + grub_vbe_bios_get_controller_info.
we use this syntax:
(grub_vbe_get_controller_info): Renamed from this...
(grub_vbe_bios_get_controller_info): ... to this. All users
changed to use the new function name.
It's important that it is visible that the new function did not just
pop up. So now you can look back in the changelog entry where it was
added.
> + * include/grub/video.h: Added.
`New file.' is more consistent with the rest of GRUB.
> + * normal/cmdline.c (cl_set_pos): Made it refresh screen, to enable
> + better visual experience to video drivers.
Just use something like `Refresh the screen.'. It's a general bug
fix, not only for the video drivers (although it unfortunately shows
up there :)).
> + * term/videoterm.c: Added.
> +
> + * video/video.c: Added
`New file.' again.
> + * video/i386/pc/vbe.c: Refactored to new video subsystem.
Just leave away this line. Usually this is done by using `All users
changed.' when interfaces change or functions are renamed.
> -# For vga.mod.
> -vga_mod_SOURCES = term/i386/pc/vga.c
> -vga_mod_CFLAGS = $(COMMON_CFLAGS)
> -vga_mod_LDFLAGS = $(COMMON_LDFLAGS)
Why do you remove this?
> include $(srcdir)/conf/common.mk
> diff -ruN -x '*CVS*' grub2/font/manager.c grub2.new/font/manager.c
> --- grub2/font/manager.c 2005-11-13 17:47:09.000000000 +0200
> +++ grub2.new/font/manager.c 2006-02-25 14:16:16.000000000 +0200
> @@ -24,6 +24,7 @@
> #include <grub/types.h>
> #include <grub/mm.h>
> #include <grub/font.h>
> +//#include <grub/gzio.h>
Can you remove this line?
> struct entry
> {
> @@ -50,6 +51,7 @@
> struct font *font = 0;
>
> file = grub_file_open (filename);
> + //file = grub_gzfile_open (filename, 1);
And this one.
> /* Get a glyph corresponding to the codepoint CODE. Always fill BITMAP
> and WIDTH with something, even if no glyph is found. */
> int
> grub_font_get_glyph (grub_uint32_t code,
> - unsigned char bitmap[32], unsigned *width)
> + grub_font_glyph_t glyph)
The prototype was changed, but the comment wasn't.
> {
> struct font *font;
> + grub_uint8_t bitmap[32];
>
> /* FIXME: It is necessary to cache glyphs! */
>
> @@ -183,12 +186,19 @@
> if (offset)
> {
> grub_uint32_t w;
> + grub_uint8_t x;
> + grub_uint8_t y;
> + grub_uint32_t len;
Please just use int here. You read w from disk, so I understand why
it is a grub_uint32_t, but the others don't come from disk, right?
> - if (grub_file_read (font->file, (char *) &w, 4) != 4)
> + if ((len = grub_file_read (font->file, (char *) &w, 4)) != 4)
I'm sorry that I am commenting on old code, but can you change this to
some sizeof test or so?
> + glyph->baseline = (16*3)/4;
Can you place some spaces around the operators, so:
glyph->baseline = (16 * 3) / 4;
> +struct grub_font_glyph
> +{
> + /* Glyph width in pixels. */
> + grub_uint8_t width;
> +
> + /* Glyph height in pixels. */
> + grub_uint8_t height;
> +
> + /* Glyph width in characters. */
> + grub_uint8_t char_width;
> +
> + /* Glyph baseline position in pixels (from up). */
> + grub_uint8_t baseline;
> +
> + /* Glyph bitmap data array of bytes in ((width + 7) / 8) * height.
> + Bitmap is formulated by height scanlines, each scanline having
> + width number of pixels. Pixels are coded as bits, value 1 meaning
> + of opaque pixel and 0 is transparent. If width does not fit byte
> + boundary, it will be padded with 0 to make it fit. */
> + grub_uint8_t bitmap[32];
> +};
> +
> +typedef struct grub_font_glyph *grub_font_glyph_t;
I hope Okuji will look at this, I am clueless about the font manager
as for now. :-)
> #endif /* ! GRUB_MISC_HEADER */
> diff -ruN -x '*CVS*' grub2/include/grub/video.h grub2.new/include/grub/video.h
> --- grub2/include/grub/video.h 1970-01-01 02:00:00.000000000 +0200
> +++ grub2.new/include/grub/video.h 2006-03-02 15:33:32.650225312 +0200
> @@ -0,0 +1,300 @@
> +/*
> + * GRUB -- GRand Unified Bootloader
> + * Copyright (C) 2002,2003,2005 Free Software Foundation, Inc.
I think it should just be 2006, right?
> +typedef grub_uint32_t grub_color_t;
I think grub_video_color_t is better.
> +struct grub_video_mode_info {
It think it is more appropriate to use `int' instead of
`grub_uint32_t' for the members of this struct.
> +};
> + grub_err_t (*get_info) (struct grub_video_mode_info * mode_info);
Can you remove the space between `*' and `mode_info'?
> + grub_err_t (*get_viewport) (unsigned int * x,
> + unsigned int * y,
> + unsigned int * width,
> + unsigned int * height);
Same here. Please look at other places where you did this too.
> +struct grub_virtual_screen
> +{
> + /* Dimensions of the virual screen. */
Typo.
Can you change grub_uint32_t to ints inside this struct?
> +};
> +/* Make seure text buffer is not marked as allocated. */
Typo: seure->sure
> +static struct grub_virtual_screen virtual_screen =
> + {
> + .text_buffer = 0
> + };
You can leave away the initiazation, it is done automatically.
> +static struct grub_video_render_target *text_layer = 0;
Same here.
> + /* Cleare new render target for text layer. */
Typo: Cleare->Create (right?)
> + grub_video_create_render_target (&text_layer,
> + GRUB_VIDEO_MODE_TYPE_RGB
> + | GRUB_VIDEO_MODE_TYPE_ALPHA,
> + virtual_screen.width,
> + virtual_screen.height);
> +static grub_err_t
> +grub_videoterm_init (void)
> +{
> + char *modevar;
> + int width = 1024;
> + int height = 768;
Please make macros for these defaults. In that case it can be easily
changed without looking at the code.
> + /* Leave borders for virtual screen. */
> + width = mode_info.width - (2 * 10);
> + height = mode_info.height - (2 * 10);
Can you explain this? Isn't it better to use some font width
multiple?
> + if (x < dirty_region.top_left_x)
> + {
> + dirty_region.top_left_x = x;
> + }
You don't have to use { and } for a singe line. It makes this code
hard to read. So please don't use it for such if statements.
> diff -ruN -x '*CVS*' grub2/video/i386/pc/vbe.c grub2.new/video/i386/pc/vbe.c
> --- grub2/video/i386/pc/vbe.c 2005-09-19 00:04:41.000000000 +0300
> +++ grub2.new/video/i386/pc/vbe.c 2006-03-02 20:35:43.719014568 +0200
> @@ -1,6 +1,6 @@
> /*
> * GRUB -- GRand Unified Bootloader
> - * Copyright (C) 2005 Free Software Foundation, Inc.
> + * Copyright (C) 2005-2006 Free Software Foundation, Inc.
Please use commas to separate lines. For legal reasons a range of
years is unfortunately not allowed.
> + render_target->mode_info.bpp = active_mode_info.bits_per_pixel;
> + render_target->mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel;
> + render_target->mode_info.pitch = framebuffer.bytes_per_scan_line;
> + render_target->mode_info.number_of_colors = 256; /* TODO: fix me. */
> + render_target->mode_info.red_mask_size = active_mode_info.red_mask_size;
> + render_target->mode_info.red_field_pos = active_mode_info.red_field_position;
> + render_target->mode_info.green_mask_size = active_mode_info.green_mask_size;
> + render_target->mode_info.green_field_pos = active_mode_info.green_field_position;
> + render_target->mode_info.blue_mask_size = active_mode_info.blue_mask_size;
> + render_target->mode_info.blue_field_pos = active_mode_info.blue_field_position;
> + render_target->mode_info.reserved_mask_size = active_mode_info.rsvd_mask_size;
> + render_target->mode_info.reserved_field_pos = active_mode_info.rsvd_field_position;
Isn't it possible to copy this in a single statement?
> + /* If we have negative coordintes, optimize drawing to minimum. */
Typo.
> + width = render_target->viewport.width - grub_abs(dx);
> + height = render_target->viewport.height - grub_abs(dy);
Please add a space after `grub_abs'.
> + // TODO: PROOFREAD THIS!.
Ehm? :-)
> +static grub_err_t
> +grub_video_vbe_swap_buffers (void)
> +{
> + /* TODO: Implement buffer swapping. */
Sin't this just activating another region in the video memory? I
think it would be quite trivial when using VESA.
> + /* TODO: Implement other types too. */
> + size = (width * 4) * height;
Please use sizeof here.
> + /* Setup render target format. */
> + target->mode_info.width = width;
> + target->mode_info.height = height;
> + target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB
> + | GRUB_VIDEO_MODE_TYPE_ALPHA;
> + target->mode_info.bpp = 32;
> + target->mode_info.bytes_per_pixel = 4;
> + target->mode_info.pitch = target->mode_info.bytes_per_pixel * width;
> + target->mode_info.number_of_colors = 256;
> + target->mode_info.red_mask_size = 8;
> + target->mode_info.red_field_pos = 0;
> + target->mode_info.green_mask_size = 8;
> + target->mode_info.green_field_pos = 8;
> + target->mode_info.blue_mask_size = 8;
> + target->mode_info.blue_field_pos = 16;
> + target->mode_info.reserved_mask_size = 8;
> + target->mode_info.reserved_field_pos = 24;
These are all defaults, right? First of all, I prefer macros instead
of hardcoded values.
bpp is set to 32, while number of colors says 256, are you sure this
is correct? I prefer a bpp of 8 as default, for compatibility
reasons.
> +static grub_err_t
> +grub_video_vbe_delete_render_target (struct grub_video_render_target * target)
> +{
> + /* If there is no target, then just return without error. */
> + if (! target)
> + {
> + return GRUB_ERR_NONE;
> + }
No braces, like before. Same for the code below.
> +static grub_err_t
> +grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)),
> + int argc __attribute__ ((unused)),
> + char **args __attribute__ ((unused)))
It's better to move this to another file, like commands/videotest.c.
Or do you think this is only useful for debugging, in that case better
put it in some #ifdef.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: New patch for video subsystem...
2006-03-03 11:49 ` Marco Gerards
@ 2006-03-03 15:23 ` Vesa Jääskeläinen
2006-03-05 22:25 ` Yoshinori K. Okuji
` (2 more replies)
0 siblings, 3 replies; 14+ messages in thread
From: Vesa Jääskeläinen @ 2006-03-03 15:23 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 16397 bytes --]
Marco Gerards wrote:
> Vesa Jääskeläinen <chaac@nic.fi> writes:
>
> Hi Vesa,
>
> Thanks for your patch. I have done a review, but you should know that
> I am not a graphics expert and don't understand all of the code in
> detail. Most issues are GCS related, they don't only apply to the
> line I commented on, but in general. Please make sure all the code is
> fixed and not this single line.
That wasn't a small job ;).. I hope I got all right.
> I hope other people will do a quick review as well, so the code can be
> committed soon in a state everyone is happy with.
Sounds fine.
I have made modifications and attached it as a new diff in this message.
Thanks,
Vesa Jääskeläinen
>> How to use it:
>> In order to have graphical console, you need to first load video driver
>> (that would be vbe module) and then load videoterm module. After that
>> you will need to tell what video mode you would like to use. And last
>> you just initialize it with "terminal videoterm".
>>
>> Example command sequence:
>> insmod font
>> font /boot/grub/unifont.pff
>> insmod terminal
>> insmod vbe
>> insmod videoterm
>> set video_mode=1024x768
>> terminal videoterm
>>
>> How to fine tune video mode:
>> Handling of video_mode environment variable is a flexible one. You can
>> specify multiple settings at one line. If video_mode is not set, it will
>> use 1024x768 as a default resolution and will use highes number of
>> colors available. Supported options are following:
>
> Personally I would prefer a VGA compatible default. The reason for
> that is that not always videoterm.mod is loaded from grub.cfg. For
> example, the module might be added to the (GRUB 2) kernel when loading
> GRUB via the network.
Well that default is in videoterm, and if it is not loaded then I do not
see that as a problem. We can change the default resolution easily if
that is the case. And if you need it for other purposes currently you
will need to tell what mode you want.
Nowadays 1024x768 is a normal standard resolution.
> As for the name, I do not think videoterm is a good name. For my
> feeling something like `fbterm' or so is better. Perhaps someone else
> has some good suggestions.
I am all ears for suggestions.
>> width=<value>
>> height=<value>
>> index
>> rgb
>> <width>x<height>x<depth>
>>
>> And you can make combo's of those like:
>>
>> set video_mode="width=1024 height=768 rgb"
>
> I prefer to just use a simplified notation. So 1024x768x24. Most
> people understand this notation, it will make scripting easier and
> doesn't require that much code for parsing.
Reason why I added more complex one is that there might be settings that
would be good to be parsed to flags field.
>> +2006-02-25 Vesa Jaaskelainen <chaac@nic.fi>
>> +
>> + * DISTLIST: Added include/grub/video.h, term/videoterm.c,
>> + video/video.c.
>> + Removed term/i386/pc/vesafb.c.
>> +
>> + * conf/i386-pc.rmk (pkgdata_MODULES): Added video.mod,
>> + videoterm.mod.
>> + Removed vga.mod, vesafb.mod.
>
> Just put the removed line on the same line as where you say things
> were added. It looks a bit nicer and that is what we in general do.
Ok.
>
>> + * font/manager.c (fill_with_default_glyph): Modified to use
>> + grub_font_glyph.
>> + (grub_font_get_glyph): Modified to use grub_font_glyph.
>> + (fontmanager): Renamed to font_manager.
>> +
>> + * include/grub/font.h (grub_font_glyph): Added.
>
> Please say `New function.' or `New variable.'. It's in general better
> to do that, you can immediatly see what it is.
Ok.
>> + * include/grub/i386/pc/vbe.h (GRUB_VBE_STATUS_OK): Added.
>> + (GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL): Likewise.
>> + (GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR): Likewise.
>
> `New macro.' would be better.
Ok.
>
>> + (grub_vbe_get_controller_info): Renamed to
>> + grub_vbe_bios_get_controller_info.
>
> we use this syntax:
>
> (grub_vbe_get_controller_info): Renamed from this...
> (grub_vbe_bios_get_controller_info): ... to this. All users
> changed to use the new function name.
>
> It's important that it is visible that the new function did not just
> pop up. So now you can look back in the changelog entry where it was
> added.
Ok. I left out additional description as it would have made huge entries.
>> + * include/grub/video.h: Added.
>
> `New file.' is more consistent with the rest of GRUB.
Ok.
>
>> + * normal/cmdline.c (cl_set_pos): Made it refresh screen, to enable
>> + better visual experience to video drivers.
>
> Just use something like `Refresh the screen.'. It's a general bug
> fix, not only for the video drivers (although it unfortunately shows
> up there :)).
Ok.
>> + * term/videoterm.c: Added.
>> +
>> + * video/video.c: Added
>
> `New file.' again.
Ok.
>> + * video/i386/pc/vbe.c: Refactored to new video subsystem.
>
> Just leave away this line. Usually this is done by using `All users
> changed.' when interfaces change or functions are renamed.
Hmm. But then there is no mentioning about changes done in this file at
all?. (I have removed it from current diff.)
>> -# For vga.mod.
>> -vga_mod_SOURCES = term/i386/pc/vga.c
>> -vga_mod_CFLAGS = $(COMMON_CFLAGS)
>> -vga_mod_LDFLAGS = $(COMMON_LDFLAGS)
>
> Why do you remove this?
After modifying the fontmanager it would have needed to make some
changes to VGA code. And I am not familiar with VGA planes and such, so
I left it out.
>> include $(srcdir)/conf/common.mk
>> diff -ruN -x '*CVS*' grub2/font/manager.c grub2.new/font/manager.c
>> --- grub2/font/manager.c 2005-11-13 17:47:09.000000000 +0200
>> +++ grub2.new/font/manager.c 2006-02-25 14:16:16.000000000 +0200
>> @@ -24,6 +24,7 @@
>> #include <grub/types.h>
>> #include <grub/mm.h>
>> #include <grub/font.h>
>> +//#include <grub/gzio.h>
>
> Can you remove this line?
Sure.
>> struct entry
>> {
>> @@ -50,6 +51,7 @@
>> struct font *font = 0;
>>
>> file = grub_file_open (filename);
>> + //file = grub_gzfile_open (filename, 1);
>
> And this one.
Ok.
>
>> /* Get a glyph corresponding to the codepoint CODE. Always fill BITMAP
>> and WIDTH with something, even if no glyph is found. */
>> int
>> grub_font_get_glyph (grub_uint32_t code,
>> - unsigned char bitmap[32], unsigned *width)
>> + grub_font_glyph_t glyph)
>
> The prototype was changed, but the comment wasn't.
Oh, yes... Fixed.
>> {
>> struct font *font;
>> + grub_uint8_t bitmap[32];
>>
>> /* FIXME: It is necessary to cache glyphs! */
>>
>> @@ -183,12 +186,19 @@
>> if (offset)
>> {
>> grub_uint32_t w;
>> + grub_uint8_t x;
>> + grub_uint8_t y;
>> + grub_uint32_t len;
>
> Please just use int here. You read w from disk, so I understand why
> it is a grub_uint32_t, but the others don't come from disk, right?
Ok.
>> - if (grub_file_read (font->file, (char *) &w, 4) != 4)
>> + if ((len = grub_file_read (font->file, (char *) &w, 4)) != 4)
>
> I'm sorry that I am commenting on old code, but can you change this to
> some sizeof test or so?
Changed to sizeof (grub_uint32_t).
>> + glyph->baseline = (16*3)/4;
>
> Can you place some spaces around the operators, so:
>
> glyph->baseline = (16 * 3) / 4;
Sure. I must have forgotten this one.
>> +struct grub_font_glyph
>> +{
>> + /* Glyph width in pixels. */
>> + grub_uint8_t width;
>> +
>> + /* Glyph height in pixels. */
>> + grub_uint8_t height;
>> +
>> + /* Glyph width in characters. */
>> + grub_uint8_t char_width;
>> +
>> + /* Glyph baseline position in pixels (from up). */
>> + grub_uint8_t baseline;
>> +
>> + /* Glyph bitmap data array of bytes in ((width + 7) / 8) * height.
>> + Bitmap is formulated by height scanlines, each scanline having
>> + width number of pixels. Pixels are coded as bits, value 1 meaning
>> + of opaque pixel and 0 is transparent. If width does not fit byte
>> + boundary, it will be padded with 0 to make it fit. */
>> + grub_uint8_t bitmap[32];
>> +};
>> +
>> +typedef struct grub_font_glyph *grub_font_glyph_t;
>
> I hope Okuji will look at this, I am clueless about the font manager
> as for now. :-)
>
>> #endif /* ! GRUB_MISC_HEADER */
>> diff -ruN -x '*CVS*' grub2/include/grub/video.h grub2.new/include/grub/video.h
>> --- grub2/include/grub/video.h 1970-01-01 02:00:00.000000000 +0200
>> +++ grub2.new/include/grub/video.h 2006-03-02 15:33:32.650225312 +0200
>> @@ -0,0 +1,300 @@
>> +/*
>> + * GRUB -- GRand Unified Bootloader
>> + * Copyright (C) 2002,2003,2005 Free Software Foundation, Inc.
>
> I think it should just be 2006, right?
Yep ;)
>> +typedef grub_uint32_t grub_color_t;
>
> I think grub_video_color_t is better.
It is a long one, but changed.
>> +struct grub_video_mode_info {
>
> It think it is more appropriate to use `int' instead of
> `grub_uint32_t' for the members of this struct.
Ok.
>> +};
>
>> + grub_err_t (*get_info) (struct grub_video_mode_info * mode_info);
>
> Can you remove the space between `*' and `mode_info'?
Ok.
>> + grub_err_t (*get_viewport) (unsigned int * x,
>> + unsigned int * y,
>> + unsigned int * width,
>> + unsigned int * height);
>
> Same here. Please look at other places where you did this too.
Ok.
>> +struct grub_virtual_screen
>> +{
>> + /* Dimensions of the virual screen. */
>
> Typo.
>
> Can you change grub_uint32_t to ints inside this struct?
Fixed. Ok.
>> +};
>
>
>> +/* Make seure text buffer is not marked as allocated. */
>
> Typo: seure->sure
Fixed.
>> +static struct grub_virtual_screen virtual_screen =
>> + {
>> + .text_buffer = 0
>> + };
>
> You can leave away the initiazation, it is done automatically.
>
>> +static struct grub_video_render_target *text_layer = 0;
>
> Same here.
Ok.
>> + /* Cleare new render target for text layer. */
>
> Typo: Cleare->Create (right?)
Fixed.
>> + grub_video_create_render_target (&text_layer,
>> + GRUB_VIDEO_MODE_TYPE_RGB
>> + | GRUB_VIDEO_MODE_TYPE_ALPHA,
>> + virtual_screen.width,
>> + virtual_screen.height);
>
>> +static grub_err_t
>> +grub_videoterm_init (void)
>> +{
>> + char *modevar;
>> + int width = 1024;
>> + int height = 768;
>
> Please make macros for these defaults. In that case it can be easily
> changed without looking at the code.
Ok.
>> + /* Leave borders for virtual screen. */
>> + width = mode_info.width - (2 * 10);
>> + height = mode_info.height - (2 * 10);
>
> Can you explain this? Isn't it better to use some font width
> multiple?
It was something from the "hat". Basic idea here is here to show that it
can be anything. In future this most likely changes to something
completely different as we want(?) to have more flexibility on configure
things.
>> + if (x < dirty_region.top_left_x)
>> + {
>> + dirty_region.top_left_x = x;
>> + }
>
> You don't have to use { and } for a singe line. It makes this code
> hard to read. So please don't use it for such if statements.
I think the opposite, but changed.
>> diff -ruN -x '*CVS*' grub2/video/i386/pc/vbe.c grub2.new/video/i386/pc/vbe.c
>> --- grub2/video/i386/pc/vbe.c 2005-09-19 00:04:41.000000000 +0300
>> +++ grub2.new/video/i386/pc/vbe.c 2006-03-02 20:35:43.719014568 +0200
>> @@ -1,6 +1,6 @@
>> /*
>> * GRUB -- GRand Unified Bootloader
>> - * Copyright (C) 2005 Free Software Foundation, Inc.
>> + * Copyright (C) 2005-2006 Free Software Foundation, Inc.
>
> Please use commas to separate lines. For legal reasons a range of
> years is unfortunately not allowed.
Oh. Fixed.
>> + render_target->mode_info.bpp = active_mode_info.bits_per_pixel;
>> + render_target->mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel;
>> + render_target->mode_info.pitch = framebuffer.bytes_per_scan_line;
>> + render_target->mode_info.number_of_colors = 256; /* TODO: fix me. */
>> + render_target->mode_info.red_mask_size = active_mode_info.red_mask_size;
>> + render_target->mode_info.red_field_pos = active_mode_info.red_field_position;
>> + render_target->mode_info.green_mask_size = active_mode_info.green_mask_size;
>> + render_target->mode_info.green_field_pos = active_mode_info.green_field_position;
>> + render_target->mode_info.blue_mask_size = active_mode_info.blue_mask_size;
>> + render_target->mode_info.blue_field_pos = active_mode_info.blue_field_position;
>> + render_target->mode_info.reserved_mask_size = active_mode_info.rsvd_mask_size;
>> + render_target->mode_info.reserved_field_pos = active_mode_info.rsvd_field_position;
>
> Isn't it possible to copy this in a single statement?
No. As structure types are different.
>> + /* If we have negative coordintes, optimize drawing to minimum. */
>
> Typo.
Fixed.
>
>> + width = render_target->viewport.width - grub_abs(dx);
>> + height = render_target->viewport.height - grub_abs(dy);
>
> Please add a space after `grub_abs'.
Ok.
>> + // TODO: PROOFREAD THIS!.
>
> Ehm? :-)
Whups :).
>> +static grub_err_t
>> +grub_video_vbe_swap_buffers (void)
>> +{
>> + /* TODO: Implement buffer swapping. */
>
> Sin't this just activating another region in the video memory? I
> think it would be quite trivial when using VESA.
Depends if we have enough memory on card. But will be done. I was
intending to implement this functionality after we have version
in CVS.
>> + /* TODO: Implement other types too. */
>> + size = (width * 4) * height;
>
> Please use sizeof here.
I made different change :).
>> + /* Setup render target format. */
>> + target->mode_info.width = width;
>> + target->mode_info.height = height;
>> + target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB
>> + | GRUB_VIDEO_MODE_TYPE_ALPHA;
>> + target->mode_info.bpp = 32;
>> + target->mode_info.bytes_per_pixel = 4;
>> + target->mode_info.pitch = target->mode_info.bytes_per_pixel * width;
>> + target->mode_info.number_of_colors = 256;
>> + target->mode_info.red_mask_size = 8;
>> + target->mode_info.red_field_pos = 0;
>> + target->mode_info.green_mask_size = 8;
>> + target->mode_info.green_field_pos = 8;
>> + target->mode_info.blue_mask_size = 8;
>> + target->mode_info.blue_field_pos = 16;
>> + target->mode_info.reserved_mask_size = 8;
>> + target->mode_info.reserved_field_pos = 24;
>
> These are all defaults, right? First of all, I prefer macros instead
> of hardcoded values.
In most cases I would agree, but this one is something that should not
be modified. But if that is a real problem, then of course I will change it.
> bpp is set to 32, while number of colors says 256, are you sure this
> is correct? I prefer a bpp of 8 as default, for compatibility
> reasons.
number_of_colors tells how many indexed colors we have in mode. In RGB
rendering target we have always 256 emulated indexed colors.
As there is a comment in file (now perhaps better written), currently
only RGB rendering targets are supported. This is not a huge problem as
blit function can handle it even for indexed color modes.
>> +static grub_err_t
>> +grub_video_vbe_delete_render_target (struct grub_video_render_target * target)
>> +{
>> + /* If there is no target, then just return without error. */
>> + if (! target)
>> + {
>> + return GRUB_ERR_NONE;
>> + }
>
> No braces, like before. Same for the code below.
Ok.
>> +static grub_err_t
>> +grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)),
>> + int argc __attribute__ ((unused)),
>> + char **args __attribute__ ((unused)))
>
> It's better to move this to another file, like commands/videotest.c.
> Or do you think this is only useful for debugging, in that case better
> put it in some #ifdef.
Moved as new module.
[-- Attachment #2: grub2-video-20060303.diff --]
[-- Type: text/plain, Size: 123593 bytes --]
diff -ruN -x '*CVS*' grub2/ChangeLog grub2.new/ChangeLog
--- grub2/ChangeLog 2006-02-09 00:42:47.000000000 +0200
+++ grub2.new/ChangeLog 2006-03-03 16:51:42.214034272 +0200
@@ -1,3 +1,110 @@
+2006-02-25 Vesa Jaaskelainen <chaac@nic.fi>
+
+ * DISTLIST: Added include/grub/video.h, term/videoterm.c,
+ video/video.c. Removed term/i386/pc/vesafb.c.
+
+ * conf/i386-pc.rmk (pkgdata_MODULES): Added video.mod,
+ videoterm.mod, videotest.mod. Removed vga.mod, vesafb.mod.
+ (video_mod_SOURCES): Added.
+ (video_mod_CFLAGS): Likewise.
+ (video_mod_LDFLAGS): Likewise.
+ (videoterm_mod_SOURCES): Likewise.
+ (videoterm_mod_CFLAGS): Likewise.
+ (videoterm_mod_LDFLAGS): Likewise.
+ (videotest_mod_SOURCES): Likewise.
+ (videotest_mod_CFLAGS): Likewise.
+ (videotest_mod_LDFLAGS): Likewise.
+ (vesafb_mod_SOURCES): Removed.
+ (vesafb_mod_CFLAGS): Likewise.
+ (vesafb_mod_LDFLAGS): Likewise.
+ (vga_mod_SOURCES): Likewise.
+ (vga_mod_CFLAGS): Likewise.
+ (vga_mod_LDFLAGS): Likewise.
+
+ * commands/videotest.c: New file.
+
+ * font/manager.c (fill_with_default_glyph): Modified to use
+ grub_font_glyph.
+ (grub_font_get_glyph): Likewise.
+ (fontmanager): Renamed from this...
+ (font_manager): ... to this.
+
+ * include/grub/font.h (grub_font_glyph): Added new structure.
+ (grub_font_get_glyph): Modified to use grub_font_glyph.
+
+ * include/grub/misc.h (grub_abs): Added as inline function.
+
+ * include/grub/i386/pc/vbe.h (GRUB_VBE_STATUS_OK): New macro.
+ (GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL): Likewise.
+ (GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR): Likewise.
+ (grub_vbe_get_controller_info): Renamed from this...
+ (grub_vbe_bios_get_controller_info): ... to this.
+ (grub_vbe_get_mode_info): Renamed from this...
+ (grub_vbe_bios_get_mode_info): ... to this.
+ (grub_vbe_set_mode): Renamed from this...
+ (grub_vbe_bios_set_mode): ... to this.
+ (grub_vbe_get_mode): Renamed from this...
+ (grub_vbe_bios_get_mode): ... to this.
+ (grub_vbe_set_memory_window): Renamed from this...
+ (grub_vbe_bios_set_memory_window): ... to this.
+ (grub_vbe_get_memory_window): Renamed from this...
+ (grub_vbe_bios_get_memory_window): ... to this.
+ (grub_vbe_set_scanline_length): Renamed from this...
+ (grub_vbe_set_scanline_length): ... to this.
+ (grub_vbe_get_scanline_length): Renamed from this...
+ (grub_vbe_bios_get_scanline_length): ... to this.
+ (grub_vbe_set_display_start): Renamed from this...
+ (grub_vbe_bios_set_display_start): ... to this.
+ (grub_vbe_get_display_start): Renamed from this...
+ (grub_vbe_bios_get_display_start): ... to this.
+ (grub_vbe_set_palette_data): Renamed from this...
+ (grub_vbe_bios_set_palette_data): ... to this.
+ (grub_vbe_set_pixel_rgb): Removed.
+ (grub_vbe_set_pixel_index): Likewise.
+
+ * include/grub/video.h: New file.
+
+ * kern/i386/pc/startup.S (grub_vbe_get_controller_info): Renamed
+ from this...
+ (grub_vbe_bios_get_controller_info): ... to this.
+ (grub_vbe_get_mode_info): Renamed from this...
+ (grub_vbe_bios_get_mode_info): ... to this.
+ (grub_vbe_set_mode): Renamed from this...
+ (grub_vbe_bios_set_mode): ... to this.
+ (grub_vbe_get_mode): Renamed from this...
+ (grub_vbe_bios_get_mode): ... to this.
+ (grub_vbe_set_memory_window): Renamed from this...
+ (grub_vbe_bios_set_memory_window): ... to this.
+ (grub_vbe_get_memory_window): Renamed from this...
+ (grub_vbe_bios_get_memory_window): ... to this.
+ (grub_vbe_set_scanline_length): Renamed from this...
+ (grub_vbe_set_scanline_length): ... to this.
+ (grub_vbe_get_scanline_length): Renamed from this...
+ (grub_vbe_bios_get_scanline_length): ... to this.
+ (grub_vbe_set_display_start): Renamed from this...
+ (grub_vbe_bios_set_display_start): ... to this.
+ (grub_vbe_get_display_start): Renamed from this...
+ (grub_vbe_bios_get_display_start): ... to this.
+ (grub_vbe_set_palette_data): Renamed from this...
+ (grub_vbe_bios_set_palette_data): ... to this.
+ (grub_vbe_bios_get_controller_info): Fixed problem with registers
+ getting corrupted after calling it. Added more pushes and pops.
+ (grub_vbe_bios_set_mode): Likewise.
+ (grub_vbe_bios_get_mode): Likewise.
+ (grub_vbe_bios_get_memory_window): Likewise.
+ (grub_vbe_bios_set_scanline_length): Likewise.
+ (grub_vbe_bios_get_scanline_length): Likewise.
+ (grub_vbe_bios_get_display_start): Likewise.
+ (grub_vbe_bios_set_palette_data): Likewise.
+
+ * normal/cmdline.c (cl_set_pos): Refresh the screen.
+ (cl_insert): Likewise.
+ (cl_delete): Likewise.
+
+ * term/videoterm.c: New file.
+
+ * video/video.c: New file.
+
2006-02-01 Yoshinori K. Okuji <okuji@enbug.org>
* boot/i386/pc/boot.S (general_error): Before looping, try INT
diff -ruN -x '*CVS*' grub2/DISTLIST grub2.new/DISTLIST
--- grub2/DISTLIST 2005-12-26 01:04:28.000000000 +0200
+++ grub2.new/DISTLIST 2006-02-25 13:29:16.000000000 +0200
@@ -106,6 +106,7 @@
include/grub/terminfo.h
include/grub/tparm.h
include/grub/types.h
+include/grub/video.h
include/grub/i386/setjmp.h
include/grub/i386/types.h
include/grub/i386/pc/biosdisk.h
@@ -208,6 +209,7 @@
partmap/sun.c
term/terminfo.c
term/tparm.c
+term/videoterm.c
term/i386/pc/console.c
term/i386/pc/serial.c
term/i386/pc/vesafb.c
@@ -229,4 +231,5 @@
util/i386/pc/misc.c
util/powerpc/ieee1275/grub-mkimage.c
util/powerpc/ieee1275/misc.c
+video/video.c
video/i386/pc/vbe.c
diff -ruN -x '*CVS*' grub2/commands/videotest.c grub2.new/commands/videotest.c
--- grub2/commands/videotest.c 1970-01-01 02:00:00.000000000 +0200
+++ grub2.new/commands/videotest.c 2006-03-03 16:56:57.792059120 +0200
@@ -0,0 +1,133 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/machine/memory.h>
+#include <grub/video.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/arg.h>
+#include <grub/mm.h>
+#include <grub/font.h>
+#include <grub/term.h>
+
+static grub_err_t
+grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+ if (grub_video_setup (1024,
+ 768,
+ GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != GRUB_ERR_NONE)
+ {
+ return grub_errno;
+ }
+
+ grub_getkey ();
+
+ grub_video_color_t color;
+ unsigned int x, y, width, height;
+ int i;
+ struct grub_font_glyph glyph;
+ struct grub_video_render_target *text_layer;
+ grub_video_color_t palette[16];
+
+ grub_video_get_viewport (&x, &y, &width, &height);
+
+ grub_video_create_render_target (&text_layer,
+ GRUB_VIDEO_MODE_TYPE_RGB
+ | GRUB_VIDEO_MODE_TYPE_ALPHA,
+ width,
+ height);
+
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ color = grub_video_map_rgb (0, 0, 0);
+ grub_video_fill_rect (color, 0, 0, width, height);
+
+ color = grub_video_map_rgb (255,0,0);
+ grub_video_fill_rect (color, 0, 0, 100, 100);
+
+ color = grub_video_map_rgb (0,255,255);
+ grub_video_fill_rect (color, 100, 100, 100, 100);
+
+ grub_font_get_glyph ('*', &glyph);
+ grub_video_blit_glyph (&glyph, color, 200 ,0);
+
+ grub_video_set_viewport (x + 150, y + 150, width - 150*2, height - 150*2);
+ color = grub_video_map_rgb (77,33,77);
+ grub_video_fill_rect (color, 0, 0, width, height);
+
+ grub_video_set_active_render_target (text_layer);
+
+ color = grub_video_map_rgb (255,255,255);
+
+ grub_font_get_glyph ('A', &glyph);
+ grub_video_blit_glyph (&glyph, color, 16, 16);
+ grub_font_get_glyph ('B', &glyph);
+ grub_video_blit_glyph (&glyph, color, 16*2, 16);
+
+ grub_font_get_glyph ('*', &glyph);
+
+ for (i = 0; i < 16; i++)
+ {
+ color = grub_video_map_color (i);
+ palette[i] = color;
+ grub_video_blit_glyph (&glyph, color, 16 + i * 16, 32);
+ }
+
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ for (i = 0; i < 255; i++)
+ {
+ color = grub_video_map_rgb (i, 33, 77);
+ grub_video_fill_rect (color, 0, 0, width, height);
+ grub_video_blit_render_target (text_layer, 0, 0, 0, 0, width, height);
+ }
+
+ grub_getkey ();
+
+ grub_video_delete_render_target (text_layer);
+
+ grub_video_restore ();
+
+ for (i = 0; i < 16; i++)
+ {
+ grub_printf("color %d: %08x\n", i, palette[i]);
+ }
+
+ grub_errno = GRUB_ERR_NONE;
+ return grub_errno;
+}
+
+GRUB_MOD_INIT(videotest)
+{
+ grub_register_command ("videotest",
+ grub_cmd_videotest,
+ GRUB_COMMAND_FLAG_BOTH,
+ "videotest",
+ "Test video subsystem",
+ 0);
+}
+
+GRUB_MOD_FINI(videotest)
+{
+ grub_unregister_command ("videotest");
+}
diff -ruN -x '*CVS*' grub2/conf/i386-pc.rmk grub2.new/conf/i386-pc.rmk
--- grub2/conf/i386-pc.rmk 2005-12-26 01:04:29.000000000 +0200
+++ grub2.new/conf/i386-pc.rmk 2006-03-03 16:56:09.548393272 +0200
@@ -113,9 +113,10 @@
grub_install_SOURCES = util/i386/pc/grub-install.in
# Modules.
-pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod vga.mod \
+pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod \
_multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod \
- vbe.mod vesafb.mod vbetest.mod vbeinfo.mod play.mod
+ vbe.mod vbetest.mod vbeinfo.mod video.mod videoterm.mod \
+ videotest.mod play.mod
# For _chain.mod.
_chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -157,11 +158,6 @@
halt_mod_CFLAGS = $(COMMON_CFLAGS)
halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
-# For vga.mod.
-vga_mod_SOURCES = term/i386/pc/vga.c
-vga_mod_CFLAGS = $(COMMON_CFLAGS)
-vga_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
# For serial.mod.
serial_mod_SOURCES = term/i386/pc/serial.c
serial_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -182,11 +178,6 @@
vbe_mod_CFLAGS = $(COMMON_CFLAGS)
vbe_mod_LDFLAGS = $(COMMON_LDFLAGS)
-# For vesafb.mod.
-vesafb_mod_SOURCES = term/i386/pc/vesafb.c
-vesafb_mod_CFLAGS = $(COMMON_CFLAGS)
-vesafb_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
# For vbeinfo.mod.
vbeinfo_mod_SOURCES = commands/i386/pc/vbeinfo.c
vbeinfo_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -202,4 +193,19 @@
play_mod_CFLAGS = $(COMMON_CFLAGS)
play_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For video.mod.
+video_mod_SOURCES = video/video.c
+video_mod_CFLAGS = $(COMMON_CFLAGS)
+video_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For videoterm.mod.
+videoterm_mod_SOURCES = term/videoterm.c
+videoterm_mod_CFLAGS = $(COMMON_CFLAGS)
+videoterm_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For videotest.mod.
+videotest_mod_SOURCES = commands/videotest.c
+videotest_mod_CFLAGS = $(COMMON_CFLAGS)
+videotest_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff -ruN -x '*CVS*' grub2/font/manager.c grub2.new/font/manager.c
--- grub2/font/manager.c 2005-11-13 17:47:09.000000000 +0200
+++ grub2.new/font/manager.c 2006-03-03 15:55:20.440376240 +0200
@@ -151,26 +151,27 @@
/* Set the glyph to something stupid. */
static void
-fill_with_default_glyph (unsigned char bitmap[32], unsigned *width)
+fill_with_default_glyph (grub_font_glyph_t glyph)
{
- if (bitmap)
- {
- unsigned i;
+ unsigned i;
- for (i = 0; i < 16; i++)
- bitmap[i] = (i & 1) ? 0x55 : 0xaa;
- }
-
- *width = 1;
+ for (i = 0; i < 16; i++)
+ glyph->bitmap[i] = (i & 1) ? 0x55 : 0xaa;
+
+ glyph->char_width = 1;
+ glyph->width = glyph->char_width * 8;
+ glyph->height = 16;
+ glyph->baseline = (16*3)/4;
}
-/* Get a glyph corresponding to the codepoint CODE. Always fill BITMAP
- and WIDTH with something, even if no glyph is found. */
+/* Get a glyph corresponding to the codepoint CODE. Always fill glyph
+ information with something, even if no glyph is found. */
int
grub_font_get_glyph (grub_uint32_t code,
- unsigned char bitmap[32], unsigned *width)
+ grub_font_glyph_t glyph)
{
struct font *font;
+ grub_uint8_t bitmap[32];
/* FIXME: It is necessary to cache glyphs! */
@@ -183,12 +184,19 @@
if (offset)
{
grub_uint32_t w;
+ unsigned int x;
+ unsigned int y;
+ int len;
+
+ /* Make sure we can find glyphs for error messages. Push active
+ error message to error stack and reset error message. */
+ grub_error_push ();
grub_file_seek (font->file, offset);
- if (grub_file_read (font->file, (char *) &w, 4) != 4)
+ if ((len = grub_file_read (font->file, (char *) &w, sizeof (w))) != 4)
{
- remove_font (font);
- goto restart;
+ remove_font (font);
+ goto restart;
}
w = grub_le_to_cpu32 (w);
@@ -206,14 +214,30 @@
remove_font (font);
goto restart;
}
-
- *width = w;
+
+ /* Temporary workaround, fix font bitmap. */
+ for (y = 0; y < 16; y++)
+ {
+ for (x = 0; x < w; x++)
+ {
+ glyph->bitmap[y * w + x] = bitmap[x * 16 + y];
+ }
+ }
+
+ glyph->char_width = w;
+ glyph->width = glyph->char_width * 8;
+ glyph->height = 16;
+ glyph->baseline = (16 * 3) / 4;
+
+ /* Restore old error message. */
+ grub_error_pop ();
+
return 1;
}
}
/* Uggh... No font was found. */
- fill_with_default_glyph (bitmap, width);
+ fill_with_default_glyph (glyph);
return 0;
}
@@ -232,7 +256,7 @@
return 0;
}
-GRUB_MOD_INIT(fontmanager)
+GRUB_MOD_INIT(font_manager)
{
(void) mod; /* Stop warning. */
grub_register_command ("font", font_command, GRUB_COMMAND_FLAG_BOTH,
@@ -240,7 +264,7 @@
"Specify one or more font files to display.", 0);
}
-GRUB_MOD_FINI(fontmanager)
+GRUB_MOD_FINI(font_manager)
{
grub_unregister_command ("font");
}
diff -ruN -x '*CVS*' grub2/include/grub/font.h grub2.new/include/grub/font.h
--- grub2/include/grub/font.h 2004-04-04 16:46:00.000000000 +0300
+++ grub2.new/include/grub/font.h 2006-02-25 13:43:08.000000000 +0200
@@ -24,7 +24,31 @@
#define GRUB_FONT_MAGIC "PPF\x7f"
+struct grub_font_glyph
+{
+ /* Glyph width in pixels. */
+ grub_uint8_t width;
+
+ /* Glyph height in pixels. */
+ grub_uint8_t height;
+
+ /* Glyph width in characters. */
+ grub_uint8_t char_width;
+
+ /* Glyph baseline position in pixels (from up). */
+ grub_uint8_t baseline;
+
+ /* Glyph bitmap data array of bytes in ((width + 7) / 8) * height.
+ Bitmap is formulated by height scanlines, each scanline having
+ width number of pixels. Pixels are coded as bits, value 1 meaning
+ of opaque pixel and 0 is transparent. If width does not fit byte
+ boundary, it will be padded with 0 to make it fit. */
+ grub_uint8_t bitmap[32];
+};
+
+typedef struct grub_font_glyph *grub_font_glyph_t;
+
int grub_font_get_glyph (grub_uint32_t code,
- unsigned char bitmap[32], unsigned *width);
+ grub_font_glyph_t glyph);
#endif /* ! GRUB_FONT_HEADER */
diff -ruN -x '*CVS*' grub2/include/grub/i386/pc/vbe.h grub2.new/include/grub/i386/pc/vbe.h
--- grub2/include/grub/i386/pc/vbe.h 2005-08-16 21:34:17.000000000 +0300
+++ grub2.new/include/grub/i386/pc/vbe.h 2006-03-03 16:47:37.589222896 +0200
@@ -27,6 +27,13 @@
/* Default video mode to be used. */
#define GRUB_VBE_DEFAULT_VIDEO_MODE 0x101
+/* VBE status codes. */
+#define GRUB_VBE_STATUS_OK 0x004f
+
+/* VBE memory model types. */
+#define GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL 0x04
+#define GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR 0x06
+
/* Note:
Please refer to VESA BIOS Extension 3.0 Specification for more descriptive
@@ -147,45 +154,45 @@
/* Prototypes for kernel real mode thunks. */
/* Call VESA BIOS 0x4f00 to get VBE Controller Information, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_controller_info) (struct grub_vbe_info_block *controller_info);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_controller_info) (struct grub_vbe_info_block *controller_info);
/* Call VESA BIOS 0x4f01 to get VBE Mode Information, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_mode_info) (grub_uint32_t mode,
- struct grub_vbe_mode_info_block *mode_info);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_mode_info) (grub_uint32_t mode,
+ struct grub_vbe_mode_info_block *mode_info);
/* Call VESA BIOS 0x4f02 to set video mode, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_mode) (grub_uint32_t mode,
- struct grub_vbe_crtc_info_block *crtc_info);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_mode) (grub_uint32_t mode,
+ struct grub_vbe_crtc_info_block *crtc_info);
/* Call VESA BIOS 0x4f03 to return current VBE Mode, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_mode) (grub_uint32_t *mode);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_mode) (grub_uint32_t *mode);
/* Call VESA BIOS 0x4f05 to set memory window, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_memory_window) (grub_uint32_t window,
- grub_uint32_t position);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_memory_window) (grub_uint32_t window,
+ grub_uint32_t position);
/* Call VESA BIOS 0x4f05 to return memory window, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_memory_window) (grub_uint32_t window,
- grub_uint32_t *position);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_memory_window) (grub_uint32_t window,
+ grub_uint32_t *position);
/* Call VESA BIOS 0x4f06 to set scanline length (in bytes), return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_scanline_length) (grub_uint32_t length);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_scanline_length) (grub_uint32_t length);
/* Call VESA BIOS 0x4f06 to return scanline length (in bytes), return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_scanline_length) (grub_uint32_t *length);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_scanline_length) (grub_uint32_t *length);
/* Call VESA BIOS 0x4f07 to set display start, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_display_start) (grub_uint32_t x,
- grub_uint32_t y);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_display_start) (grub_uint32_t x,
+ grub_uint32_t y);
/* Call VESA BIOS 0x4f07 to get display start, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_display_start) (grub_uint32_t *x,
- grub_uint32_t *y);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_display_start) (grub_uint32_t *x,
+ grub_uint32_t *y);
/* Call VESA BIOS 0x4f09 to set palette data, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_palette_data) (grub_uint32_t color_count,
- grub_uint32_t start_index,
- struct grub_vbe_palette_data *palette_data);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_palette_data) (grub_uint32_t color_count,
+ grub_uint32_t start_index,
+ struct grub_vbe_palette_data *palette_data);
/* Prototypes for helper functions. */
@@ -195,13 +202,5 @@
grub_err_t grub_vbe_get_video_mode (grub_uint32_t *mode);
grub_err_t grub_vbe_get_video_mode_info (grub_uint32_t mode,
struct grub_vbe_mode_info_block *mode_info);
-void grub_vbe_set_pixel_rgb (grub_uint32_t x,
- grub_uint32_t y,
- grub_uint8_t red,
- grub_uint8_t green,
- grub_uint8_t blue);
-void grub_vbe_set_pixel_index (grub_uint32_t x,
- grub_uint32_t y,
- grub_uint8_t color);
#endif /* ! GRUB_VBE_MACHINE_HEADER */
diff -ruN -x '*CVS*' grub2/include/grub/misc.h grub2.new/include/grub/misc.h
--- grub2/include/grub/misc.h 2005-10-24 13:23:46.000000000 +0300
+++ grub2.new/include/grub/misc.h 2006-03-02 20:40:08.000000000 +0200
@@ -76,4 +76,14 @@
const grub_uint8_t *src,
grub_size_t size);
+/* Inline functions. */
+static inline unsigned int
+grub_abs (int x)
+{
+ if (x < 0)
+ return (unsigned int)(-x);
+ else
+ return (unsigned int)x;
+}
+
#endif /* ! GRUB_MISC_HEADER */
diff -ruN -x '*CVS*' grub2/include/grub/video.h grub2.new/include/grub/video.h
--- grub2/include/grub/video.h 1970-01-01 02:00:00.000000000 +0200
+++ grub2.new/include/grub/video.h 2006-03-03 16:48:40.981585792 +0200
@@ -0,0 +1,301 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006 Free Software Foundation, Inc.
+ *
+ * GRUB is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef GRUB_VIDEO_HEADER
+#define GRUB_VIDEO_HEADER 1
+
+#include <grub/err.h>
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+typedef grub_uint32_t grub_video_color_t;
+
+struct grub_video_render_target;
+
+/* Defines used to describe video mode or rendering target. */
+#define GRUB_VIDEO_MODE_TYPE_ALPHA 0x00000008
+#define GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED 0x00000004
+#define GRUB_VIDEO_MODE_TYPE_INDEX_COLOR 0x00000002
+#define GRUB_VIDEO_MODE_TYPE_RGB 0x00000001
+
+/* Defines used to mask flags. */
+#define GRUB_VIDEO_MODE_TYPE_COLOR_MASK 0x00000003
+
+/* Defined predefined render targets. */
+#define GRUB_VIDEO_RENDER_TARGET_DISPLAY ((struct grub_video_render_target *) 0)
+#define GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER ((struct grub_video_render_target *) 0)
+#define GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER ((struct grub_video_render_target *) 1)
+
+struct grub_video_mode_info {
+ /* Width of the screen. */
+ unsigned int width;
+
+ /* Height of the screen. */
+ unsigned int height;
+
+ /* Mode type bitmask. Contains information like is it Index color or
+ RGB mode. */
+ unsigned int mode_type;
+
+ /* Bits per pixel. */
+ unsigned int bpp;
+
+ /* Bytes per pixel. */
+ unsigned int bytes_per_pixel;
+
+ /* Pitch of one scanline. How many bytes there are for scanline. */
+ unsigned int pitch;
+
+ /* In index color mode, number of colors. In RGB mode this is 256. */
+ unsigned int number_of_colors;
+
+ /* How many bits are reserved for red color. */
+ unsigned int red_mask_size;
+
+ /* What is location of red color bits. In Index Color mode, this is 0. */
+ unsigned int red_field_pos;
+
+ /* How many bits are reserved for green color. */
+ unsigned int green_mask_size;
+
+ /* What is location of green color bits. In Index Color mode, this is 0. */
+ unsigned int green_field_pos;
+
+ /* How many bits are reserved for blue color. */
+ unsigned int blue_mask_size;
+
+ /* What is location of blue color bits. In Index Color mode, this is 0. */
+ unsigned int blue_field_pos;
+
+ /* How many bits are reserved in color. */
+ unsigned int reserved_mask_size;
+
+ /* What is location of reserved color bits. In Index Color mode,
+ this is 0. */
+ unsigned int reserved_field_pos;
+};
+
+struct grub_video_render_target {
+ /* Copy of the screen's mode info structure, except that width, height and
+ mode_type has been re-adjusted to requested render target settings. */
+ struct grub_video_mode_info mode_info;
+
+ struct {
+ unsigned int x;
+ unsigned int y;
+ unsigned int width;
+ unsigned int height;
+ } viewport;
+
+ /* Indicates wether the data has been allocated by us and must be freed
+ when render target is destroyed. */
+ int is_allocated;
+
+ /* Pointer to data. Can either be in video card memory or in local host's
+ memory. */
+ void *data;
+};
+
+struct grub_video_palette_data {
+ grub_uint8_t r; /* Red color value (0-255). */
+ grub_uint8_t g; /* Green color value (0-255). */
+ grub_uint8_t b; /* Blue color value (0-255). */
+ grub_uint8_t a; /* Reserved bits value (0-255). */
+};
+
+struct grub_font_glyph;
+struct grub_video_bitmap;
+
+struct grub_video_adapter
+{
+ /* The video adapter name. */
+ const char *name;
+
+ /* Initialize the video adapter. */
+ grub_err_t (*init) (void);
+
+ /* Clean up the video adapter. */
+ grub_err_t (*fini) (void);
+
+ grub_err_t (*setup) (unsigned int width,
+ unsigned int height,
+ unsigned int mode_type);
+
+ grub_err_t (*get_info) (struct grub_video_mode_info *mode_info);
+
+ grub_err_t (*set_palette) (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data);
+
+ grub_err_t (*get_palette) (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data);
+
+ grub_err_t (*set_viewport) (unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height);
+
+ grub_err_t (*get_viewport) (unsigned int *x,
+ unsigned int *y,
+ unsigned int *width,
+ unsigned int *height);
+
+ grub_video_color_t (*map_color) (grub_uint32_t color_name);
+
+ grub_video_color_t (*map_rgb) (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue);
+
+ grub_video_color_t (*map_rgba) (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue,
+ grub_uint8_t alpha);
+
+ grub_err_t (*fill_rect) (grub_video_color_t color,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height);
+
+ grub_err_t (*blit_glyph) (struct grub_font_glyph *glyph,
+ grub_video_color_t color,
+ int x,
+ int y);
+
+ grub_err_t (*blit_bitmap) (struct grub_video_bitmap *bitmap,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height);
+
+ grub_err_t (*blit_render_target) (struct grub_video_render_target *source,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height);
+
+ grub_err_t (*scroll) (grub_video_color_t color,
+ int dx,
+ int dy);
+
+ grub_err_t (*swap_buffers) (void);
+
+ grub_err_t (*create_render_target) (struct grub_video_render_target **result,
+ unsigned int mode_type,
+ unsigned int width,
+ unsigned int height);
+
+ grub_err_t (*delete_render_target) (struct grub_video_render_target *target);
+
+ grub_err_t (*set_active_render_target) (struct grub_video_render_target *target);
+
+ /* The next video adapter. */
+ struct grub_video_adapter *next;
+};
+typedef struct grub_video_adapter *grub_video_adapter_t;
+
+void EXPORT_FUNC(grub_video_register) (grub_video_adapter_t adapter);
+void EXPORT_FUNC(grub_video_unregister) (grub_video_adapter_t adapter);
+void EXPORT_FUNC(grub_video_iterate) (int (*hook) (grub_video_adapter_t adapter));
+
+grub_err_t EXPORT_FUNC(grub_video_setup) (unsigned int width,
+ unsigned int height,
+ unsigned int mode_type);
+
+grub_err_t EXPORT_FUNC(grub_video_restore) (void);
+
+grub_err_t EXPORT_FUNC(grub_video_get_info) (struct grub_video_mode_info *mode_info);
+
+grub_err_t EXPORT_FUNC(grub_video_set_palette) (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data);
+
+grub_err_t EXPORT_FUNC(grub_video_get_palette) (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data);
+
+grub_err_t EXPORT_FUNC(grub_video_set_viewport) (unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_get_viewport) (unsigned int *x,
+ unsigned int *y,
+ unsigned int *width,
+ unsigned int *height);
+
+grub_video_color_t EXPORT_FUNC(grub_video_map_color) (grub_uint32_t color_name);
+
+grub_video_color_t EXPORT_FUNC(grub_video_map_rgb) (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue);
+
+grub_video_color_t EXPORT_FUNC(grub_video_map_rgba) (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue,
+ grub_uint8_t alpha);
+
+grub_err_t EXPORT_FUNC(grub_video_fill_rect) (grub_video_color_t color,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_blit_glyph) (struct grub_font_glyph *glyph,
+ grub_video_color_t color,
+ int x,
+ int y);
+
+grub_err_t EXPORT_FUNC(grub_video_blit_bitmap) (struct grub_video_bitmap *bitmap,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_blit_render_target) (struct grub_video_render_target *source,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_scroll) (grub_video_color_t color,
+ int dx,
+ int dy);
+
+grub_err_t EXPORT_FUNC(grub_video_swap_buffers) (void);
+
+grub_err_t EXPORT_FUNC(grub_video_create_render_target) (struct grub_video_render_target **result,
+ unsigned int mode_type,
+ unsigned int width,
+ unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_delete_render_target) (struct grub_video_render_target *target);
+
+grub_err_t EXPORT_FUNC(grub_video_set_active_render_target) (struct grub_video_render_target *target);
+
+#endif /* ! GRUB_VIDEO_HEADER */
diff -ruN -x '*CVS*' grub2/kern/i386/pc/startup.S grub2.new/kern/i386/pc/startup.S
--- grub2/kern/i386/pc/startup.S 2005-10-15 20:28:36.000000000 +0300
+++ grub2.new/kern/i386/pc/startup.S 2006-03-02 14:14:06.000000000 +0200
@@ -1758,14 +1758,15 @@
ret
/*
- * grub_vbe_status_t grub_vbe_get_controller_info (struct grub_vbe_info_block *controller_info)
+ * grub_vbe_bios_status_t grub_vbe_get_controller_info (struct grub_vbe_info_block *controller_info)
*
* Register allocations for parameters:
* %eax *controller_info
*/
-FUNCTION(grub_vbe_get_controller_info)
+FUNCTION(grub_vbe_bios_get_controller_info)
pushl %ebp
pushl %edi
+ pushl %edx
movw %ax, %di /* Store *controller_info to %edx:%di. */
xorw %ax, %ax
@@ -1791,19 +1792,20 @@
movl %edx, %eax
andl $0x0FFFF, %eax /* Return value in %eax. */
+ pop %edx
popl %edi
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_get_mode_info (grub_uint32_t mode,
- * struct grub_vbe_mode_info_block *mode_info)
+ * grub_vbe_status_t grub_vbe_bios_get_mode_info (grub_uint32_t mode,
+ * struct grub_vbe_mode_info_block *mode_info)
*
* Register allocations for parameters:
* %eax mode
* %edx *mode_info
*/
-FUNCTION(grub_vbe_get_mode_info)
+FUNCTION(grub_vbe_bios_get_mode_info)
pushl %ebp
pushl %edi
@@ -1837,16 +1839,17 @@
ret
/*
- * grub_vbe_status_t grub_vbe_set_mode (grub_uint32_t mode,
- * struct grub_vbe_crtc_info_block *crtc_info)
+ * grub_vbe_status_t grub_vbe_bios_set_mode (grub_uint32_t mode,
+ * struct grub_vbe_crtc_info_block *crtc_info)
*
* Register allocations for parameters:
* %eax mode
* %edx *crtc_info
*/
-FUNCTION(grub_vbe_set_mode)
+FUNCTION(grub_vbe_bios_set_mode)
pushl %ebp
pushl %ebx
+ pushl %edi
movl %eax, %ebx /* Store mode in %ebx. */
@@ -1874,19 +1877,22 @@
movw %dx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edi
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_get_mode (grub_uint32_t *mode)
+ * grub_vbe_status_t grub_vbe_bios_get_mode (grub_uint32_t *mode)
*
* Register allocations for parameters:
* %eax *mode
*/
-FUNCTION(grub_vbe_get_mode)
+FUNCTION(grub_vbe_bios_get_mode)
pushl %ebp
pushl %ebx
+ pushl %edi
+ pushl %edx
pushl %eax /* Push *mode to stack. */
call prot_to_real
@@ -1907,19 +1913,21 @@
movw %dx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edx
+ popl %edi
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_set_memory_window (grub_uint32_t window,
- * grub_uint32_t position);
+ * grub_vbe_status_t grub_vbe_bios_set_memory_window (grub_uint32_t window,
+ * grub_uint32_t position);
*
* Register allocations for parameters:
* %eax window
* %edx position
*/
-FUNCTION(grub_vbe_set_memory_window)
+FUNCTION(grub_vbe_bios_set_memory_window)
pushl %ebp
pushl %ebx
@@ -1945,16 +1953,17 @@
ret
/*
- * grub_vbe_status_t grub_vbe_get_memory_window (grub_uint32_t window,
- * grub_uint32_t *position);
+ * grub_vbe_status_t grub_vbe_bios_get_memory_window (grub_uint32_t window,
+ * grub_uint32_t *position);
*
* Register allocations for parameters:
* %eax window
* %edx *position
*/
-FUNCTION(grub_vbe_get_memory_window)
+FUNCTION(grub_vbe_bios_get_memory_window)
pushl %ebp
pushl %ebx
+ pushl %edi
pushl %edx /* Push *position to stack. */
movl %eax, %ebx /* Store window in %ebx. */
@@ -1979,19 +1988,21 @@
movw %bx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edi
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_set_scanline_length (grub_uint32_t length)
+ * grub_vbe_status_t grub_vbe_bios_set_scanline_length (grub_uint32_t length)
*
* Register allocations for parameters:
* %eax length
*/
-FUNCTION(grub_vbe_set_scanline_length)
+FUNCTION(grub_vbe_bios_set_scanline_length)
pushl %ebp
pushl %ebx
+ pushl %edx
movl %eax, %ecx /* Store length in %ecx. */
@@ -2010,19 +2021,21 @@
movw %dx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edx
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_get_scanline_length (grub_uint32_t *length)
+ * grub_vbe_status_t grub_vbe_bios_get_scanline_length (grub_uint32_t *length)
*
* Register allocations for parameters:
* %eax *length
*/
-FUNCTION(grub_vbe_get_scanline_length)
+FUNCTION(grub_vbe_bios_get_scanline_length)
pushl %ebp
pushl %ebx
+ pushl %edi
pushl %edx /* Push *length to stack. */
call prot_to_real
@@ -2044,19 +2057,20 @@
movw %dx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edi
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_set_display_start (grub_uint32_t x,
- * grub_uint32_t y)
+ * grub_vbe_status_t grub_vbe_bios_set_display_start (grub_uint32_t x,
+ * grub_uint32_t y)
*
* Register allocations for parameters:
* %eax x
* %edx y
*/
-FUNCTION(grub_vbe_set_display_start)
+FUNCTION(grub_vbe_bios_set_display_start)
pushl %ebp
pushl %ebx
@@ -2083,16 +2097,17 @@
ret
/*
- * grub_vbe_status_t grub_vbe_get_display_start (grub_uint32_t *x,
- * grub_uint32_t *y)
+ * grub_vbe_status_t grub_vbe_bios_get_display_start (grub_uint32_t *x,
+ * grub_uint32_t *y)
*
* Register allocations for parameters:
* %eax *x
* %edx *y
*/
-FUNCTION(grub_vbe_get_display_start)
+FUNCTION(grub_vbe_bios_get_display_start)
pushl %ebp
pushl %ebx
+ pushl %edi
pushl %eax /* Push *x to stack. */
pushl %edx /* Push *y to stack. */
@@ -2119,23 +2134,25 @@
movw %bx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edi
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_set_palette_data (grub_uint32_t color_count,
- * grub_uint32_t start_index,
- * struct grub_vbe_palette_data *palette_data)
+ * grub_vbe_status_t grub_vbe_bios_set_palette_data (grub_uint32_t color_count,
+ * grub_uint32_t start_index,
+ * struct grub_vbe_palette_data *palette_data)
*
* Register allocations for parameters:
* %eax color_count
* %edx start_index
* %ecx *palette_data
*/
-FUNCTION(grub_vbe_set_palette_data)
+FUNCTION(grub_vbe_bios_set_palette_data)
pushl %ebp
pushl %ebx
+ pushl %edi
movl %eax, %ebx /* Store color_count in %ebx. */
@@ -2165,6 +2182,7 @@
movw %dx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edi
popl %ebx
popl %ebp
ret
diff -ruN -x '*CVS*' grub2/normal/cmdline.c grub2.new/normal/cmdline.c
--- grub2/normal/cmdline.c 2005-08-28 20:01:16.000000000 +0300
+++ grub2.new/normal/cmdline.c 2006-02-25 14:50:44.000000000 +0200
@@ -231,6 +231,8 @@
xpos = (plen + lpos) % 79;
ypos = ystart + (plen + lpos) / 79;
grub_gotoxy (xpos, ypos);
+
+ grub_refresh ();
}
void cl_print (int pos, int c)
@@ -271,6 +273,8 @@
cl_print (lpos - len, echo_char);
cl_set_pos ();
}
+
+ grub_refresh ();
}
void cl_delete (unsigned len)
@@ -290,6 +294,8 @@
cl_print (lpos, echo_char);
cl_set_pos ();
}
+
+ grub_refresh ();
}
plen = grub_strlen (prompt);
diff -ruN -x '*CVS*' grub2/term/videoterm.c grub2.new/term/videoterm.c
--- grub2/term/videoterm.c 1970-01-01 02:00:00.000000000 +0200
+++ grub2.new/term/videoterm.c 2006-03-03 15:58:20.868946928 +0200
@@ -0,0 +1,877 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/machine/memory.h>
+#include <grub/machine/console.h>
+#include <grub/term.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/font.h>
+#include <grub/arg.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+#include <grub/video.h>
+
+#define DEFAULT_VIDEO_WIDTH 1024
+#define DEFAULT_VIDEO_HEIGHT 768
+#define DEFAULT_VIDEO_FLAGS 0
+
+#define DEFAULT_CHAR_WIDTH 8
+#define DEFAULT_CHAR_HEIGHT 16
+
+#define DEFAULT_FG_COLOR 0x0a
+#define DEFAULT_BG_COLOR 0x00
+#define DEFAULT_CURSOR_COLOR 0x0f
+
+struct grub_dirty_region
+{
+ int top_left_x;
+ int top_left_y;
+ int bottom_right_x;
+ int bottom_right_y;
+};
+
+struct grub_colored_char
+{
+ /* An Unicode codepoint. */
+ grub_uint32_t code;
+
+ /* Color values. */
+ grub_video_color_t fg_color;
+ grub_video_color_t bg_color;
+
+ /* The width of this character minus one. */
+ unsigned char width;
+
+ /* The column index of this character. */
+ unsigned char index;
+};
+
+struct grub_virtual_screen
+{
+ /* Dimensions of the virtual screen. */
+ unsigned int width;
+ unsigned int height;
+
+ /* Offset in the display. */
+ unsigned int offset_x;
+ unsigned int offset_y;
+
+ /* TTY Character sizes. */
+ unsigned int char_width;
+ unsigned int char_height;
+
+ /* Virtual screen TTY size. */
+ unsigned int columns;
+ unsigned int rows;
+
+ /* Current cursor details. */
+ unsigned int cursor_x;
+ unsigned int cursor_y;
+ int cursor_state;
+
+ /* Color settings. */
+ grub_video_color_t fg_color_setting;
+ grub_video_color_t bg_color_setting;
+ grub_video_color_t fg_color;
+ grub_video_color_t bg_color;
+ grub_video_color_t cursor_color;
+
+ /* Text buffer for virual screen. Contains (columns * rows) number
+ of entries. */
+ struct grub_colored_char *text_buffer;
+};
+
+static struct grub_virtual_screen virtual_screen;
+
+static grub_dl_t my_mod;
+static struct grub_video_mode_info mode_info;
+
+static struct grub_video_render_target *text_layer;
+
+static struct grub_dirty_region dirty_region;
+
+static void dirty_region_reset (void);
+
+static int dirty_region_is_empty (void);
+
+static void dirty_region_add (int x,
+ int y,
+ unsigned int width,
+ unsigned int height);
+
+static void
+grub_virtual_screen_free (void)
+{
+ /* If virtual screen has been allocated, free it. */
+ if (virtual_screen.text_buffer != 0)
+ grub_free (virtual_screen.text_buffer);
+
+ /* Reset virtual screen data. */
+ grub_memset (&virtual_screen, 0, sizeof (virtual_screen));
+
+ /* Free render targets. */
+ grub_video_delete_render_target (text_layer);
+ text_layer = 0;
+}
+
+static grub_err_t
+grub_virtual_screen_setup (unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height)
+{
+ /* Free old virtual screen. */
+ grub_virtual_screen_free ();
+
+ /* Initialize with default data. */
+ virtual_screen.width = width;
+ virtual_screen.height = height;
+ virtual_screen.offset_x = x;
+ virtual_screen.offset_y = y;
+ virtual_screen.char_width = DEFAULT_CHAR_WIDTH;
+ virtual_screen.char_height = DEFAULT_CHAR_HEIGHT;
+ virtual_screen.cursor_x = 0;
+ virtual_screen.cursor_y = 0;
+ virtual_screen.cursor_state = 1;
+
+ /* Calculate size of text buffer. */
+ virtual_screen.columns = virtual_screen.width / virtual_screen.char_width;
+ virtual_screen.rows = virtual_screen.height / virtual_screen.char_height;
+
+ /* Allocate memory for text buffer. */
+ virtual_screen.text_buffer =
+ (struct grub_colored_char *) grub_malloc (virtual_screen.columns
+ * virtual_screen.rows
+ * sizeof (*virtual_screen.text_buffer));
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Create new render target for text layer. */
+ grub_video_create_render_target (&text_layer,
+ GRUB_VIDEO_MODE_TYPE_RGB
+ | GRUB_VIDEO_MODE_TYPE_ALPHA,
+ virtual_screen.width,
+ virtual_screen.height);
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* As we want to have colors compatible with rendering target,
+ we can only have those after mode is initialized. */
+ grub_video_set_active_render_target (text_layer);
+
+ virtual_screen.fg_color_setting = grub_video_map_color (DEFAULT_FG_COLOR);
+ virtual_screen.bg_color_setting = grub_video_map_color (DEFAULT_BG_COLOR);
+ virtual_screen.fg_color = virtual_screen.fg_color_setting;
+ virtual_screen.bg_color = virtual_screen.bg_color_setting;
+ virtual_screen.cursor_color = grub_video_map_color (DEFAULT_CURSOR_COLOR);
+
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ return grub_errno;
+}
+
+static grub_err_t
+grub_videoterm_init (void)
+{
+ char *modevar;
+ int width = DEFAULT_VIDEO_WIDTH;
+ int height = DEFAULT_VIDEO_HEIGHT;
+ int flags = DEFAULT_VIDEO_FLAGS;
+ grub_video_color_t color;
+
+ /* Parse video_mode environment variable if set. */
+ modevar = grub_env_get ("video_mode");
+ if (modevar)
+ {
+ char *tmp;
+ char *param;
+ char *value;
+
+ /* Take copy of env.var. as we don't want to modify that. */
+ tmp = grub_strdup (modevar);
+ modevar = tmp;
+
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Skip whitespace. */
+ while (grub_isspace (*tmp))
+ tmp++;
+
+ /* Initialize token holders. */
+ param = tmp;
+ value = NULL;
+
+ /* Loop until all characters have been handled. */
+ while (1)
+ {
+ if (grub_isspace (*tmp) || (*tmp == 0))
+ {
+ /* If there are more variables, mark seperator with NUL. */
+ if (*tmp != 0)
+ *tmp++ = 0;
+
+ /* Analyze setting. */
+
+ /* Handle width=<number>. */
+ if ((grub_strcmp (param, "width") == 0) && (value != NULL))
+ {
+ width = grub_strtoul (value, 0, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_errno;
+ }
+ }
+
+ /* Handle height=<number>. */
+ if ((grub_strcmp (param, "height") == 0) && (value != NULL))
+ {
+ height = grub_strtoul (value, 0, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_errno;
+ }
+ }
+
+ /* Handle rgb. Used to request RGB mode. */
+ if ((grub_strcmp (param, "rgb") == 0) && (value == NULL))
+ {
+ flags &= ~GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+ flags |= GRUB_VIDEO_MODE_TYPE_RGB;
+ }
+
+ /* Handle index. Used to request index color mode. */
+ if ((grub_strcmp (param, "index") == 0) && (value == NULL))
+ {
+ flags &= ~GRUB_VIDEO_MODE_TYPE_RGB;
+ flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+ }
+
+ /* Handle double. Used to request double buffering mode. */
+ if ((grub_strcmp (param, "double") == 0) && (value == NULL))
+ flags |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
+
+ /* Handle <width>x<height>[x<depth>]*/
+ if (grub_isdigit (param[0]))
+ {
+ /* Find width value. */
+ value = param;
+ param = grub_strchr(param, 'x');
+ if (param == NULL)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "Invalid argument: %s\n",
+ param);
+ }
+
+ *param = 0;
+ param++;
+
+ width = grub_strtoul (value, 0, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_errno;
+ }
+
+ /* Find height value. */
+ value = param;
+ param = grub_strchr(param, 'x');
+ if (param == NULL)
+ {
+ height = grub_strtoul (value, 0, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_errno;
+ }
+ }
+ else
+ {
+ /* We have optional color depth value. */
+ *param = 0;
+ param++;
+
+ height = grub_strtoul (value, 0, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_errno;
+ }
+
+ /* Convert color depth value. */
+ value = param;
+#if 0
+ depth = grub_strtoul (value, 0, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_errno;
+ }
+#endif
+ }
+ }
+
+ /* Skip whitespace. */
+ while (grub_isspace (*tmp))
+ tmp++;
+
+ /* Check if we are at end of string. */
+ if (*tmp == 0)
+ break;
+
+ /* Initialize token holders. */
+ param = tmp;
+ value = NULL;
+ }
+
+ /* Check if there is value seperator. */
+ if (*tmp == '=')
+ {
+ *tmp++ = 0;
+ value = tmp;
+ }
+
+ /* Advance to next character. */
+ tmp++;
+ }
+
+ /* Free memory. */
+ grub_free (modevar);
+ }
+
+ /* Intialize user requested mode. */
+ if (grub_video_setup (width, height, flags) != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Figure out what mode we ended up. */
+ if (grub_video_get_info (&mode_info) != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Make sure screen is black. */
+ color = grub_video_map_rgb (0, 0, 0);
+ grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
+
+ /* Leave borders for virtual screen. */
+ width = mode_info.width - (2 * 10);
+ height = mode_info.height - (2 * 10);
+
+ /* Create virtual screen. */
+ if (grub_virtual_screen_setup (10,
+ 10,
+ width,
+ height) != GRUB_ERR_NONE)
+ {
+ grub_video_restore ();
+ return grub_errno;
+ }
+
+ /* Mark whole screen as dirty. */
+ dirty_region_reset ();
+ dirty_region_add (0, 0, mode_info.width, mode_info.height);
+
+ return (grub_errno = GRUB_ERR_NONE);
+}
+
+static grub_err_t
+grub_videoterm_fini (void)
+{
+ grub_virtual_screen_free ();
+
+ grub_video_restore ();
+
+ return GRUB_ERR_NONE;
+}
+
+static void
+redraw_screen_rect (unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height)
+{
+ grub_video_color_t color;
+
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ /* Render background layer. */
+ color = virtual_screen.bg_color;
+ grub_video_fill_rect (color, x, y, width, height);
+
+ /* Render text layer. */
+ grub_video_blit_render_target (text_layer,
+ x,
+ y,
+ x - virtual_screen.offset_x,
+ y - virtual_screen.offset_y,
+ width,
+ height);
+}
+
+static void
+dirty_region_reset (void)
+{
+ dirty_region.top_left_x = -1;
+ dirty_region.top_left_y = -1;
+ dirty_region.bottom_right_x = -1;
+ dirty_region.bottom_right_y = -1;
+}
+
+static int
+dirty_region_is_empty (void)
+{
+ if ((dirty_region.top_left_x == -1)
+ || (dirty_region.top_left_y == -1)
+ || (dirty_region.bottom_right_x == -1)
+ || (dirty_region.bottom_right_y == -1))
+ {
+ return 1;
+ }
+ return 0;
+}
+
+static void
+dirty_region_add (int x, int y, unsigned int width, unsigned int height)
+{
+ if ((width == 0) || (height == 0))
+ return;
+
+ if (dirty_region_is_empty ())
+ {
+ dirty_region.top_left_x = x;
+ dirty_region.top_left_y = y;
+ dirty_region.bottom_right_x = x + width - 1;
+ dirty_region.bottom_right_y = y + height - 1;
+ }
+ else
+ {
+ if (x < dirty_region.top_left_x)
+ {
+ dirty_region.top_left_x = x;
+ }
+ if (y < dirty_region.top_left_y)
+ {
+ dirty_region.top_left_y = y;
+ }
+ if ((x + (int)width - 1) > dirty_region.bottom_right_x)
+ {
+ dirty_region.bottom_right_x = x + width - 1;
+ }
+ if ((y + (int)height - 1) > dirty_region.bottom_right_y)
+ {
+ dirty_region.bottom_right_y = y + height - 1;
+ }
+ }
+}
+
+static void
+dirty_region_add_virtualscreen (void)
+{
+ /* Mark virtual screen as dirty. */
+ dirty_region_add (virtual_screen.offset_x, virtual_screen.offset_y,
+ virtual_screen.width, virtual_screen.height);
+}
+
+
+static void
+dirty_region_redraw (void)
+{
+ int x;
+ int y;
+ int width;
+ int height;
+
+ if (dirty_region_is_empty ())
+ return;
+
+ x = dirty_region.top_left_x;
+ y = dirty_region.top_left_y;
+
+ width = dirty_region.bottom_right_x - x + 1;
+ height = dirty_region.bottom_right_y - y + 1;
+
+ redraw_screen_rect (x, y, width, height);
+
+ dirty_region_reset ();
+}
+
+static void
+write_char (void)
+{
+ struct grub_colored_char *p;
+ struct grub_font_glyph glyph;
+ grub_video_color_t color;
+ grub_video_color_t bgcolor;
+ unsigned int x;
+ unsigned int y;
+
+ /* Find out active character. */
+ p = (virtual_screen.text_buffer
+ + virtual_screen.cursor_x
+ + (virtual_screen.cursor_y * virtual_screen.columns));
+
+ p -= p->index;
+
+ /* Get glyph for character. */
+ grub_font_get_glyph (p->code, &glyph);
+
+ color = p->fg_color;
+ bgcolor = p->bg_color;
+
+ x = virtual_screen.cursor_x * virtual_screen.char_width;
+ y = virtual_screen.cursor_y * virtual_screen.char_height;
+
+ /* Render glyph to text layer. */
+ grub_video_set_active_render_target (text_layer);
+ grub_video_fill_rect (bgcolor, x, y, glyph.width, glyph.height);
+ grub_video_blit_glyph (&glyph, color, x, y);
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ /* Mark character to be drawn. */
+ dirty_region_add (virtual_screen.offset_x + x,
+ virtual_screen.offset_y + y,
+ glyph.width,
+ glyph.height);
+}
+
+static void
+write_cursor (void)
+{
+ unsigned int x;
+ unsigned int y;
+ unsigned int width;
+ unsigned int height;
+ grub_video_color_t color;
+
+ /* Determine cursor properties and position on text layer. */
+ x = virtual_screen.cursor_x * virtual_screen.char_width;
+ y = ((virtual_screen.cursor_y + 1) * virtual_screen.char_height) - 3;
+ width = virtual_screen.char_width;
+ height = 2;
+
+ color = virtual_screen.cursor_color;
+
+ /* Render cursor to text layer. */
+ grub_video_set_active_render_target (text_layer);
+ grub_video_fill_rect (color, x, y, width, height);
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ /* Mark cursor to be redrawn. */
+ dirty_region_add (virtual_screen.offset_x + x,
+ virtual_screen.offset_y + y,
+ width,
+ height);
+}
+
+static void
+scroll_up (void)
+{
+ unsigned int i;
+ grub_video_color_t color;
+
+ /* Scroll text buffer with one line to up. */
+ grub_memmove (virtual_screen.text_buffer,
+ virtual_screen.text_buffer + virtual_screen.columns,
+ sizeof (*virtual_screen.text_buffer)
+ * virtual_screen.columns
+ * (virtual_screen.rows - 1));
+
+ /* Clear last line in text buffer. */
+ for (i = virtual_screen.columns * (virtual_screen.rows - 1);
+ i < virtual_screen.columns * virtual_screen.rows;
+ i++)
+ {
+ virtual_screen.text_buffer[i].code = ' ';
+ virtual_screen.text_buffer[i].fg_color = virtual_screen.fg_color;
+ virtual_screen.text_buffer[i].bg_color = virtual_screen.bg_color;
+ virtual_screen.text_buffer[i].width = 0;
+ virtual_screen.text_buffer[i].index = 0;
+ }
+
+ /* Scroll physical screen. */
+ grub_video_set_active_render_target (text_layer);
+ color = virtual_screen.bg_color;
+ grub_video_scroll (color, 0, -virtual_screen.char_height);
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ /* Mark virtual screen to be redrawn. */
+ dirty_region_add_virtualscreen ();
+}
+
+static void
+grub_videoterm_putchar (grub_uint32_t c)
+{
+ if (c == '\a')
+ /* FIXME */
+ return;
+
+ if (c == '\b' || c == '\n' || c == '\r')
+ {
+ /* Erase current cursor, if any. */
+ if (virtual_screen.cursor_state)
+ write_char ();
+
+ switch (c)
+ {
+ case '\b':
+ if (virtual_screen.cursor_x > 0)
+ virtual_screen.cursor_x--;
+ break;
+
+ case '\n':
+ if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
+ scroll_up ();
+ else
+ virtual_screen.cursor_y++;
+ break;
+
+ case '\r':
+ virtual_screen.cursor_x = 0;
+ break;
+ }
+
+ /* Redraw cursor if visible. */
+ if (virtual_screen.cursor_state)
+ write_cursor ();
+ }
+ else
+ {
+ struct grub_font_glyph glyph;
+ struct grub_colored_char *p;
+
+ /* Get properties of the character. */
+ grub_font_get_glyph (c, &glyph);
+
+ /* If we are about to exceed line length, wrap to next line. */
+ if (virtual_screen.cursor_x + glyph.char_width > virtual_screen.columns)
+ grub_putchar ('\n');
+
+ /* Find position on virtual screen, and fill information. */
+ p = (virtual_screen.text_buffer +
+ virtual_screen.cursor_x +
+ virtual_screen.cursor_y * virtual_screen.columns);
+ p->code = c;
+ p->fg_color = virtual_screen.fg_color;
+ p->bg_color = virtual_screen.bg_color;
+ p->width = glyph.char_width - 1;
+ p->index = 0;
+
+ /* If we have large glyph, add fixup info. */
+ if (glyph.char_width > 1)
+ {
+ unsigned i;
+
+ for (i = 1; i < glyph.char_width; i++)
+ {
+ p[i].code = ' ';
+ p[i].width = glyph.char_width - 1;
+ p[i].index = i;
+ }
+ }
+
+ /* Draw glyph. */
+ write_char ();
+
+ /* Make sure we scroll screen when needed and wrap line correctly. */
+ virtual_screen.cursor_x += glyph.char_width;
+ if (virtual_screen.cursor_x >= virtual_screen.columns)
+ {
+ virtual_screen.cursor_x = 0;
+
+ if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
+ scroll_up ();
+ else
+ virtual_screen.cursor_y++;
+ }
+
+ /* Draw cursor if visible. */
+ if (virtual_screen.cursor_state)
+ write_cursor ();
+ }
+}
+
+static grub_ssize_t
+grub_videoterm_getcharwidth (grub_uint32_t c)
+{
+ struct grub_font_glyph glyph;
+
+ if (! grub_font_get_glyph (c, &glyph))
+ return 0;
+
+ return glyph.char_width;
+}
+
+static grub_uint16_t
+grub_virtual_screen_getwh (void)
+{
+ return (virtual_screen.columns << 8) | virtual_screen.rows;
+}
+
+static grub_uint16_t
+grub_virtual_screen_getxy (void)
+{
+ return ((virtual_screen.cursor_x << 8) | virtual_screen.cursor_y);
+}
+
+static void
+grub_videoterm_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+ if (x >= virtual_screen.columns || y >= virtual_screen.rows)
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)",
+ (unsigned) x, (unsigned) y);
+ return;
+ }
+
+ if (virtual_screen.cursor_state)
+ write_char ();
+
+ virtual_screen.cursor_x = x;
+ virtual_screen.cursor_y = y;
+
+ if (virtual_screen.cursor_state)
+ write_cursor ();
+}
+
+static void
+grub_virtual_screen_cls (void)
+{
+ grub_uint32_t i;
+
+ for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++)
+ {
+ virtual_screen.text_buffer[i].code = ' ';
+ virtual_screen.text_buffer[i].fg_color = virtual_screen.fg_color;
+ virtual_screen.text_buffer[i].bg_color = virtual_screen.bg_color;
+ virtual_screen.text_buffer[i].width = 0;
+ virtual_screen.text_buffer[i].index = 0;
+ }
+
+ virtual_screen.cursor_x = virtual_screen.cursor_y = 0;
+}
+
+static void
+grub_videoterm_cls (void)
+{
+ grub_video_color_t color;
+
+ /* Clear virtual screen. */
+ grub_virtual_screen_cls ();
+
+ /* Clear text layer. */
+ grub_video_set_active_render_target (text_layer);
+ color = virtual_screen.bg_color_setting;
+ grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ /* Mark virtual screen to be redrawn. */
+ dirty_region_add_virtualscreen ();
+}
+
+static void
+grub_virtual_screen_setcolorstate (grub_term_color_state state)
+{
+ switch (state)
+ {
+ case GRUB_TERM_COLOR_STANDARD:
+ case GRUB_TERM_COLOR_NORMAL:
+ virtual_screen.fg_color = virtual_screen.fg_color_setting;
+ virtual_screen.bg_color = virtual_screen.bg_color_setting;
+ break;
+ case GRUB_TERM_COLOR_HIGHLIGHT:
+ virtual_screen.fg_color = virtual_screen.bg_color_setting;
+ virtual_screen.bg_color = virtual_screen.fg_color_setting;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+grub_virtual_screen_setcolor (grub_uint8_t normal_color __attribute__ ((unused)),
+ grub_uint8_t highlight_color __attribute__ ((unused)))
+{
+ virtual_screen.fg_color_setting = grub_video_map_color (normal_color);
+ virtual_screen.bg_color_setting = grub_video_map_color (highlight_color);
+}
+
+static void
+grub_videoterm_setcursor (int on)
+{
+ if (virtual_screen.cursor_state != on)
+ {
+ if (virtual_screen.cursor_state)
+ write_char ();
+ else
+ write_cursor ();
+
+ virtual_screen.cursor_state = on;
+ }
+}
+
+static void
+grub_videoterm_refresh (void)
+{
+ /* Redraw only changed regions. */
+ dirty_region_redraw ();
+}
+
+static struct grub_term grub_video_term =
+ {
+ .name = "videoterm",
+ .init = grub_videoterm_init,
+ .fini = grub_videoterm_fini,
+ .putchar = grub_videoterm_putchar,
+ .getcharwidth = grub_videoterm_getcharwidth,
+ .checkkey = grub_console_checkkey,
+ .getkey = grub_console_getkey,
+ .getwh = grub_virtual_screen_getwh,
+ .getxy = grub_virtual_screen_getxy,
+ .gotoxy = grub_videoterm_gotoxy,
+ .cls = grub_videoterm_cls,
+ .setcolorstate = grub_virtual_screen_setcolorstate,
+ .setcolor = grub_virtual_screen_setcolor,
+ .setcursor = grub_videoterm_setcursor,
+ .refresh = grub_videoterm_refresh,
+ .flags = 0,
+ .next = 0
+ };
+
+GRUB_MOD_INIT(term_videoterm)
+{
+ my_mod = mod;
+ grub_term_register (&grub_video_term);
+}
+
+GRUB_MOD_FINI(term_videoterm)
+{
+ grub_term_unregister (&grub_video_term);
+}
Files grub2/unifont.pff and grub2.new/unifont.pff differ
diff -ruN -x '*CVS*' grub2/video/i386/pc/vbe.c grub2.new/video/i386/pc/vbe.c
--- grub2/video/i386/pc/vbe.c 2005-09-19 00:04:41.000000000 +0300
+++ grub2.new/video/i386/pc/vbe.c 2006-03-03 16:57:36.187222168 +0200
@@ -1,6 +1,6 @@
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2005 Free Software Foundation, Inc.
+ * Copyright (C) 2005,2006 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,20 +17,20 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+/* General TODO's:
+ - Implement mode optimized operations and automatically select best
+
+*/
+
#include <grub/err.h>
#include <grub/machine/memory.h>
-#include <grub/machine/vga.h>
#include <grub/machine/vbe.h>
-#include <grub/machine/console.h>
-#include <grub/term.h>
#include <grub/types.h>
#include <grub/dl.h>
#include <grub/misc.h>
-#include <grub/normal.h>
#include <grub/font.h>
-#include <grub/arg.h>
#include <grub/mm.h>
-#include <grub/env.h>
+#include <grub/video.h>
/* Specify "standard" VGA palette, some video cards may
need this and this will also be used when using RGB modes. */
@@ -57,15 +57,52 @@
};
static int vbe_detected = -1;
-static int index_color_mode = 0;
static struct grub_vbe_info_block controller_info;
static struct grub_vbe_mode_info_block active_mode_info;
-static grub_uint32_t active_mode = 0;
+static struct {
+ struct grub_video_render_target render_target;
+
+ unsigned int bytes_per_scan_line;
+ unsigned int bytes_per_pixel;
+ grub_uint32_t active_mode;
+ grub_uint8_t *ptr;
+ int index_color_mode;
+ struct grub_video_palette_data palette[256];
+} framebuffer;
+
+static struct grub_video_render_target *render_target;
+static grub_uint32_t initial_mode;
+static grub_uint32_t mode_in_use = 0x55aa;
+static grub_uint16_t *mode_list;
+
+static grub_video_color_t
+grub_video_vbe_map_rgb (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue);
+
+static grub_video_color_t
+grub_video_vbe_map_rgba (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue,
+ grub_uint8_t alpha);
+
+static void
+grub_video_vbe_unmap_color (struct grub_video_render_target * source,
+ grub_video_color_t color,
+ grub_uint8_t *red,
+ grub_uint8_t *green,
+ grub_uint8_t *blue,
+ grub_uint8_t *alpha);
-static grub_uint8_t *framebuffer = 0;
-static grub_uint32_t bytes_per_scan_line = 0;
+
+static void *
+real2pm (grub_vbe_farptr_t ptr)
+{
+ return (void *) ((((unsigned long) ptr & 0xFFFF0000) >> 12UL)
+ + ((unsigned long) ptr & 0x0000FFFF));
+}
grub_err_t
grub_vbe_probe (struct grub_vbe_info_block *info_block)
@@ -99,7 +136,7 @@
vbe_ib->signature[3] = '2';
/* Try to get controller info block. */
- status = grub_vbe_get_controller_info (vbe_ib);
+ status = grub_vbe_bios_get_controller_info (vbe_ib);
if (status == 0x004F)
{
/* Copy it for later usage. */
@@ -128,11 +165,13 @@
grub_uint32_t old_mode;
/* Make sure that VBE is supported. */
- if (grub_vbe_probe (0) != GRUB_ERR_NONE)
+ grub_vbe_probe (0);
+ if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* Try to get mode info. */
- if (grub_vbe_get_video_mode_info (mode, &active_mode_info) != GRUB_ERR_NONE)
+ grub_vbe_get_video_mode_info (mode, &active_mode_info);
+ if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* For all VESA BIOS modes, force linear frame buffer. */
@@ -144,12 +183,12 @@
/* Determine frame buffer pixel format. */
switch (active_mode_info.memory_model)
{
- case 0x04:
- index_color_mode = 1;
+ case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL:
+ framebuffer.index_color_mode = 1;
break;
- case 0x06:
- index_color_mode = 0;
+ case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR:
+ framebuffer.index_color_mode = 0;
break;
default:
@@ -160,51 +199,68 @@
}
/* Get current mode. */
- if (grub_vbe_get_video_mode (&old_mode) != GRUB_ERR_NONE)
+ grub_vbe_get_video_mode (&old_mode);
+ if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* Try to set video mode. */
- status = grub_vbe_set_mode (mode, 0);
- if (status != 0x004F)
+ status = grub_vbe_bios_set_mode (mode, 0);
+ if (status != GRUB_VBE_STATUS_OK)
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot set VBE mode %x", mode);
/* Save information for later usage. */
- active_mode = mode;
+ framebuffer.active_mode = mode;
if (mode < 0x100)
{
/* If this is not a VESA mode, guess address. */
- framebuffer = (grub_uint8_t *) 0xA0000;
- index_color_mode = 1;
+ framebuffer.ptr = (grub_uint8_t *) 0xA0000;
+ framebuffer.index_color_mode = 1;
}
else
{
- framebuffer = (grub_uint8_t *) active_mode_info.phys_base_addr;
+ framebuffer.ptr = (grub_uint8_t *) active_mode_info.phys_base_addr;
if (controller_info.version >= 0x300)
- bytes_per_scan_line = active_mode_info.lin_bytes_per_scan_line;
+ framebuffer.bytes_per_scan_line = active_mode_info.lin_bytes_per_scan_line;
else
- bytes_per_scan_line = active_mode_info.bytes_per_scan_line;
+ framebuffer.bytes_per_scan_line = active_mode_info.bytes_per_scan_line;
+ }
+
+ /* Calculate bytes_per_pixel value. */
+ switch(active_mode_info.bits_per_pixel)
+ {
+ case 32: framebuffer.bytes_per_pixel = 4; break;
+ case 24: framebuffer.bytes_per_pixel = 3; break;
+ case 16: framebuffer.bytes_per_pixel = 2; break;
+ case 15: framebuffer.bytes_per_pixel = 2; break;
+ case 8: framebuffer.bytes_per_pixel = 1; break;
+ default:
+ grub_vbe_bios_set_mode (old_mode, 0);
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ "cannot set VBE mode %x",
+ mode);
+ break;
}
/* If video mode is in indexed color, setup default VGA palette. */
- if (index_color_mode)
+ if (framebuffer.index_color_mode)
{
struct grub_vbe_palette_data *palette
= (struct grub_vbe_palette_data *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
/* Make sure that the BIOS can reach the palette. */
grub_memcpy (palette, vga_colors, sizeof (vga_colors));
- status = grub_vbe_set_palette_data (sizeof (vga_colors)
- / sizeof (struct grub_vbe_palette_data),
- 0,
- palette);
+ status = grub_vbe_bios_set_palette_data (sizeof (vga_colors)
+ / sizeof (struct grub_vbe_palette_data),
+ 0,
+ palette);
/* For now, ignore the status. Not sure if this is fatal. */
#if 0
- if (status != 0x004F)
+ if (status != GRUB_VBE_STATUS_OK)
{
- grub_vbe_set_mode (old_mode, 0);
+ grub_vbe_bios_set_mode (old_mode, 0);
return grub_error (GRUB_ERR_BAD_DEVICE,
"cannot set the default VGA palette");
}
@@ -224,12 +280,13 @@
grub_vbe_status_t status;
/* Make sure that VBE is supported. */
- if (grub_vbe_probe (0) != GRUB_ERR_NONE)
+ grub_vbe_probe (0);
+ if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* Try to query current mode from VESA BIOS. */
- status = grub_vbe_get_mode (mode);
- if (status != 0x004F)
+ status = grub_vbe_bios_get_mode (mode);
+ if (status != GRUB_VBE_STATUS_OK)
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot get current VBE mode");
return GRUB_ERR_NONE;
@@ -244,15 +301,16 @@
grub_vbe_status_t status;
/* Make sure that VBE is supported. */
- if (grub_vbe_probe (0) != GRUB_ERR_NONE)
+ grub_vbe_probe (0);
+ if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* If mode is not VESA mode, skip mode info query. */
if (mode >= 0x100)
{
/* Try to get mode info from VESA BIOS. */
- status = grub_vbe_get_mode_info (mode, mi_tmp);
- if (status != 0x004F)
+ status = grub_vbe_bios_get_mode_info (mode, mi_tmp);
+ if (status != GRUB_VBE_STATUS_OK)
return grub_error (GRUB_ERR_BAD_DEVICE,
"cannot get information on the mode %x", mode);
@@ -266,60 +324,75 @@
return GRUB_ERR_NONE;
}
-void
-grub_vbe_set_pixel_rgb (grub_uint32_t x,
- grub_uint32_t y,
- grub_uint8_t red,
- grub_uint8_t green,
- grub_uint8_t blue)
+static grub_uint8_t *
+grub_video_vbe_get_video_ptr (struct grub_video_render_target *source,
+ grub_uint32_t x,
+ grub_uint32_t y)
{
- grub_uint32_t value;
+ grub_uint8_t *ptr = 0;
+
+ switch (source->mode_info.bpp)
+ {
+ case 32:
+ ptr = (grub_uint8_t *)source->data
+ + y * source->mode_info.pitch
+ + x * 4;
+ break;
- if (x >= active_mode_info.x_resolution)
- return;
+ case 24:
+ ptr = (grub_uint8_t *)source->data
+ + y * source->mode_info.pitch
+ + x * 3;
+ break;
- if (y >= active_mode_info.y_resolution)
- return;
+ case 16:
+ case 15:
+ ptr = (grub_uint8_t *)source->data
+ + y * source->mode_info.pitch
+ + x * 2;
+ break;
- if (controller_info.version >= 0x300)
- {
- red >>= 8 - active_mode_info.lin_red_mask_size;
- green >>= 8 - active_mode_info.lin_green_mask_size;
- blue >>= 8 - active_mode_info.lin_blue_mask_size;
-
- value = red << active_mode_info.lin_red_field_position;
- value |= green << active_mode_info.lin_green_field_position;
- value |= blue << active_mode_info.lin_blue_field_position;
+ case 8:
+ ptr = (grub_uint8_t *)source->data
+ + y * source->mode_info.pitch
+ + x;
+ break;
}
- else
- {
- red >>= 8 - active_mode_info.red_mask_size;
- green >>= 8 - active_mode_info.green_mask_size;
- blue >>= 8 - active_mode_info.blue_mask_size;
+
+ return ptr;
+}
- value = red << active_mode_info.red_field_position;
- value |= green << active_mode_info.green_field_position;
- value |= blue << active_mode_info.blue_field_position;
- }
+static void
+grub_video_vbe_draw_pixel (grub_uint32_t x,
+ grub_uint32_t y,
+ grub_video_color_t color)
+{
+ if (x >= render_target->mode_info.width)
+ return;
+
+ if (y >= render_target->mode_info.height)
+ return;
- switch (active_mode_info.bits_per_pixel)
+ switch (render_target->mode_info.bpp)
{
case 32:
{
- grub_uint32_t *ptr = (grub_uint32_t *) (framebuffer
- + y * bytes_per_scan_line
- + x * 4);
+ grub_uint32_t *ptr;
- *ptr = value;
+ ptr = (grub_uint32_t *)grub_video_vbe_get_video_ptr (render_target,
+ x,
+ y);
+
+ *ptr = color;
}
break;
case 24:
{
- grub_uint8_t *ptr = (grub_uint8_t *) (framebuffer
- + y * bytes_per_scan_line
- + x * 3);
- grub_uint8_t *ptr2 = (grub_uint8_t *) &value;
+ grub_uint8_t *ptr;
+ grub_uint8_t *ptr2 = (grub_uint8_t *) &color;
+
+ ptr = grub_video_vbe_get_video_ptr (render_target, x, y);
ptr[0] = ptr2[0];
ptr[1] = ptr2[1];
@@ -330,11 +403,25 @@
case 16:
case 15:
{
- grub_uint16_t *ptr = (grub_uint16_t *) (framebuffer
- + y * bytes_per_scan_line
- + x * 2);
+ grub_uint16_t *ptr;
+
+ ptr = (grub_uint16_t *)grub_video_vbe_get_video_ptr (render_target,
+ x,
+ y);
- *ptr = (grub_uint16_t) (value & 0xFFFF);
+ *ptr = (grub_uint16_t) (color & 0xFFFF);
+ }
+ break;
+
+ case 8:
+ {
+ grub_uint8_t *ptr;
+
+ ptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (render_target,
+ x,
+ y);
+
+ *ptr = (grub_uint8_t) (color & 0xFF);
}
break;
@@ -343,44 +430,1117 @@
}
}
-void
-grub_vbe_set_pixel_index (grub_uint32_t x,
- grub_uint32_t y,
- grub_uint8_t color)
+static grub_video_color_t
+grub_video_vbe_get_pixel (struct grub_video_render_target *source,
+ grub_uint32_t x,
+ grub_uint32_t y)
{
- if (x >= active_mode_info.x_resolution)
- return;
+ grub_video_color_t color = 0;
+
+ if (x >= source->mode_info.width)
+ return 0;
- if (y >= active_mode_info.y_resolution)
- return;
+ if (y >= source->mode_info.height)
+ return 0;
- if (index_color_mode == 1)
+ switch (source->mode_info.bpp)
{
- grub_uint8_t *ptr = (grub_uint8_t *) (framebuffer
- + y * bytes_per_scan_line
- + x);
+ case 32:
+ color = *(grub_uint32_t *)grub_video_vbe_get_video_ptr (source, x, y);
+ break;
+
+ case 24:
+ {
+ grub_uint8_t *ptr;
+ ptr = grub_video_vbe_get_video_ptr (source, x, y);
+ color = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
+ }
+ break;
- *ptr = color;
+ case 16:
+ case 15:
+ color = *(grub_uint16_t *)grub_video_vbe_get_video_ptr (source, x, y);
+ break;
+
+ case 8:
+ color = *(grub_uint8_t *)grub_video_vbe_get_video_ptr (source, x, y);
+ break;
+
+ default:
+ break;
+ }
+
+ return color;
+}
+
+static grub_err_t
+grub_video_vbe_init (void)
+{
+ grub_uint16_t *rm_mode_list;
+ grub_uint16_t *p;
+ grub_size_t mode_list_size;
+ struct grub_vbe_info_block info_block;
+
+ /* Check if there is adapter present.
+
+ Firmware note: There has been a report that some cards store video mode
+ list in temporary memory. So we must first use vbe probe to get
+ refreshed information to receive valid pointers and data, and then
+ copy this information to somewhere safe. */
+ grub_vbe_probe (&info_block);
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Copy modelist to local memory. */
+ p = rm_mode_list = real2pm (info_block.video_mode_ptr);
+ while(*p++ != 0xFFFF)
+ ;
+
+ mode_list_size = (grub_addr_t) p - (grub_addr_t) rm_mode_list;
+ mode_list = grub_malloc (mode_list_size);
+ if (! mode_list)
+ return grub_errno;
+ grub_memcpy (mode_list, rm_mode_list, mode_list_size);
+
+ /* Adapter could be found, figure out initial video mode. */
+ grub_vbe_get_video_mode (&initial_mode);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free allocated resources. */
+ grub_free (mode_list);
+ mode_list = 0;
+
+ return grub_errno;
+ }
+
+ /* Reset frame buffer and render target variables. */
+ grub_memset (&framebuffer, 0, sizeof(framebuffer));
+ render_target = &framebuffer.render_target;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_fini (void)
+{
+ grub_vbe_status_t status;
+
+ /* Restore old video mode. */
+ status = grub_vbe_bios_set_mode (initial_mode, 0);
+ if (status != GRUB_VBE_STATUS_OK)
+ /* TODO: Decide, is this something we want to do. */
+ return grub_errno;
+
+ /* TODO: Free any resources allocated by driver. */
+ grub_free (mode_list);
+ mode_list = 0;
+
+ /* TODO: destroy render targets. */
+
+ /* Return success to caller. */
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_setup (unsigned int width,
+ unsigned int height,
+ unsigned int mode_type)
+{
+ grub_uint16_t *p;
+ struct grub_vbe_mode_info_block mode_info;
+ struct grub_vbe_mode_info_block best_mode_info;
+ grub_uint32_t best_mode = 0;
+ unsigned int i;
+
+ /* Walk thru mode list and try to find matching mode. */
+ for (p = mode_list; *p != 0xFFFF; p++)
+ {
+ grub_uint32_t mode = *p;
+
+ grub_vbe_get_video_mode_info (mode, &mode_info);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Could not retrieve mode info, retreat. */
+ grub_errno = GRUB_ERR_NONE;
+ break;
+ }
+
+ if ((mode_info.mode_attributes & 0x001) == 0)
+ /* If not available, skip it. */
+ continue;
+
+ if ((mode_info.mode_attributes & 0x002) == 0)
+ /* Not enough information. */
+ continue;
+
+ if ((mode_info.mode_attributes & 0x008) == 0)
+ /* Monochrome is unusable. */
+ continue;
+
+ if ((mode_info.mode_attributes & 0x080) == 0)
+ /* We support only linear frame buffer modes. */
+ continue;
+
+ if ((mode_info.mode_attributes & 0x010) == 0)
+ /* We allow only graphical modes. */
+ continue;
+
+ if ((mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL)
+ && (mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR))
+ /* Not compatible memory model. */
+ continue;
+
+ if ((mode_info.x_resolution != width)
+ || (mode_info.y_resolution != height))
+ /* Non matching resolution. */
+ continue;
+
+ /* Check if user requested RGB or index color mode. */
+ if ((mode_type & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0)
+ {
+ if (((mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ && (mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL))
+ /* Requested only index color modes. */
+ continue;
+
+ if (((mode_type & GRUB_VIDEO_MODE_TYPE_RGB) != 0)
+ && (mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR))
+ /* Requested only RGB modes. */
+ continue;
+ }
+
+ /* Select mode with most number of bits per pixel. */
+ if (best_mode != 0)
+ if (mode_info.bits_per_pixel < best_mode_info.bits_per_pixel)
+ continue;
+
+ /* Save so far best mode information for later use. */
+ best_mode = mode;
+ grub_memcpy (&best_mode_info, &mode_info, sizeof (mode_info));
+ }
+
+ /* Try to initialize best mode found. */
+ if (best_mode != 0)
+ {
+ /* If this fails, then we have mode selection heuristics problem,
+ or adapter failure. */
+ grub_vbe_set_video_mode (best_mode, &active_mode_info);
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Now we are happily in requested video mode. Cache some info
+ in order to fasten later operations. */
+ mode_in_use = best_mode;
+
+ /* Reset render target to framebuffer one. */
+ render_target = &framebuffer.render_target;
+
+ /* Fill mode info details in framebuffer's render target. */
+ render_target->mode_info.width = active_mode_info.x_resolution;
+ render_target->mode_info.height = active_mode_info.y_resolution;
+
+ if (framebuffer.index_color_mode)
+ render_target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+ else
+ render_target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
+
+ render_target->mode_info.bpp = active_mode_info.bits_per_pixel;
+ render_target->mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel;
+ render_target->mode_info.pitch = framebuffer.bytes_per_scan_line;
+ render_target->mode_info.number_of_colors = 256; /* TODO: fix me. */
+ render_target->mode_info.red_mask_size = active_mode_info.red_mask_size;
+ render_target->mode_info.red_field_pos = active_mode_info.red_field_position;
+ render_target->mode_info.green_mask_size = active_mode_info.green_mask_size;
+ render_target->mode_info.green_field_pos = active_mode_info.green_field_position;
+ render_target->mode_info.blue_mask_size = active_mode_info.blue_mask_size;
+ render_target->mode_info.blue_field_pos = active_mode_info.blue_field_position;
+ render_target->mode_info.reserved_mask_size = active_mode_info.rsvd_mask_size;
+ render_target->mode_info.reserved_field_pos = active_mode_info.rsvd_field_position;
+
+ /* Reset viewport to match new mode. */
+ render_target->viewport.x = 0;
+ render_target->viewport.y = 0;
+ render_target->viewport.width = active_mode_info.x_resolution;
+ render_target->viewport.height = active_mode_info.y_resolution;
+
+ /* Set framebuffer pointer and mark it as non allocated. */
+ render_target->is_allocated = 0;
+ render_target->data = framebuffer.ptr;
+
+ /* Copy default palette to initialize emulated palette. */
+ for (i = 0;
+ i < (sizeof (vga_colors)
+ / sizeof (struct grub_vbe_palette_data));
+ i++)
+ {
+ framebuffer.palette[i].r = vga_colors[i].red;
+ framebuffer.palette[i].g = vga_colors[i].green;
+ framebuffer.palette[i].b = vga_colors[i].blue;
+ framebuffer.palette[i].a = 0xFF;
+ }
+
+ return GRUB_ERR_NONE;
+ }
+
+ /* Couldn't found matching mode. */
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found.");
+}
+
+static grub_err_t
+grub_video_vbe_get_info (struct grub_video_mode_info *mode_info)
+{
+ /* Copy mode info from active render target. */
+ grub_memcpy (mode_info,
+ &render_target->mode_info,
+ sizeof (struct grub_video_mode_info));
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_palette (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data)
+{
+ unsigned int i;
+
+ if (framebuffer.index_color_mode)
+ {
+ /* TODO: Implement setting indexed color mode palette to hardware. */
+ //status = grub_vbe_bios_set_palette_data (sizeof (vga_colors)
+ // / sizeof (struct grub_vbe_palette_data),
+ // 0,
+ // palette);
+
+ }
+
+ /* Then set color to emulated palette. */
+ for (i = 0; (i < count) && ((i + start) < 256); i++)
+ framebuffer.palette[start + i] = palette_data[i];
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_get_palette (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data)
+{
+ unsigned int i;
+
+ /* Assume that we know everything from index color palette. */
+ for (i = 0; (i < count) && ((i + start) < 256); i++)
+ palette_data[i] = framebuffer.palette[start + i];
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_viewport (unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height)
+{
+ /* Make sure viewport is withing screen dimensions. If viewport was set
+ to be out of the reqion, mark its size as zero. */
+ if (x > active_mode_info.x_resolution)
+ {
+ x = 0;
+ width = 0;
+ }
+
+ if (y > active_mode_info.y_resolution)
+ {
+ y = 0;
+ height = 0;
+ }
+
+ if (x + width > active_mode_info.x_resolution)
+ width = active_mode_info.x_resolution - x;
+
+ if (y + height > active_mode_info.y_resolution)
+ height = active_mode_info.y_resolution - y;
+
+ render_target->viewport.x = x;
+ render_target->viewport.y = y;
+ render_target->viewport.width = width;
+ render_target->viewport.height = height;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_get_viewport (unsigned int *x,
+ unsigned int *y,
+ unsigned int *width,
+ unsigned int *height)
+{
+ if (x) *x = render_target->viewport.x;
+ if (y) *y = render_target->viewport.y;
+ if (width) *width = render_target->viewport.width;
+ if (height) *height = render_target->viewport.height;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_video_color_t
+grub_video_vbe_map_color (grub_uint32_t color_name)
+{
+ /* TODO: implement color theme mapping code. */
+
+ if (color_name < 256)
+ {
+ if ((render_target->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ return color_name;
+ else
+ {
+ grub_video_color_t color;
+
+ color = grub_video_vbe_map_rgb (framebuffer.palette[color_name].r,
+ framebuffer.palette[color_name].g,
+ framebuffer.palette[color_name].b);
+
+ return color;
+ }
+ }
+
+ return 0;
+}
+
+static grub_video_color_t
+grub_video_vbe_map_rgb (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue)
+{
+ if ((render_target->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ {
+ int minindex = 0;
+ int delta = 0;
+ int tmp;
+ int val;
+ int i;
+
+ /* Find best matching color. */
+ for (i = 0; i < 256; i++)
+ {
+ val = framebuffer.palette[i].r - red;
+ tmp = val * val;
+ val = framebuffer.palette[i].g - green;
+ tmp += val * val;
+ val = framebuffer.palette[i].b - blue;
+ tmp += val * val;
+
+ if (i == 0)
+ delta = tmp;
+
+ if (tmp < delta)
+ {
+ delta = tmp;
+ minindex = i;
+ if (tmp == 0)
+ break;
+ }
+ }
+
+ return minindex;
}
else
{
- color &= 0x0F;
+ grub_uint32_t value;
+ grub_uint8_t alpha = 255; /* Opaque color. */
- if (color < 16)
- {
- grub_vbe_set_pixel_rgb (x,
- y,
- vga_colors[color].red,
- vga_colors[color].green,
- vga_colors[color].blue);
- }
+ red >>= 8 - render_target->mode_info.red_mask_size;
+ green >>= 8 - render_target->mode_info.green_mask_size;
+ blue >>= 8 - render_target->mode_info.blue_mask_size;
+ alpha >>= 8 - render_target->mode_info.reserved_mask_size;
+
+ value = red << render_target->mode_info.red_field_pos;
+ value |= green << render_target->mode_info.green_field_pos;
+ value |= blue << render_target->mode_info.blue_field_pos;
+ value |= alpha << render_target->mode_info.reserved_field_pos;
+
+ return value;
+ }
+
+}
+
+static grub_video_color_t
+grub_video_vbe_map_rgba (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue,
+ grub_uint8_t alpha)
+{
+ if ((render_target->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ /* No alpha available in index color modes, just use
+ same value as in only RGB modes. */
+ return grub_video_vbe_map_rgb (red, green, blue);
+ else
+ {
+ grub_uint32_t value;
+
+ red >>= 8 - render_target->mode_info.red_mask_size;
+ green >>= 8 - render_target->mode_info.green_mask_size;
+ blue >>= 8 - render_target->mode_info.blue_mask_size;
+ alpha >>= 8 - render_target->mode_info.reserved_mask_size;
+
+ value = red << render_target->mode_info.red_field_pos;
+ value |= green << render_target->mode_info.green_field_pos;
+ value |= blue << render_target->mode_info.blue_field_pos;
+ value |= alpha << render_target->mode_info.reserved_field_pos;
+
+ return value;
+ }
+}
+
+static void
+grub_video_vbe_unmap_color (struct grub_video_render_target * source,
+ grub_video_color_t color,
+ grub_uint8_t *red,
+ grub_uint8_t *green,
+ grub_uint8_t *blue,
+ grub_uint8_t *alpha)
+{
+ if ((source->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ {
+ /* If we have out of bounds color, return trasnparent black. */
+ if (color > 255)
+ {
+ *red = 0;
+ *green = 0;
+ *blue = 0;
+ *alpha = 0;
+ return;
+ }
+
+ *red = framebuffer.palette[color].r;
+ *green = framebuffer.palette[color].g;
+ *blue = framebuffer.palette[color].b;
+ *alpha = framebuffer.palette[color].a;
+ return;
+ }
+ else
+ {
+ grub_uint32_t tmp;
+
+ /* Get red component. */
+ tmp = color >> source->mode_info.red_field_pos;
+ tmp &= (1 << source->mode_info.red_mask_size) - 1;
+ tmp <<= 8 - source->mode_info.red_mask_size;
+ tmp |= (1 << (8 - source->mode_info.red_mask_size)) - 1;
+ *red = tmp & 0xFF;
+
+ /* Get green component. */
+ tmp = color >> source->mode_info.green_field_pos;
+ tmp &= (1 << source->mode_info.green_mask_size) - 1;
+ tmp <<= 8 - source->mode_info.green_mask_size;
+ tmp |= (1 << (8 - source->mode_info.green_mask_size)) - 1;
+ *green = tmp & 0xFF;
+
+ /* Get blue component. */
+ tmp = color >> source->mode_info.blue_field_pos;
+ tmp &= (1 << source->mode_info.blue_mask_size) - 1;
+ tmp <<= 8 - source->mode_info.blue_mask_size;
+ tmp |= (1 << (8 - source->mode_info.blue_mask_size)) - 1;
+ *blue = tmp & 0xFF;
+
+ /* Get alpha component. */
+ if (source->mode_info.reserved_mask_size > 0)
+ {
+ tmp = color >> source->mode_info.reserved_field_pos;
+ tmp &= (1 << source->mode_info.reserved_mask_size) - 1;
+ tmp <<= 8 - source->mode_info.reserved_mask_size;
+ tmp |= (1 << (8 - source->mode_info.reserved_mask_size)) - 1;
+ }
else
- {
- grub_vbe_set_pixel_rgb (x,
- y,
- 0,
- 0,
- 0);
- }
+ {
+ /* If there is no alpha component, assume it opaque. */
+ tmp = 255;
+ }
+
+ *alpha = tmp & 0xFF;
+ }
+}
+
+static grub_err_t
+grub_video_vbe_fill_rect (grub_video_color_t color,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height)
+{
+ unsigned int i, j;
+
+ /* Make sure there is something to do. */
+ if ((x > (int)render_target->viewport.width) || (x + (int)width < 0))
+ return GRUB_ERR_NONE;
+ if ((y > (int)render_target->viewport.height) || (y + (int)height < 0))
+ return GRUB_ERR_NONE;
+
+ /* Do not allow drawing out of viewport. */
+ if (x < 0)
+ {
+ width += x;
+ x = 0;
+ }
+ if (y < 0)
+ {
+ height += y;
+ y = 0;
+ }
+
+ if ((x + width) > render_target->viewport.width)
+ width = render_target->viewport.width - x;
+ if ((y + height) > render_target->viewport.height)
+ height = render_target->viewport.height - y;
+
+ /* Add viewport offset. */
+ x += render_target->viewport.x;
+ y += render_target->viewport.y;
+
+ /* Fill area. */
+ for (j = 0; j < height; j++)
+ for (i = 0; i < width; i++)
+ grub_video_vbe_draw_pixel (x+i, y+j, color);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_blit_glyph (struct grub_font_glyph * glyph,
+ grub_video_color_t color,
+ int x,
+ int y)
+{
+ unsigned int width;
+ unsigned int charwidth;
+ unsigned int height;
+ unsigned int i;
+ unsigned int j;
+ unsigned int x_offset = 0;
+ unsigned int y_offset = 0;
+
+ /* Make sure there is something to do. */
+ if (x > (int)render_target->viewport.width)
+ return GRUB_ERR_NONE;
+
+ if (y > (int)render_target->viewport.height)
+ return GRUB_ERR_NONE;
+
+ /* Calculate glyph dimensions. */
+ width = ((glyph->width + 7) / 8) * 8;
+ charwidth = width;
+ height = glyph->height;
+
+ if (x + (int)width < 0)
+ return GRUB_ERR_NONE;
+
+ if (y + (int)height < 0)
+ return GRUB_ERR_NONE;
+
+ /* Do not allow drawing out of viewport. */
+ if (x < 0)
+ {
+ width += x;
+ x_offset = (unsigned int)-x;
+ x = 0;
+ }
+ if (y < 0)
+ {
+ height += y;
+ y_offset = (unsigned int)-y;
+ y = 0;
+ }
+
+ if ((x + width) > render_target->viewport.width)
+ width = render_target->viewport.width - x;
+ if ((y + height) > render_target->viewport.height)
+ height = render_target->viewport.height - y;
+
+ /* Add viewport offset. */
+ x += render_target->viewport.x;
+ y += render_target->viewport.y;
+
+ /* Draw glyph. */
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ if ((glyph->bitmap[((i + x_offset) / 8)
+ + (j + y_offset) * (charwidth / 8)]
+ & (1 << ((charwidth - (i + x_offset) - 1) % 8))))
+ {
+ grub_video_vbe_draw_pixel (x+i, y+j, color);
+ }
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_blit_bitmap (struct grub_video_bitmap * bitmap,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height)
+{
+ /* Make sure there is something to do. */
+ if ((x > (int)render_target->viewport.width) || (x + (int)width < 0))
+ return GRUB_ERR_NONE;
+ if ((y > (int)render_target->viewport.height) || (y + (int)height < 0))
+ return GRUB_ERR_NONE;
+
+ /* Do not allow drawing out of viewport. */
+ if (offset_x < 0)
+ {
+ width += offset_x;
+ x -= offset_x;
+ offset_x = 0;
+ }
+
+ if (offset_y < 0)
+ {
+ height += offset_y;
+ y -= offset_y;
+ offset_y = 0;
+ }
+
+ if (x < 0)
+ {
+ width += x;
+ offset_x += (unsigned int)-x;
+ x = 0;
+ }
+ if (y < 0)
+ {
+ height += y;
+ offset_y += (unsigned int)-y;
+ y = 0;
+ }
+
+ if ((x + width) > render_target->viewport.width)
+ width = render_target->viewport.width - x;
+ if ((y + height) > render_target->viewport.height)
+ height = render_target->viewport.height - y;
+
+ /* TODO: Limit drawing to bitmap dimensions. */
+
+ /* Add viewport offset. */
+ x += render_target->viewport.x;
+ y += render_target->viewport.y;
+
+ /* TODO: Render bitmap. */
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_blit_render_target (struct grub_video_render_target *source,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height)
+{
+ unsigned int i;
+ unsigned int j;
+
+ /* Make sure there is something to do. */
+ if ((width == 0) || (height == 0))
+ return GRUB_ERR_NONE;
+ if ((x > (int)render_target->viewport.width) || (x + (int)width < 0))
+ return GRUB_ERR_NONE;
+ if ((y > (int)render_target->viewport.height) || (y + (int)height < 0))
+ return GRUB_ERR_NONE;
+ if ((x + (int)source->mode_info.width) < 0)
+ return GRUB_ERR_NONE;
+ if ((y + (int)source->mode_info.height) < 0)
+ return GRUB_ERR_NONE;
+ if ((offset_x > (int)source->mode_info.width)
+ || (offset_x + (int)source->mode_info.width < 0))
+ return GRUB_ERR_NONE;
+ if ((offset_y > (int)source->mode_info.height)
+ || (offset_y + (int)source->mode_info.height < 0))
+ return GRUB_ERR_NONE;
+
+ /* If we have negative coordinates, optimize drawing to minimum. */
+ if (offset_x < 0)
+ {
+ width += offset_x;
+ x -= offset_x;
+ offset_x = 0;
+ }
+
+ if (offset_y < 0)
+ {
+ height += offset_y;
+ y -= offset_y;
+ offset_y = 0;
+ }
+
+ if (x < 0)
+ {
+ width += x;
+ offset_x += (unsigned int)-x;
+ x = 0;
+ }
+
+ if (y < 0)
+ {
+ height += y;
+ offset_y += (unsigned int)-y;
+ y = 0;
+ }
+
+ /* Do not allow drawing out of viewport. */
+ if ((x + width) > render_target->viewport.width)
+ width = render_target->viewport.width - x;
+ if ((y + height) > render_target->viewport.height)
+ height = render_target->viewport.height - y;
+
+ if ((offset_x + width) > source->mode_info.width)
+ width = source->mode_info.width - offset_x;
+ if ((offset_y + height) > source->mode_info.height)
+ height = source->mode_info.height - offset_y;
+
+ /* Limit drawing to source render target dimensions. */
+ if (width > source->mode_info.width)
+ width = source->mode_info.width;
+
+ if (height > source->mode_info.height)
+ height = source->mode_info.height;
+
+ /* Add viewport offset. */
+ x += render_target->viewport.x;
+ y += render_target->viewport.y;
+
+ /* Render. */
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ grub_uint8_t src_red;
+ grub_uint8_t src_green;
+ grub_uint8_t src_blue;
+ grub_uint8_t src_alpha;
+ grub_uint8_t dst_red;
+ grub_uint8_t dst_green;
+ grub_uint8_t dst_blue;
+ grub_uint8_t dst_alpha;
+ grub_video_color_t src_color;
+ grub_video_color_t dst_color;
+
+ src_color = grub_video_vbe_get_pixel (source, i + offset_x, j + offset_y);
+ grub_video_vbe_unmap_color (source,
+ src_color,
+ &src_red,
+ &src_green,
+ &src_blue,
+ &src_alpha);
+
+ if (src_alpha == 0)
+ continue;
+
+ if (src_alpha == 255)
+ {
+ dst_color = grub_video_vbe_map_rgba (src_red,
+ src_green,
+ src_blue,
+ src_alpha);
+ grub_video_vbe_draw_pixel (x + i, y + j, dst_color);
+ continue;
+ }
+
+ dst_color = grub_video_vbe_get_pixel (render_target,
+ x + i,
+ y + j);
+
+ grub_video_vbe_unmap_color (render_target,
+ dst_color,
+ &dst_red,
+ &dst_green,
+ &dst_blue,
+ &dst_alpha);
+
+ dst_red = (((src_red * src_alpha)
+ + (dst_red * (255 - src_alpha))) / 255);
+ dst_green = (((src_green * src_alpha)
+ + (dst_green * (255 - src_alpha))) / 255);
+ dst_blue = (((src_blue * src_alpha)
+ + (dst_blue * (255 - src_alpha))) / 255);
+
+ dst_alpha = src_alpha;
+ dst_color = grub_video_vbe_map_rgba (dst_red,
+ dst_green,
+ dst_blue,
+ dst_alpha);
+
+ grub_video_vbe_draw_pixel (x + i, y + j, dst_color);
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_scroll (grub_video_color_t color,
+ int dx,
+ int dy)
+{
+ int width;
+ int height;
+ int src_x;
+ int src_y;
+ int dst_x;
+ int dst_y;
+
+ /* 1. Check if we have something to do. */
+ if ((dx == 0) && (dy == 0))
+ return GRUB_ERR_NONE;
+
+ width = render_target->viewport.width - grub_abs (dx);
+ height = render_target->viewport.height - grub_abs (dy);
+
+ if (dx < 0)
+ {
+ src_x = render_target->viewport.x - dx;
+ dst_x = render_target->viewport.x;
+ }
+ else
+ {
+ src_x = render_target->viewport.x;
+ dst_x = render_target->viewport.x + dx;
+ }
+
+ if (dy < 0)
+ {
+ src_y = render_target->viewport.y - dy;
+ dst_y = render_target->viewport.y;
+ }
+ else
+ {
+ src_y = render_target->viewport.y;
+ dst_y = render_target->viewport.y + dy;
+ }
+
+ /* 2. Check if there is need to copy data. */
+ if ((grub_abs (dx) < render_target->viewport.width)
+ && (grub_abs (dy) < render_target->viewport.height))
+ {
+ /* 3. Move data in render target. */
+ grub_uint8_t *src;
+ grub_uint8_t *dst;
+ int j;
+
+ for (j = 0; j < height; j++)
+ {
+ dst = grub_video_vbe_get_video_ptr (render_target, dst_x, dst_y + j);
+ src = grub_video_vbe_get_video_ptr (render_target, src_x, src_y + j);
+ grub_memmove (dst,
+ src,
+ width * render_target->mode_info.bytes_per_pixel);
+ }
+ }
+
+ /* 4. Fill empty space with specified color. In this implementation
+ there might be colliding areas but at the moment there is no need
+ to optimize this. */
+
+ /* 4a. Fill top & bottom parts. */
+ if (dy > 0)
+ grub_video_vbe_fill_rect (color,
+ 0, 0,
+ render_target->viewport.width, dy);
+ else if (dy < 0)
+ {
+ if (render_target->viewport.height < grub_abs (dy))
+ dy = -render_target->viewport.height;
+
+ grub_video_vbe_fill_rect (color,
+ 0, render_target->viewport.height + dy,
+ render_target->viewport.width, -dy);
+ }
+
+ /* 4b. Fill left & right parts. */
+ if (dx > 0)
+ grub_video_vbe_fill_rect (color,
+ 0, 0,
+ dx, render_target->viewport.height);
+ else if (dx < 0)
+ {
+ if (render_target->viewport.width < grub_abs (dx))
+ dx = -render_target->viewport.width;
+
+ grub_video_vbe_fill_rect (color,
+ render_target->viewport.width + dx, 0,
+ -dx, render_target->viewport.height);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_swap_buffers (void)
+{
+ /* TODO: Implement buffer swapping. */
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_create_render_target (struct grub_video_render_target **result,
+ unsigned int mode_type,
+ unsigned int width,
+ unsigned int height)
+{
+ struct grub_video_render_target *target;
+ unsigned int size;
+
+ /* Validate arguments. */
+ if ((! result)
+ || (width == 0)
+ || (height == 0))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "invalid argument given.");
+
+ /* Allocate memory for render target. */
+ target = grub_malloc (sizeof (struct grub_video_render_target));
+ if (! target)
+ return grub_errno;
+
+ /* TODO: Implement other types too.
+ Currently only 32bit render targets are supported. */
+
+ /* Mark render target as allocated. */
+ target->is_allocated = 1;
+
+ /* Maximize viewport. */
+ target->viewport.x = 0;
+ target->viewport.y = 0;
+ target->viewport.width = width;
+ target->viewport.height = height;
+
+ /* Setup render target format. */
+ target->mode_info.width = width;
+ target->mode_info.height = height;
+ target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB
+ | GRUB_VIDEO_MODE_TYPE_ALPHA;
+ target->mode_info.bpp = 32;
+ target->mode_info.bytes_per_pixel = 4;
+ target->mode_info.pitch = target->mode_info.bytes_per_pixel * width;
+ target->mode_info.number_of_colors = 256; /* Emulated paletted. */
+ target->mode_info.red_mask_size = 8;
+ target->mode_info.red_field_pos = 0;
+ target->mode_info.green_mask_size = 8;
+ target->mode_info.green_field_pos = 8;
+ target->mode_info.blue_mask_size = 8;
+ target->mode_info.blue_field_pos = 16;
+ target->mode_info.reserved_mask_size = 8;
+ target->mode_info.reserved_field_pos = 24;
+
+ /* Calculate size needed for the data. */
+ size = (width * target->mode_info.bytes_per_pixel) * height;
+
+ target->data = grub_malloc (size);
+ if (! target->data)
+ {
+ grub_free (target);
+ return grub_errno;
}
+
+ /* Clear render target with black and maximum transparency. */
+ grub_memset (target->data, 0, size);
+
+ /* TODO: Add render target to render target list. */
+
+ /* Save result to caller. */
+ *result = target;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_delete_render_target (struct grub_video_render_target *target)
+{
+ /* If there is no target, then just return without error. */
+ if (! target)
+ return GRUB_ERR_NONE;
+
+ /* TODO: Delist render target fron render target list. */
+
+ /* If this is software render target, free it's memory. */
+ if (target->is_allocated)
+ grub_free (target->data);
+
+ /* Free render target. */
+ grub_free (target);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_active_render_target (struct grub_video_render_target *target)
+{
+ if (target == GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER)
+ {
+ render_target = &framebuffer.render_target;
+
+ return GRUB_ERR_NONE;
+ }
+
+ if (target == GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "double buffering not implemented yet.");
+
+ if (! target->data)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "invalid render target given.");
+
+ render_target = target;
+
+ return GRUB_ERR_NONE;
+}
+
+static struct grub_video_adapter grub_video_vbe_adapter =
+ {
+ .name = "VESA BIOS Extension Video Driver",
+
+ .init = grub_video_vbe_init,
+ .fini = grub_video_vbe_fini,
+ .setup = grub_video_vbe_setup,
+ .get_info = grub_video_vbe_get_info,
+ .set_palette = grub_video_vbe_set_palette,
+ .get_palette = grub_video_vbe_get_palette,
+ .set_viewport = grub_video_vbe_set_viewport,
+ .get_viewport = grub_video_vbe_get_viewport,
+ .map_color = grub_video_vbe_map_color,
+ .map_rgb = grub_video_vbe_map_rgb,
+ .map_rgba = grub_video_vbe_map_rgba,
+ .fill_rect = grub_video_vbe_fill_rect,
+ .blit_glyph = grub_video_vbe_blit_glyph,
+ .blit_bitmap = grub_video_vbe_blit_bitmap,
+ .blit_render_target = grub_video_vbe_blit_render_target,
+ .scroll = grub_video_vbe_scroll,
+ .swap_buffers = grub_video_vbe_swap_buffers,
+ .create_render_target = grub_video_vbe_create_render_target,
+ .delete_render_target = grub_video_vbe_delete_render_target,
+ .set_active_render_target = grub_video_vbe_set_active_render_target,
+
+ .next = 0
+ };
+
+GRUB_MOD_INIT(video_i386_pc_vbe)
+{
+ grub_video_register (&grub_video_vbe_adapter);
+}
+
+GRUB_MOD_FINI(video_i386_pc_ovbe)
+{
+ grub_video_unregister (&grub_video_vbe_adapter);
}
diff -ruN -x '*CVS*' grub2/video/video.c grub2.new/video/video.c
--- grub2/video/video.c 1970-01-01 02:00:00.000000000 +0200
+++ grub2.new/video/video.c 2006-03-03 16:57:12.779780640 +0200
@@ -0,0 +1,372 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/video.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+
+/* The list of video adapters registerd to system. */
+static grub_video_adapter_t grub_video_adapter_list;
+
+/* Active video adapter. */
+static grub_video_adapter_t grub_video_adapter_active;
+
+void
+grub_video_register (grub_video_adapter_t adapter)
+{
+ adapter->next = grub_video_adapter_list;
+ grub_video_adapter_list = adapter;
+}
+
+void
+grub_video_unregister (grub_video_adapter_t adapter)
+{
+ grub_video_adapter_t *p, q;
+
+ for (p = &grub_video_adapter_list, q = *p; q; p = &(q->next), q = q->next)
+ if (q == adapter)
+ {
+ *p = q->next;
+ break;
+ }
+}
+
+void
+grub_video_iterate (int (*hook) (grub_video_adapter_t adapter))
+{
+ grub_video_adapter_t p;
+
+ for (p = grub_video_adapter_list; p; p = p->next)
+ if (hook (p))
+ break;
+}
+
+grub_err_t
+grub_video_setup (unsigned int width,
+ unsigned int height,
+ unsigned int mode_type)
+{
+ grub_video_adapter_t p;
+
+ /* De-activate last set video adapter. */
+ if (grub_video_adapter_active)
+ {
+ /* Finalize adapter. */
+ grub_video_adapter_active->fini ();
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Mark active adapter as not set. */
+ grub_video_adapter_active = 0;
+ }
+
+ /* Loop thru all possible video adapter trying to find requested mode. */
+ for (p = grub_video_adapter_list; p; p = p->next)
+ {
+ /* Try to initialize adapter, if can't skip to next. */
+ p->init ();
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+
+ /* Try to initialize video mode. */
+ p->setup (width, height, mode_type);
+ if (grub_errno == GRUB_ERR_NONE)
+ {
+ /* Valid mode found from adapter, and it has been activated.
+ Specify it as active adapter. */
+ grub_video_adapter_active = p;
+ return GRUB_ERR_NONE;
+ }
+ else
+ {
+ grub_errno = GRUB_ERR_NONE;
+ }
+
+ /* No valid mode found in this adapter, finalize adapter. */
+ p->fini ();
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+ }
+
+ /* We couldn't find suitable adapter for specified mode. */
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+ "Can't locate valid adapter for mode");
+}
+
+grub_err_t
+grub_video_restore (void)
+{
+ if (grub_video_adapter_active)
+ {
+ grub_video_adapter_active->fini ();
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ grub_video_adapter_active = 0;
+ }
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_video_get_info (struct grub_video_mode_info *mode_info)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->get_info (mode_info);
+}
+
+grub_err_t
+grub_video_set_palette (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->set_palette (start, count, palette_data);
+}
+
+grub_err_t
+grub_video_get_palette (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->get_palette (start, count, palette_data);
+}
+
+grub_err_t
+grub_video_set_viewport (unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->set_viewport (x, y, width, height);
+}
+
+grub_err_t
+grub_video_get_viewport (unsigned int *x,
+ unsigned int *y,
+ unsigned int *width,
+ unsigned int *height)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->get_viewport (x, y, width, height);
+}
+
+grub_video_color_t
+grub_video_map_color (grub_uint32_t color_name)
+{
+ if (! grub_video_adapter_active)
+ {
+ return 0;
+ }
+
+ return grub_video_adapter_active->map_color (color_name);
+}
+
+grub_video_color_t
+grub_video_map_rgb (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue)
+{
+ if (! grub_video_adapter_active)
+ {
+ return 0;
+ }
+
+ return grub_video_adapter_active->map_rgb (red, green, blue);
+}
+
+grub_video_color_t
+grub_video_map_rgba (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue,
+ grub_uint8_t alpha)
+{
+ if (! grub_video_adapter_active)
+ {
+ return 0;
+ }
+
+ return grub_video_adapter_active->map_rgba (red, green, blue, alpha);
+}
+
+grub_err_t
+grub_video_fill_rect (grub_video_color_t color,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->fill_rect (color, x, y, width, height);
+}
+
+grub_err_t
+grub_video_blit_glyph (struct grub_font_glyph *glyph,
+ grub_video_color_t color,
+ int x,
+ int y)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->blit_glyph (glyph, color, x, y);
+}
+
+grub_err_t
+grub_video_blit_bitmap (struct grub_video_bitmap *bitmap,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->blit_bitmap (bitmap,
+ x, y,
+ offset_x, offset_y,
+ width, height);
+}
+
+grub_err_t
+grub_video_blit_render_target (struct grub_video_render_target *target,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->blit_render_target (target,
+ x, y,
+ offset_x, offset_y,
+ width, height);
+}
+
+grub_err_t
+grub_video_scroll (grub_video_color_t color,
+ int dx,
+ int dy)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->scroll (color, dx, dy);
+}
+
+grub_err_t
+grub_video_swap_buffers (void)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->swap_buffers ();
+}
+
+grub_err_t
+grub_video_create_render_target (struct grub_video_render_target **result,
+ unsigned int mode_type,
+ unsigned int width,
+ unsigned int height)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->create_render_target (result,
+ mode_type,
+ width,
+ height);
+}
+
+grub_err_t
+grub_video_delete_render_target (struct grub_video_render_target *target)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->delete_render_target (target);
+}
+
+grub_err_t
+grub_video_set_active_render_target (struct grub_video_render_target *target)
+{
+ if (! grub_video_adapter_active)
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+ }
+
+ return grub_video_adapter_active->set_active_render_target (target);
+}
+
+GRUB_MOD_INIT(video_video)
+{
+ grub_video_adapter_active = 0;
+ grub_video_adapter_list = 0;
+}
+
+GRUB_MOD_FINI(video_video)
+{
+}
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: New patch for video subsystem...
2006-03-03 15:23 ` Vesa Jääskeläinen
@ 2006-03-05 22:25 ` Yoshinori K. Okuji
2006-03-06 19:56 ` Vesa Jääskeläinen
2006-03-12 14:49 ` Marco Gerards
2006-03-12 14:50 ` Marco Gerards
2 siblings, 1 reply; 14+ messages in thread
From: Yoshinori K. Okuji @ 2006-03-05 22:25 UTC (permalink / raw)
To: The development of GRUB 2
On Friday 03 March 2006 15:23, Vesa Jääskeläinen wrote:
> Nowadays 1024x768 is a normal standard resolution.
Even if it is very popular, since the boot loader is a critical part of an
operation system, the default should be set to something really safe. So I
prefer 640x480. It is up to the user (or the vendor shipping GRUB) to change
it to something more comfortable.
Okuji
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: New patch for video subsystem...
2006-03-05 22:25 ` Yoshinori K. Okuji
@ 2006-03-06 19:56 ` Vesa Jääskeläinen
2006-03-09 20:43 ` Vesa Jääskeläinen
0 siblings, 1 reply; 14+ messages in thread
From: Vesa Jääskeläinen @ 2006-03-06 19:56 UTC (permalink / raw)
To: The development of GRUB 2
Yoshinori K. Okuji wrote:
> On Friday 03 March 2006 15:23, Vesa Jääskeläinen wrote:
>> Nowadays 1024x768 is a normal standard resolution.
>
> Even if it is very popular, since the boot loader is a critical part of an
> operation system, the default should be set to something really safe. So I
> prefer 640x480. It is up to the user (or the vendor shipping GRUB) to change
> it to something more comfortable.
Ok. I will change the default to that. I will only make new patch if
there are issues to be solved before commit.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: New patch for video subsystem...
2006-03-06 19:56 ` Vesa Jääskeläinen
@ 2006-03-09 20:43 ` Vesa Jääskeläinen
2006-03-10 12:21 ` Vesa Jääskeläinen
0 siblings, 1 reply; 14+ messages in thread
From: Vesa Jääskeläinen @ 2006-03-09 20:43 UTC (permalink / raw)
To: The development of GRUB 2
Vesa Jääskeläinen wrote:
> Yoshinori K. Okuji wrote:
>> On Friday 03 March 2006 15:23, Vesa Jääskeläinen wrote:
>>> Nowadays 1024x768 is a normal standard resolution.
>> Even if it is very popular, since the boot loader is a critical part of an
>> operation system, the default should be set to something really safe. So I
>> prefer 640x480. It is up to the user (or the vendor shipping GRUB) to change
>> it to something more comfortable.
>
> Ok. I will change the default to that. I will only make new patch if
> there are issues to be solved before commit.
While waiting for more comments or approval I have made some changes,
but I will commit them after we have initial set of patches in.
1. Added simple caching to font manager. Implemented as a "pageing", in
initial page there is 128 entries to hold glyphs, if it there is need
for more glyphs new page will be allocated to and added as a next page.
When finding for cached glyph, it first scans root page and then
advances to next pages.
2. Added simple buffering to videoterm. If there is enough memory for
buffer layer it will allocate it and use it. When rendering, all
operations in videoterm goes first to buffer layer, and when all layers
has been rendered to it, then it renders buffer to display. If it is not
available, we will notice some flickering.
I think the next step here would be to either add bitmap loading support
(and implement rendering for it) or add more optimal rendering
possibilities to VBE driver. Is there a nice way to split vbe driver to
more source files without causing generation of more modules. I was
thinking that "optimized" versions of some blitting operations would be
good to place on some other file as source might grow to quite large.
I am open to proposals what to implement next (it could even be
something not listed here).
Also we need to decide should there be functional changes when user has
chosen indexed color modes instead of RGB mode. (Both work now, but
indexed color mode more slowly as it tries to find best indexes for RGB
values for EVERY drawn pixel :)
Thanks,
Vesa Jääskeläinen
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: New patch for video subsystem...
2006-03-09 20:43 ` Vesa Jääskeläinen
@ 2006-03-10 12:21 ` Vesa Jääskeläinen
0 siblings, 0 replies; 14+ messages in thread
From: Vesa Jääskeläinen @ 2006-03-10 12:21 UTC (permalink / raw)
To: The development of GRUB 2
Vesa Jääskeläinen wrote:
> Is there a nice way to split vbe driver to
> more source files without causing generation of more modules. I was
> thinking that "optimized" versions of some blitting operations would be
> good to place on some other file as source might grow to quite large.
I should have sleeped before asking this question :) conf/*.rmk and just
adding source file to vbe.mod defs....
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: New patch for video subsystem...
2006-03-03 15:23 ` Vesa Jääskeläinen
2006-03-05 22:25 ` Yoshinori K. Okuji
@ 2006-03-12 14:49 ` Marco Gerards
2006-03-12 21:23 ` Vesa Jääskeläinen
2006-03-12 14:50 ` Marco Gerards
2 siblings, 1 reply; 14+ messages in thread
From: Marco Gerards @ 2006-03-12 14:49 UTC (permalink / raw)
To: Vesa Jääskeläinen; +Cc: The development of GRUB 2
Vesa Jääskeläinen <chaac@nic.fi> writes:
Hi Vesa,
Thanks a lot for the amount of work you did again! Sorry I am this
late with reviewing the patch. I assume if someone else wanted to
comment on your code, he would've done so by now. Can you please
correct the patch using my comments (and check if they also apply
elsewhere in your code) and commit the patch after that?
First of all some general comments. Please look for these issues in
the entire file, I didn't mark all:
- Between two lines in a ChangeLog entry or comment, use two spaces
after the `.'.
- Sometimes in function calls/prototypes you can join lines by using
multiple arguments on a line. Please do this, but make sure the
line does not get too long (stay below 80).
- Sometimes you use too many braces for if statements. Can you change
this so the code looks a bit more like the rest of GRUB?
Thanks,
Marco
> Marco Gerards wrote:
>> Vesa Jääskeläinen <chaac@nic.fi> writes:
>>
>> Hi Vesa,
>>
>> Thanks for your patch. I have done a review, but you should know that
>> I am not a graphics expert and don't understand all of the code in
>> detail. Most issues are GCS related, they don't only apply to the
>> line I commented on, but in general. Please make sure all the code is
>> fixed and not this single line.
>
> That wasn't a small job ;).. I hope I got all right.
:-)
>> I hope other people will do a quick review as well, so the code can be
>> committed soon in a state everyone is happy with.
>
> Sounds fine.
>
> I have made modifications and attached it as a new diff in this message.
Cool, I will review it now.
>>> How to use it:
>>> In order to have graphical console, you need to first load video driver
>>> (that would be vbe module) and then load videoterm module. After that
>>> you will need to tell what video mode you would like to use. And last
>>> you just initialize it with "terminal videoterm".
>>>
>>> Example command sequence:
>>> insmod font
>>> font /boot/grub/unifont.pff
>>> insmod terminal
>>> insmod vbe
>>> insmod videoterm
>>> set video_mode=1024x768
>>> terminal videoterm
>>>
>>> How to fine tune video mode:
>>> Handling of video_mode environment variable is a flexible one. You can
>>> specify multiple settings at one line. If video_mode is not set, it will
>>> use 1024x768 as a default resolution and will use highes number of
>>> colors available. Supported options are following:
>>
>> Personally I would prefer a VGA compatible default. The reason for
>> that is that not always videoterm.mod is loaded from grub.cfg. For
>> example, the module might be added to the (GRUB 2) kernel when loading
>> GRUB via the network.
>
> Well that default is in videoterm, and if it is not loaded then I do not
> see that as a problem. We can change the default resolution easily if
> that is the case. And if you need it for other purposes currently you
> will need to tell what mode you want.
>
> Nowadays 1024x768 is a normal standard resolution.
Right. The problem is this:
When using network boot, you can specify which modules you want to
use. If you do not have a grub.cfg, or can't load it for some reason,
you will not get a working terminal if you only can do VGA. I think
we can assume everyone has VGA, so we can use 640x400x4bpp. Of course
it should be possible to select a higher resolution afterwards.
>> As for the name, I do not think videoterm is a good name. For my
>> feeling something like `fbterm' or so is better. Perhaps someone else
>> has some good suggestions.
>
> I am all ears for suggestions.
What did you think of fbterm, as I proposed? I think it is better,
but I do not think it is perfect, so better suggestions are still
welcome. :-)
>>> width=<value>
>>> height=<value>
>>> index
>>> rgb
>>> <width>x<height>x<depth>
>>>
>>> And you can make combo's of those like:
>>>
>>> set video_mode="width=1024 height=768 rgb"
>>
>> I prefer to just use a simplified notation. So 1024x768x24. Most
>> people understand this notation, it will make scripting easier and
>> doesn't require that much code for parsing.
>
> Reason why I added more complex one is that there might be settings that
> would be good to be parsed to flags field.
Can you give an example? In that case we can better have a
video_flags variable or so, I think.
>>> + * video/i386/pc/vbe.c: Refactored to new video subsystem.
>>
>> Just leave away this line. Usually this is done by using `All users
>> changed.' when interfaces change or functions are renamed.
>
> Hmm. But then there is no mentioning about changes done in this file at
> all?. (I have removed it from current diff.)
Oh, if there are other changes, they should be mentioned of course.
But in that case your comment was not sufficient anyways.
>>> -# For vga.mod.
>>> -vga_mod_SOURCES = term/i386/pc/vga.c
>>> -vga_mod_CFLAGS = $(COMMON_CFLAGS)
>>> -vga_mod_LDFLAGS = $(COMMON_LDFLAGS)
>>
>> Why do you remove this?
>
> After modifying the fontmanager it would have needed to make some
> changes to VGA code. And I am not familiar with VGA planes and such, so
> I left it out.
So the VGA code is broken now?
>>> +typedef grub_uint32_t grub_color_t;
>>
>> I think grub_video_color_t is better.
>
> It is a long one, but changed.
If you use Emacs, you can use the M-/ key combination to complete
words. It helps a bit in such cases. ;-)
>>> + /* Leave borders for virtual screen. */
>>> + width = mode_info.width - (2 * 10);
>>> + height = mode_info.height - (2 * 10);
>>
>> Can you explain this? Isn't it better to use some font width
>> multiple?
>
> It was something from the "hat". Basic idea here is here to show that it
> can be anything. In future this most likely changes to something
> completely different as we want(?) to have more flexibility on configure
> things.
Oh, I see. In that case it would be better to use a macro so the
border width can be easily changed. And it will make the code a bit
easier to read (code with a lot of magic numbers is hard to read).
>>> + render_target->mode_info.bpp = active_mode_info.bits_per_pixel;
>>> + render_target->mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel;
>>> + render_target->mode_info.pitch = framebuffer.bytes_per_scan_line;
>>> + render_target->mode_info.number_of_colors = 256; /* TODO: fix me. */
>>> + render_target->mode_info.red_mask_size = active_mode_info.red_mask_size;
>>> + render_target->mode_info.red_field_pos = active_mode_info.red_field_position;
>>> + render_target->mode_info.green_mask_size = active_mode_info.green_mask_size;
>>> + render_target->mode_info.green_field_pos = active_mode_info.green_field_position;
>>> + render_target->mode_info.blue_mask_size = active_mode_info.blue_mask_size;
>>> + render_target->mode_info.blue_field_pos = active_mode_info.blue_field_position;
>>> + render_target->mode_info.reserved_mask_size = active_mode_info.rsvd_mask_size;
>>> + render_target->mode_info.reserved_field_pos = active_mode_info.rsvd_field_position;
>>
>> Isn't it possible to copy this in a single statement?
>
> No. As structure types are different.
Ok.
>>> +static grub_err_t
>>> +grub_video_vbe_swap_buffers (void)
>>> +{
>>> + /* TODO: Implement buffer swapping. */
>>
>> Sin't this just activating another region in the video memory? I
>> think it would be quite trivial when using VESA.
>
> Depends if we have enough memory on card. But will be done. I was
> intending to implement this functionality after we have version
> in CVS.
Cool :-)
>> bpp is set to 32, while number of colors says 256, are you sure this
>> is correct? I prefer a bpp of 8 as default, for compatibility
>> reasons.
>
> number_of_colors tells how many indexed colors we have in mode. In RGB
> rendering target we have always 256 emulated indexed colors.
>
> As there is a comment in file (now perhaps better written), currently
> only RGB rendering targets are supported. This is not a huge problem as
> blit function can handle it even for indexed color modes.
Ehm? So it doesn't work, but it does? Sorry, I do not understand
you.
---------------------------------------------------------------------
The new patch:
> diff -ruN -x '*CVS*' grub2/ChangeLog grub2.new/ChangeLog
> --- grub2/ChangeLog 2006-02-09 00:42:47.000000000 +0200
> +++ grub2.new/ChangeLog 2006-03-03 16:51:42.214034272 +0200
> @@ -1,3 +1,110 @@
> +2006-02-25 Vesa Jaaskelainen <chaac@nic.fi>
> +
> + * DISTLIST: Added include/grub/video.h, term/videoterm.c,
> + video/video.c. Removed term/i386/pc/vesafb.c.
Please use double spaces between sentences. Both in changelog entries
and in comments.
> diff -ruN -x '*CVS*' grub2/commands/videotest.c grub2.new/commands/videotest.c
> --- grub2/commands/videotest.c 1970-01-01 02:00:00.000000000 +0200
> +++ grub2.new/commands/videotest.c 2006-03-03 16:56:57.792059120 +0200
> @@ -0,0 +1,133 @@
> +/*
> + * GRUB -- GRand Unified Bootloader
> + * Copyright (C) 2006 Free Software Foundation, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +#include <grub/machine/memory.h>
> +#include <grub/video.h>
> +#include <grub/types.h>
> +#include <grub/dl.h>
> +#include <grub/misc.h>
> +#include <grub/normal.h>
> +#include <grub/arg.h>
> +#include <grub/mm.h>
> +#include <grub/font.h>
> +#include <grub/term.h>
> +
> +static grub_err_t
> +grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)),
> + int argc __attribute__ ((unused)),
> + char **args __attribute__ ((unused)))
> +{
> + if (grub_video_setup (1024,
> + 768,
> + GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != GRUB_ERR_NONE)
> + {
> + return grub_errno;
> + }
Can you remove the braces?
> + grub_getkey ();
> +
> + grub_video_color_t color;
> + unsigned int x, y, width, height;
Please just use a single declaration per line. So you would have to
split this up into 4 lines.
> + grub_video_set_viewport (x + 150, y + 150, width - 150*2, height - 150*2);
Spaces around the `*'.
> + color = grub_video_map_rgb (77,33,77);
Spaces after the `,'.
> + color = grub_video_map_rgb (255,255,255);
Likewise.
> + grub_video_blit_glyph (&glyph, color, 16*2, 16);
And here.
> + for (i = 0; i < 16; i++)
> + {
> + grub_printf("color %d: %08x\n", i, palette[i]);
> + }
Braces.
> + glyph->height = 16;
> + glyph->baseline = (16*3)/4;
Spaces.
> - if (grub_file_read (font->file, (char *) &w, 4) != 4)
> + if ((len = grub_file_read (font->file, (char *) &w, sizeof (w))) != 4)
The last 4 should also be a sizeof.
> + /* Temporary workaround, fix font bitmap. */
> + for (y = 0; y < 16; y++)
> + {
> + for (x = 0; x < w; x++)
> + {
> + glyph->bitmap[y * w + x] = bitmap[x * 16 + y];
> + }
> + }
Braces.
> +struct grub_video_mode_info {
Can you move the brace to the next line?
> + /* Text buffer for virual screen. Contains (columns * rows) number
> + of entries. */
Typo.
> + /* Intialize user requested mode. */
Typo.
> + /* Create virtual screen. */
> + if (grub_virtual_screen_setup (10,
> + 10,
> + width,
> + height) != GRUB_ERR_NONE)
This fits on less lines, I think?
> +static void
> +redraw_screen_rect (unsigned int x,
> + unsigned int y,
> + unsigned int width,
> + unsigned int height)
Doesn't this fit on two lines?
> + grub_video_blit_render_target (text_layer,
> + x,
> + y,
> + x - virtual_screen.offset_x,
> + y - virtual_screen.offset_y,
> + width,
> + height);
> +}
Same here.
> + if (x < dirty_region.top_left_x)
> + {
> + dirty_region.top_left_x = x;
> + }
> + if (y < dirty_region.top_left_y)
> + {
> + dirty_region.top_left_y = y;
> + }
> + if ((x + (int)width - 1) > dirty_region.bottom_right_x)
> + {
> + dirty_region.bottom_right_x = x + width - 1;
> + }
> + if ((y + (int)height - 1) > dirty_region.bottom_right_y)
> + {
> + dirty_region.bottom_right_y = y + height - 1;
> + }
Please remove the braces.
> +static void
> +grub_videoterm_gotoxy (grub_uint8_t x, grub_uint8_t y)
> +{
> + if (x >= virtual_screen.columns || y >= virtual_screen.rows)
> + {
> + grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)",
> + (unsigned) x, (unsigned) y);
> + return;
> + }
I wonder if it is useful to do error handing here. First of all,
callers should be more careful. And I think the user does not want to
be bothered with this. I think it is better to set x and y to max and
continue as if nothing happened.
Or you might want to use grub_printf to show when something like this
happens. Or perhaps using assertions would be nice here, but we do
not have assertions (yet).
> +/* General TODO's:
> + - Implement mode optimized operations and automatically select best
> +
> +*/
Better move this to the wiki.
> + /* Get alpha component. */
> + if (source->mode_info.reserved_mask_size > 0)
> + {
> + tmp = color >> source->mode_info.reserved_field_pos;
> + tmp &= (1 << source->mode_info.reserved_mask_size) - 1;
> + tmp <<= 8 - source->mode_info.reserved_mask_size;
> + tmp |= (1 << (8 - source->mode_info.reserved_mask_size)) - 1;
> + }
> else
> - {
> - grub_vbe_set_pixel_rgb (x,
> - y,
> - 0,
> - 0,
> - 0);
> - }
Can this be done on a single line and without braces?
> + /* 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);
> + }
> + }
> + }
Braces..
> +GRUB_MOD_INIT(video_i386_pc_vbe)
> +{
> + grub_video_register (&grub_video_vbe_adapter);
> +}
> +
> +GRUB_MOD_FINI(video_i386_pc_ovbe)
Typo.
> +grub_err_t
> +grub_video_get_info (struct grub_video_mode_info *mode_info)
> +{
> + if (! grub_video_adapter_active)
> + {
> + return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
> + }
Can you remove the brace? Same for all other functions with this same
check.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: New patch for video subsystem...
2006-03-03 15:23 ` Vesa Jääskeläinen
2006-03-05 22:25 ` Yoshinori K. Okuji
2006-03-12 14:49 ` Marco Gerards
@ 2006-03-12 14:50 ` Marco Gerards
2 siblings, 0 replies; 14+ messages in thread
From: Marco Gerards @ 2006-03-12 14:50 UTC (permalink / raw)
To: Vesa Jääskeläinen; +Cc: The development of GRUB 2
Vesa Jääskeläinen <chaac@nic.fi> writes:
> Marco Gerards wrote:
>> Vesa Jääskeläinen <chaac@nic.fi> writes:
>>
>> Hi Vesa,
>>
>> Thanks for your patch. I have done a review, but you should know that
>> I am not a graphics expert and don't understand all of the code in
>> detail. Most issues are GCS related, they don't only apply to the
>> line I commented on, but in general. Please make sure all the code is
>> fixed and not this single line.
>
> That wasn't a small job ;).. I hope I got all right.
One more thing... Can you check if the endianess when loading fonts is
converted to the machine endianess? I had some serious doubts that
this was done correctly. This should work, otherwise your code will
seriously break on some archs...
--
Marco
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: New patch for video subsystem...
2006-03-12 14:49 ` Marco Gerards
@ 2006-03-12 21:23 ` Vesa Jääskeläinen
2006-03-14 17:09 ` Vesa Jääskeläinen
0 siblings, 1 reply; 14+ messages in thread
From: Vesa Jääskeläinen @ 2006-03-12 21:23 UTC (permalink / raw)
To: The development of GRUB 2
Marco Gerards wrote:
> Vesa Jääskeläinen <chaac@nic.fi> writes:
>
> Hi Vesa,
>
> Thanks a lot for the amount of work you did again! Sorry I am this
> late with reviewing the patch. I assume if someone else wanted to
> comment on your code, he would've done so by now. Can you please
> correct the patch using my comments (and check if they also apply
> elsewhere in your code) and commit the patch after that?
>
> First of all some general comments. Please look for these issues in
> the entire file, I didn't mark all:
>
> - Between two lines in a ChangeLog entry or comment, use two spaces
> after the `.'.
Hope I catched all instances you were referring to. I think all comments
had those already.
> - Sometimes in function calls/prototypes you can join lines by using
> multiple arguments on a line. Please do this, but make sure the
> line does not get too long (stay below 80).
Actually not all lines can be limited to 80 :|... But I will try to make
sure most of them fit nicely.
> - Sometimes you use too many braces for if statements. Can you change
> this so the code looks a bit more like the rest of GRUB?
I'll try to follow this as good as I can :)
I will send new patch a bit later as a new email as this email gets
quite large :).
Thanks,
Vesa Jääskeläinen
>> Marco Gerards wrote:
>>> Vesa Jääskeläinen <chaac@nic.fi> writes:
>> Well that default is in videoterm, and if it is not loaded then I do not
>> see that as a problem. We can change the default resolution easily if
>> that is the case. And if you need it for other purposes currently you
>> will need to tell what mode you want.
>>
>> Nowadays 1024x768 is a normal standard resolution.
>
> Right. The problem is this:
>
> When using network boot, you can specify which modules you want to
> use. If you do not have a grub.cfg, or can't load it for some reason,
> you will not get a working terminal if you only can do VGA. I think
> we can assume everyone has VGA, so we can use 640x400x4bpp. Of course
> it should be possible to select a higher resolution afterwards.
Default was changed to 640x480 as per Okuji's request. I think we should
adapt that VGA console as a VGA driver that supports those "general"
cases when requested. Other memory models (like 4 bit planar modes) can
be supported later on if there is a real need.
Only problem there is that VBE does not list those VGA modes at all. In
example my card only lists modes that are better than 8 bit indexed
modes. Adding support for requesting 4 bit modes actually means to add
more flags to video setup interface functionality and then hard coding
those modes as a list.
OR we could perhaps add support to request specific mode number. But
there is currently no way to give that specific information from console
to driver. If we assume that this number is not anything, then it could
be added as set of bits in flags.
>>> As for the name, I do not think videoterm is a good name. For my
>>> feeling something like `fbterm' or so is better. Perhaps someone else
>>> has some good suggestions.
>> I am all ears for suggestions.
>
> What did you think of fbterm, as I proposed? I think it is better,
> but I do not think it is perfect, so better suggestions are still
> welcome. :-)
I do not think that fbterm informs user that it is using to video
subsystem. I think that videoterm informs user that it needs video driver.
As discussed on IRC, I have now renamed it to gfxterm.
>>>> width=<value>
>>>> height=<value>
>>>> index
>>>> rgb
>>>> <width>x<height>x<depth>
>>>>
>>>> And you can make combo's of those like:
>>>>
>>>> set video_mode="width=1024 height=768 rgb"
>>> I prefer to just use a simplified notation. So 1024x768x24. Most
>>> people understand this notation, it will make scripting easier and
>>> doesn't require that much code for parsing.
>> Reason why I added more complex one is that there might be settings that
>> would be good to be parsed to flags field.
>
> Can you give an example? In that case we can better have a
> video_flags variable or so, I think.
One example could be that you want double buffered mode or something odd
that I cannot think at the moment. But if this information is taken out
of video_mode definition then there must be a video_flags.
As discussed on IRC, I have now modified it to following:
<width>x<height>[x<bits>]
If bits are omitted, then it would auto detect mode with best number of
colors for that resolution.
An example:
"1024x768x32" would initialize mode with resolution 1024x768 and only
accept 32 bit mode. If not found it will fail.
"1024x768x8" would initialize index color mode.
"1024x768" would initialize mode with best number of colors. If there is
a 32 bit mode, it would be selected. But if there is only index color
mode it would be selected.
>>>> + * video/i386/pc/vbe.c: Refactored to new video subsystem.
>>> Just leave away this line. Usually this is done by using `All users
>>> changed.' when interfaces change or functions are renamed.
>> Hmm. But then there is no mentioning about changes done in this file at
>> all?. (I have removed it from current diff.)
>
> Oh, if there are other changes, they should be mentioned of course.
> But in that case your comment was not sufficient anyways.
Ok, I will try to summarize it more precisely then.
>>>> -# For vga.mod.
>>>> -vga_mod_SOURCES = term/i386/pc/vga.c
>>>> -vga_mod_CFLAGS = $(COMMON_CFLAGS)
>>>> -vga_mod_LDFLAGS = $(COMMON_LDFLAGS)
>>> Why do you remove this?
>> After modifying the fontmanager it would have needed to make some
>> changes to VGA code. And I am not familiar with VGA planes and such, so
>> I left it out.
>
> So the VGA code is broken now?
That is correct. I think it would be more preferable to port that
terminal as video driver. But it could stay as impedendant terminal
driver too. I can try to learn how how VGA planes work if that is
required, but if someone else has knowledge how it works, it would
fasten this process a bit.
>>>> +typedef grub_uint32_t grub_color_t;
>>> I think grub_video_color_t is better.
>> It is a long one, but changed.
>
> If you use Emacs, you can use the M-/ key combination to complete
> words. It helps a bit in such cases. ;-)
I will try to stay as far as I can from Emacs ;)... But let's drop this
religious subject here.
>>>> + /* Leave borders for virtual screen. */
>>>> + width = mode_info.width - (2 * 10);
>>>> + height = mode_info.height - (2 * 10);
>>> Can you explain this? Isn't it better to use some font width
>>> multiple?
>> It was something from the "hat". Basic idea here is here to show that it
>> can be anything. In future this most likely changes to something
>> completely different as we want(?) to have more flexibility on configure
>> things.
>
> Oh, I see. In that case it would be better to use a macro so the
> border width can be easily changed. And it will make the code a bit
> easier to read (code with a lot of magic numbers is hard to read).
Changed as a DEFINE.
>>> bpp is set to 32, while number of colors says 256, are you sure this
>>> is correct? I prefer a bpp of 8 as default, for compatibility
>>> reasons.
>> number_of_colors tells how many indexed colors we have in mode. In RGB
>> rendering target we have always 256 emulated indexed colors.
>>
>> As there is a comment in file (now perhaps better written), currently
>> only RGB rendering targets are supported. This is not a huge problem as
>> blit function can handle it even for indexed color modes.
>
> Ehm? So it doesn't work, but it does? Sorry, I do not understand
> you.
In order to support indexed color images or indexed color values in
rendering code. There must be a support to have a list of RGB values for
every 256 color indices. Now this functionality is called as emulated
palette (as it is after all emulated, eg. not supported by video mode in
use).
Currently when you are creating a custom rendering target (a layer of
bitmap data), it only support creating of 32 bit rendering targets. So
hard coding this value to 256 will work correctly in this case as we
would use emulated palette anyway. If we initialize hardware indexed
color mode, even then we are going to store palette information in
emulated palette so we can freely use that information when emulating
indexed color operations for render targets in RGB modes.
You can even draw RGB render target to index color video screen as it
will try to find best match for colors. (though it might be quite ugly
in some cases)
> ---------------------------------------------------------------------
>
> The new patch:
>
>
>> diff -ruN -x '*CVS*' grub2/ChangeLog grub2.new/ChangeLog
>> --- grub2/ChangeLog 2006-02-09 00:42:47.000000000 +0200
>> +++ grub2.new/ChangeLog 2006-03-03 16:51:42.214034272 +0200
>> @@ -1,3 +1,110 @@
>> +2006-02-25 Vesa Jaaskelainen <chaac@nic.fi>
>> +
>> + * DISTLIST: Added include/grub/video.h, term/videoterm.c,
>> + video/video.c. Removed term/i386/pc/vesafb.c.
>
> Please use double spaces between sentences. Both in changelog entries
> and in comments.
Ok.
>> diff -ruN -x '*CVS*' grub2/commands/videotest.c grub2.new/commands/videotest.c
>> --- grub2/commands/videotest.c 1970-01-01 02:00:00.000000000 +0200
>> +++ grub2.new/commands/videotest.c 2006-03-03 16:56:57.792059120 +0200
>> @@ -0,0 +1,133 @@
>> +/*
>> + * GRUB -- GRand Unified Bootloader
>> + * Copyright (C) 2006 Free Software Foundation, Inc.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
>> + */
>> +
>> +#include <grub/machine/memory.h>
>> +#include <grub/video.h>
>> +#include <grub/types.h>
>> +#include <grub/dl.h>
>> +#include <grub/misc.h>
>> +#include <grub/normal.h>
>> +#include <grub/arg.h>
>> +#include <grub/mm.h>
>> +#include <grub/font.h>
>> +#include <grub/term.h>
>> +
>> +static grub_err_t
>> +grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)),
>> + int argc __attribute__ ((unused)),
>> + char **args __attribute__ ((unused)))
>> +{
>> + if (grub_video_setup (1024,
>> + 768,
>> + GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != GRUB_ERR_NONE)
>> + {
>> + return grub_errno;
>> + }
>
> Can you remove the braces?
Ok.
>> + grub_getkey ();
>> +
>> + grub_video_color_t color;
>> + unsigned int x, y, width, height;
>
> Please just use a single declaration per line. So you would have to
> split this up into 4 lines.
Ok.
>> + grub_video_set_viewport (x + 150, y + 150, width - 150*2, height - 150*2);
>
> Spaces around the `*'.
Ok.
>> + color = grub_video_map_rgb (77,33,77);
>
> Spaces after the `,'.
Ok.
>> + color = grub_video_map_rgb (255,255,255);
>
> Likewise.
Ok.
>> + grub_video_blit_glyph (&glyph, color, 16*2, 16);
>
> And here.
Ok.
>> + for (i = 0; i < 16; i++)
>> + {
>> + grub_printf("color %d: %08x\n", i, palette[i]);
>> + }
>
> Braces.
Ok.
>> + glyph->height = 16;
>> + glyph->baseline = (16*3)/4;
>
> Spaces.
Ok.
>> - if (grub_file_read (font->file, (char *) &w, 4) != 4)
>> + if ((len = grub_file_read (font->file, (char *) &w, sizeof (w))) != 4)
>
> The last 4 should also be a sizeof.
Ok.
>> + /* Temporary workaround, fix font bitmap. */
>> + for (y = 0; y < 16; y++)
>> + {
>> + for (x = 0; x < w; x++)
>> + {
>> + glyph->bitmap[y * w + x] = bitmap[x * 16 + y];
>> + }
>> + }
>
> Braces.
Ok.
>> +struct grub_video_mode_info {
>
> Can you move the brace to the next line?
Ok.
>> + /* Text buffer for virual screen. Contains (columns * rows) number
>> + of entries. */
>
> Typo.
Fixed.
>> + /* Intialize user requested mode. */
>
> Typo.
Fixed.
>
>> + /* Create virtual screen. */
>> + if (grub_virtual_screen_setup (10,
>> + 10,
>> + width,
>> + height) != GRUB_ERR_NONE)
>
> This fits on less lines, I think?
Yes, changed 10's to DEFAULT_BORDER_SIZE.
>> +static void
>> +redraw_screen_rect (unsigned int x,
>> + unsigned int y,
>> + unsigned int width,
>> + unsigned int height)
>
> Doesn't this fit on two lines?
Ok.
>> + grub_video_blit_render_target (text_layer,
>> + x,
>> + y,
>> + x - virtual_screen.offset_x,
>> + y - virtual_screen.offset_y,
>> + width,
>> + height);
>> +}
>
> Same here.
Ok. I made it as 4 lines.
>> + if (x < dirty_region.top_left_x)
>> + {
>> + dirty_region.top_left_x = x;
>> + }
>> + if (y < dirty_region.top_left_y)
>> + {
>> + dirty_region.top_left_y = y;
>> + }
>> + if ((x + (int)width - 1) > dirty_region.bottom_right_x)
>> + {
>> + dirty_region.bottom_right_x = x + width - 1;
>> + }
>> + if ((y + (int)height - 1) > dirty_region.bottom_right_y)
>> + {
>> + dirty_region.bottom_right_y = y + height - 1;
>> + }
>
> Please remove the braces.
Ok.
>> +static void
>> +grub_videoterm_gotoxy (grub_uint8_t x, grub_uint8_t y)
>> +{
>> + if (x >= virtual_screen.columns || y >= virtual_screen.rows)
>> + {
>> + grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)",
>> + (unsigned) x, (unsigned) y);
>> + return;
>> + }
>
>
> I wonder if it is useful to do error handing here. First of all,
> callers should be more careful. And I think the user does not want to
> be bothered with this. I think it is better to set x and y to max and
> continue as if nothing happened.
>
> Or you might want to use grub_printf to show when something like this
> happens. Or perhaps using assertions would be nice here, but we do
> not have assertions (yet).
Changed it to clamp to maximum size.
>> +/* General TODO's:
>> + - Implement mode optimized operations and automatically select best
>> +
>> +*/
>
> Better move this to the wiki.
Already have some local implementation for this, so removed the line.
Will discuss this after the commit.
>> + /* Get alpha component. */
>> + if (source->mode_info.reserved_mask_size > 0)
>> + {
>> + tmp = color >> source->mode_info.reserved_field_pos;
>> + tmp &= (1 << source->mode_info.reserved_mask_size) - 1;
>> + tmp <<= 8 - source->mode_info.reserved_mask_size;
>> + tmp |= (1 << (8 - source->mode_info.reserved_mask_size)) - 1;
>> + }
>> else
>> - {
>> - grub_vbe_set_pixel_rgb (x,
>> - y,
>> - 0,
>> - 0,
>> - 0);
>> - }
>
> Can this be done on a single line and without braces?
You probably though something else here ;). Anyway there were some extra
braces at this location that I removed.
>> + /* 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);
>> + }
>> + }
>> + }
>
> Braces..
Fixed.
>
>> +GRUB_MOD_INIT(video_i386_pc_vbe)
>> +{
>> + grub_video_register (&grub_video_vbe_adapter);
>> +}
>> +
>> +GRUB_MOD_FINI(video_i386_pc_ovbe)
>
> Typo.
Fixed.
>> +grub_err_t
>> +grub_video_get_info (struct grub_video_mode_info *mode_info)
>> +{
>> + if (! grub_video_adapter_active)
>> + {
>> + return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
>> + }
>
> Can you remove the brace? Same for all other functions with this same
> check.
Done.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: New patch for video subsystem...
2006-03-12 21:23 ` Vesa Jääskeläinen
@ 2006-03-14 17:09 ` Vesa Jääskeläinen
0 siblings, 0 replies; 14+ messages in thread
From: Vesa Jääskeläinen @ 2006-03-14 17:09 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 87 bytes --]
Hi,
Here is hopefully the last patch modification :)
Thanks,
Vesa Jääskeläinen
[-- Attachment #2: grub2-video-20060314.diff --]
[-- Type: text/plain, Size: 121077 bytes --]
Index: ChangeLog
===================================================================
RCS file: /sources/grub/grub2/ChangeLog,v
retrieving revision 1.225
diff -u -r1.225 ChangeLog
--- ChangeLog 10 Mar 2006 22:27:24 -0000 1.225
+++ ChangeLog 14 Mar 2006 17:00:50 -0000
@@ -1,3 +1,150 @@
+2006-03-14 Vesa Jaaskelainen <chaac@nic.fi>
+
+ * DISTLIST: Added include/grub/video.h, term/gfxterm.c,
+ video/video.c, commands/videotest.c. Removed term/i386/pc/vesafb.c.
+
+ * conf/i386-pc.rmk (pkgdata_MODULES): Added video.mod,
+ gfxterm.mod, videotest.mod. Removed vga.mod, vesafb.mod.
+ (video_mod_SOURCES): Added.
+ (video_mod_CFLAGS): Likewise.
+ (video_mod_LDFLAGS): Likewise.
+ (gfxterm_mod_SOURCES): Likewise.
+ (gfxterm_mod_CFLAGS): Likewise.
+ (gfxterm_mod_LDFLAGS): Likewise.
+ (videotest_mod_SOURCES): Likewise.
+ (videotest_mod_CFLAGS): Likewise.
+ (videotest_mod_LDFLAGS): Likewise.
+ (vesafb_mod_SOURCES): Removed.
+ (vesafb_mod_CFLAGS): Likewise.
+ (vesafb_mod_LDFLAGS): Likewise.
+ (vga_mod_SOURCES): Likewise.
+ (vga_mod_CFLAGS): Likewise.
+ (vga_mod_LDFLAGS): Likewise.
+
+ * commands/videotest.c: New file.
+
+ * font/manager.c (fill_with_default_glyph): Modified to use
+ grub_font_glyph.
+ (grub_font_get_glyph): Likewise.
+ (fontmanager): Renamed from this...
+ (font_manager): ... to this.
+
+ * include/grub/font.h (grub_font_glyph): Added new structure.
+ (grub_font_get_glyph): Modified to use grub_font_glyph.
+
+ * include/grub/misc.h (grub_abs): Added as inline function.
+
+ * include/grub/video.h: New file.
+
+ * include/grub/i386/pc/vbe.h (GRUB_VBE_STATUS_OK): New macro.
+ (GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL): Likewise.
+ (GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR): Likewise.
+ (grub_vbe_get_controller_info): Renamed from this...
+ (grub_vbe_bios_get_controller_info): ... to this.
+ (grub_vbe_get_mode_info): Renamed from this...
+ (grub_vbe_bios_get_mode_info): ... to this.
+ (grub_vbe_set_mode): Renamed from this...
+ (grub_vbe_bios_set_mode): ... to this.
+ (grub_vbe_get_mode): Renamed from this...
+ (grub_vbe_bios_get_mode): ... to this.
+ (grub_vbe_set_memory_window): Renamed from this...
+ (grub_vbe_bios_set_memory_window): ... to this.
+ (grub_vbe_get_memory_window): Renamed from this...
+ (grub_vbe_bios_get_memory_window): ... to this.
+ (grub_vbe_set_scanline_length): Renamed from this...
+ (grub_vbe_set_scanline_length): ... to this.
+ (grub_vbe_get_scanline_length): Renamed from this...
+ (grub_vbe_bios_get_scanline_length): ... to this.
+ (grub_vbe_set_display_start): Renamed from this...
+ (grub_vbe_bios_set_display_start): ... to this.
+ (grub_vbe_get_display_start): Renamed from this...
+ (grub_vbe_bios_get_display_start): ... to this.
+ (grub_vbe_set_palette_data): Renamed from this...
+ (grub_vbe_bios_set_palette_data): ... to this.
+ (grub_vbe_set_pixel_rgb): Removed.
+ (grub_vbe_set_pixel_index): Likewise.
+
+ * kern/i386/pc/startup.S (grub_vbe_get_controller_info): Renamed
+ from this...
+ (grub_vbe_bios_get_controller_info): ... to this.
+ (grub_vbe_get_mode_info): Renamed from this...
+ (grub_vbe_bios_get_mode_info): ... to this.
+ (grub_vbe_set_mode): Renamed from this...
+ (grub_vbe_bios_set_mode): ... to this.
+ (grub_vbe_get_mode): Renamed from this...
+ (grub_vbe_bios_get_mode): ... to this.
+ (grub_vbe_set_memory_window): Renamed from this...
+ (grub_vbe_bios_set_memory_window): ... to this.
+ (grub_vbe_get_memory_window): Renamed from this...
+ (grub_vbe_bios_get_memory_window): ... to this.
+ (grub_vbe_set_scanline_length): Renamed from this...
+ (grub_vbe_set_scanline_length): ... to this.
+ (grub_vbe_get_scanline_length): Renamed from this...
+ (grub_vbe_bios_get_scanline_length): ... to this.
+ (grub_vbe_set_display_start): Renamed from this...
+ (grub_vbe_bios_set_display_start): ... to this.
+ (grub_vbe_get_display_start): Renamed from this...
+ (grub_vbe_bios_get_display_start): ... to this.
+ (grub_vbe_set_palette_data): Renamed from this...
+ (grub_vbe_bios_set_palette_data): ... to this.
+ (grub_vbe_bios_get_controller_info): Fixed problem with registers
+ getting corrupted after calling it. Added more pushes and pops.
+ (grub_vbe_bios_set_mode): Likewise.
+ (grub_vbe_bios_get_mode): Likewise.
+ (grub_vbe_bios_get_memory_window): Likewise.
+ (grub_vbe_bios_set_scanline_length): Likewise.
+ (grub_vbe_bios_get_scanline_length): Likewise.
+ (grub_vbe_bios_get_display_start): Likewise.
+ (grub_vbe_bios_set_palette_data): Likewise.
+
+ * normal/cmdline.c (cl_set_pos): Refresh the screen.
+ (cl_insert): Likewise.
+ (cl_delete): Likewise.
+
+ * term/gfxterm.c: New file.
+
+ * term/i386/pc/vesafb.c: Removed file.
+
+ * video/video.c: New file.
+
+ * video/i386/pc/vbe.c (real2pm): Added new function.
+ (grub_video_vbe_draw_pixel): Likewise.
+ (grub_video_vbe_get_video_ptr): Likewise.
+ (grub_video_vbe_get_pixel): Likewise
+ (grub_video_vbe_init): Likewise.
+ (grub_video_vbe_fini): Likewise.
+ (grub_video_vbe_setup): Likewise.
+ (grub_video_vbe_get_info): Likewise.
+ (grub_video_vbe_set_palette): Likewise.
+ (grub_video_vbe_get_palette): Likewise.
+ (grub_video_vbe_set_viewport): Likewise.
+ (grub_video_vbe_get_viewport): Likewise.
+ (grub_video_vbe_map_color): Likewise.
+ (grub_video_vbe_map_rgb): Likewise.
+ (grub_video_vbe_map_rgba): Likewise.
+ (grub_video_vbe_unmap_color): Likewise.
+ (grub_video_vbe_fill_rect): Likewise.
+ (grub_video_vbe_blit_glyph): Likewise.
+ (grub_video_vbe_blit_bitmap): Likewise.
+ (grub_video_vbe_blit_render_target): Likewise.
+ (grub_video_vbe_scroll): Likewise.
+ (grub_video_vbe_swap_buffers): Likewise.
+ (grub_video_vbe_create_render_target): Likewise.
+ (grub_video_vbe_delete_render_target): Likewise.
+ (grub_video_vbe_set_active_render_target): Likewise.
+ (grub_vbe_set_pixel_rgb): Remove function.
+ (grub_vbe_set_pixel_index): Likewise.
+ (index_color_mode): Remove static variable.
+ (active_mode): Likewise.
+ (framebuffer): Likewise.
+ (bytes_per_scan_line): Likewise.
+ (grub_video_vbe_adapter): Added new static variable.
+ (framebuffer): Likewise.
+ (render_target): Likewise.
+ (initial_mode): Likewise.
+ (mode_in_use): Likewise.
+ (mode_list): Likewise.
+
2006-03-10 Marco Gerards <marco@gnu.org>
* configure.ac (AC_INIT): Bumped to 1.93.
Index: DISTLIST
===================================================================
RCS file: /sources/grub/grub2/DISTLIST,v
retrieving revision 1.23
diff -u -r1.23 DISTLIST
--- DISTLIST 10 Mar 2006 22:27:24 -0000 1.23
+++ DISTLIST 14 Mar 2006 17:00:50 -0000
@@ -41,6 +41,7 @@
commands/terminal.c
commands/test.c
commands/timeout.c
+commands/videotest.c
commands/i386/pc/halt.c
commands/i386/pc/play.c
commands/i386/pc/reboot.c
@@ -107,6 +108,7 @@
include/grub/terminfo.h
include/grub/tparm.h
include/grub/types.h
+include/grub/video.h
include/grub/i386/setjmp.h
include/grub/i386/types.h
include/grub/i386/pc/biosdisk.h
@@ -209,6 +211,7 @@
partmap/sun.c
term/terminfo.c
term/tparm.c
+term/gfxterm.c
term/i386/pc/console.c
term/i386/pc/serial.c
term/i386/pc/vesafb.c
@@ -230,4 +233,5 @@
util/i386/pc/misc.c
util/powerpc/ieee1275/grub-mkimage.c
util/powerpc/ieee1275/misc.c
+video/video.c
video/i386/pc/vbe.c
Index: commands/videotest.c
===================================================================
RCS file: commands/videotest.c
diff -N commands/videotest.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ commands/videotest.c 14 Mar 2006 17:00:50 -0000
@@ -0,0 +1,130 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/machine/memory.h>
+#include <grub/video.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/arg.h>
+#include <grub/mm.h>
+#include <grub/font.h>
+#include <grub/term.h>
+
+static grub_err_t
+grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+ if (grub_video_setup (1024, 768,
+ GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != GRUB_ERR_NONE)
+ return grub_errno;
+
+ grub_getkey ();
+
+ grub_video_color_t color;
+ unsigned int x;
+ unsigned int y;
+ unsigned int width;
+ unsigned int height;
+ int i;
+ struct grub_font_glyph glyph;
+ struct grub_video_render_target *text_layer;
+ grub_video_color_t palette[16];
+
+ grub_video_get_viewport (&x, &y, &width, &height);
+
+ grub_video_create_render_target (&text_layer, width, height,
+ GRUB_VIDEO_MODE_TYPE_RGB
+ | GRUB_VIDEO_MODE_TYPE_ALPHA);
+
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ color = grub_video_map_rgb (0, 0, 0);
+ grub_video_fill_rect (color, 0, 0, width, height);
+
+ color = grub_video_map_rgb (255, 0, 0);
+ grub_video_fill_rect (color, 0, 0, 100, 100);
+
+ color = grub_video_map_rgb (0, 255, 255);
+ grub_video_fill_rect (color, 100, 100, 100, 100);
+
+ grub_font_get_glyph ('*', &glyph);
+ grub_video_blit_glyph (&glyph, color, 200 ,0);
+
+ grub_video_set_viewport (x + 150, y + 150,
+ width - 150 * 2, height - 150 * 2);
+ color = grub_video_map_rgb (77, 33, 77);
+ grub_video_fill_rect (color, 0, 0, width, height);
+
+ grub_video_set_active_render_target (text_layer);
+
+ color = grub_video_map_rgb (255, 255, 255);
+
+ grub_font_get_glyph ('A', &glyph);
+ grub_video_blit_glyph (&glyph, color, 16, 16);
+ grub_font_get_glyph ('B', &glyph);
+ grub_video_blit_glyph (&glyph, color, 16 * 2, 16);
+
+ grub_font_get_glyph ('*', &glyph);
+
+ for (i = 0; i < 16; i++)
+ {
+ color = grub_video_map_color (i);
+ palette[i] = color;
+ grub_video_blit_glyph (&glyph, color, 16 + i * 16, 32);
+ }
+
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ for (i = 0; i < 255; i++)
+ {
+ color = grub_video_map_rgb (i, 33, 77);
+ grub_video_fill_rect (color, 0, 0, width, height);
+ grub_video_blit_render_target (text_layer, 0, 0, 0, 0, width, height);
+ }
+
+ grub_getkey ();
+
+ grub_video_delete_render_target (text_layer);
+
+ grub_video_restore ();
+
+ for (i = 0; i < 16; i++)
+ grub_printf("color %d: %08x\n", i, palette[i]);
+
+ grub_errno = GRUB_ERR_NONE;
+ return grub_errno;
+}
+
+GRUB_MOD_INIT(videotest)
+{
+ grub_register_command ("videotest",
+ grub_cmd_videotest,
+ GRUB_COMMAND_FLAG_BOTH,
+ "videotest",
+ "Test video subsystem",
+ 0);
+}
+
+GRUB_MOD_FINI(videotest)
+{
+ grub_unregister_command ("videotest");
+}
Index: conf/i386-pc.rmk
===================================================================
RCS file: /sources/grub/grub2/conf/i386-pc.rmk,v
retrieving revision 1.58
diff -u -r1.58 i386-pc.rmk
--- conf/i386-pc.rmk 25 Dec 2005 15:59:50 -0000 1.58
+++ conf/i386-pc.rmk 14 Mar 2006 17:00:52 -0000
@@ -113,9 +113,10 @@
grub_install_SOURCES = util/i386/pc/grub-install.in
# Modules.
-pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod vga.mod \
+pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod \
_multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod \
- vbe.mod vesafb.mod vbetest.mod vbeinfo.mod play.mod
+ vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
+ videotest.mod play.mod
# For _chain.mod.
_chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -157,11 +158,6 @@
halt_mod_CFLAGS = $(COMMON_CFLAGS)
halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
-# For vga.mod.
-vga_mod_SOURCES = term/i386/pc/vga.c
-vga_mod_CFLAGS = $(COMMON_CFLAGS)
-vga_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
# For serial.mod.
serial_mod_SOURCES = term/i386/pc/serial.c
serial_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -182,11 +178,6 @@
vbe_mod_CFLAGS = $(COMMON_CFLAGS)
vbe_mod_LDFLAGS = $(COMMON_LDFLAGS)
-# For vesafb.mod.
-vesafb_mod_SOURCES = term/i386/pc/vesafb.c
-vesafb_mod_CFLAGS = $(COMMON_CFLAGS)
-vesafb_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
# For vbeinfo.mod.
vbeinfo_mod_SOURCES = commands/i386/pc/vbeinfo.c
vbeinfo_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -202,4 +193,19 @@
play_mod_CFLAGS = $(COMMON_CFLAGS)
play_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For video.mod.
+video_mod_SOURCES = video/video.c
+video_mod_CFLAGS = $(COMMON_CFLAGS)
+video_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For gfxterm.mod.
+gfxterm_mod_SOURCES = term/gfxterm.c
+gfxterm_mod_CFLAGS = $(COMMON_CFLAGS)
+gfxterm_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For videotest.mod.
+videotest_mod_SOURCES = commands/videotest.c
+videotest_mod_CFLAGS = $(COMMON_CFLAGS)
+videotest_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
Index: font/manager.c
===================================================================
RCS file: /sources/grub/grub2/font/manager.c,v
retrieving revision 1.6
diff -u -r1.6 manager.c
--- font/manager.c 13 Nov 2005 15:47:09 -0000 1.6
+++ font/manager.c 14 Mar 2006 17:00:53 -0000
@@ -1,6 +1,6 @@
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2003,2005 Free Software Foundation, Inc.
+ * Copyright (C) 2003,2005,2006 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -121,7 +121,7 @@
}
/* Return the offset of the glyph corresponding to the codepoint CODE
- in the font FONT. If no found, return zero. */
+ in the font FONT. If no found, return zero. */
static grub_uint32_t
find_glyph (const struct font *font, grub_uint32_t code)
{
@@ -151,26 +151,27 @@
/* Set the glyph to something stupid. */
static void
-fill_with_default_glyph (unsigned char bitmap[32], unsigned *width)
+fill_with_default_glyph (grub_font_glyph_t glyph)
{
- if (bitmap)
- {
- unsigned i;
+ unsigned i;
- for (i = 0; i < 16; i++)
- bitmap[i] = (i & 1) ? 0x55 : 0xaa;
- }
-
- *width = 1;
+ for (i = 0; i < 16; i++)
+ glyph->bitmap[i] = (i & 1) ? 0x55 : 0xaa;
+
+ glyph->char_width = 1;
+ glyph->width = glyph->char_width * 8;
+ glyph->height = 16;
+ glyph->baseline = (16 * 3) / 4;
}
-/* Get a glyph corresponding to the codepoint CODE. Always fill BITMAP
- and WIDTH with something, even if no glyph is found. */
+/* Get a glyph corresponding to the codepoint CODE. Always fill glyph
+ information with something, even if no glyph is found. */
int
grub_font_get_glyph (grub_uint32_t code,
- unsigned char bitmap[32], unsigned *width)
+ grub_font_glyph_t glyph)
{
struct font *font;
+ grub_uint8_t bitmap[32];
/* FIXME: It is necessary to cache glyphs! */
@@ -183,12 +184,20 @@
if (offset)
{
grub_uint32_t w;
+ unsigned int x;
+ unsigned int y;
+ int len;
+
+ /* Make sure we can find glyphs for error messages. Push active
+ error message to error stack and reset error message. */
+ grub_error_push ();
grub_file_seek (font->file, offset);
- if (grub_file_read (font->file, (char *) &w, 4) != 4)
+ if ((len = grub_file_read (font->file, (char *) &w, sizeof (w)))
+ != sizeof (w))
{
- remove_font (font);
- goto restart;
+ remove_font (font);
+ goto restart;
}
w = grub_le_to_cpu32 (w);
@@ -206,14 +215,26 @@
remove_font (font);
goto restart;
}
-
- *width = w;
+
+ /* Temporary workaround, fix font bitmap. */
+ for (y = 0; y < 16; y++)
+ for (x = 0; x < w; x++)
+ glyph->bitmap[y * w + x] = bitmap[x * 16 + y];
+
+ glyph->char_width = w;
+ glyph->width = glyph->char_width * 8;
+ glyph->height = 16;
+ glyph->baseline = (16 * 3) / 4;
+
+ /* Restore old error message. */
+ grub_error_pop ();
+
return 1;
}
}
- /* Uggh... No font was found. */
- fill_with_default_glyph (bitmap, width);
+ /* Uggh... No font was found. */
+ fill_with_default_glyph (glyph);
return 0;
}
@@ -232,15 +253,14 @@
return 0;
}
-GRUB_MOD_INIT(fontmanager)
+GRUB_MOD_INIT(font_manager)
{
- (void) mod; /* Stop warning. */
grub_register_command ("font", font_command, GRUB_COMMAND_FLAG_BOTH,
"font FILE...",
"Specify one or more font files to display.", 0);
}
-GRUB_MOD_FINI(fontmanager)
+GRUB_MOD_FINI(font_manager)
{
grub_unregister_command ("font");
}
Index: include/grub/font.h
===================================================================
RCS file: /sources/grub/grub2/include/grub/font.h,v
retrieving revision 1.3
diff -u -r1.3 font.h
--- include/grub/font.h 4 Apr 2004 13:46:00 -0000 1.3
+++ include/grub/font.h 14 Mar 2006 17:00:53 -0000
@@ -24,7 +24,31 @@
#define GRUB_FONT_MAGIC "PPF\x7f"
+struct grub_font_glyph
+{
+ /* Glyph width in pixels. */
+ grub_uint8_t width;
+
+ /* Glyph height in pixels. */
+ grub_uint8_t height;
+
+ /* Glyph width in characters. */
+ grub_uint8_t char_width;
+
+ /* Glyph baseline position in pixels (from up). */
+ grub_uint8_t baseline;
+
+ /* Glyph bitmap data array of bytes in ((width + 7) / 8) * height.
+ Bitmap is formulated by height scanlines, each scanline having
+ width number of pixels. Pixels are coded as bits, value 1 meaning
+ of opaque pixel and 0 is transparent. If width does not fit byte
+ boundary, it will be padded with 0 to make it fit. */
+ grub_uint8_t bitmap[32];
+};
+
+typedef struct grub_font_glyph *grub_font_glyph_t;
+
int grub_font_get_glyph (grub_uint32_t code,
- unsigned char bitmap[32], unsigned *width);
+ grub_font_glyph_t glyph);
#endif /* ! GRUB_FONT_HEADER */
Index: include/grub/misc.h
===================================================================
RCS file: /sources/grub/grub2/include/grub/misc.h,v
retrieving revision 1.17
diff -u -r1.17 misc.h
--- include/grub/misc.h 24 Oct 2005 10:23:46 -0000 1.17
+++ include/grub/misc.h 14 Mar 2006 17:00:53 -0000
@@ -76,4 +76,14 @@
const grub_uint8_t *src,
grub_size_t size);
+/* Inline functions. */
+static inline unsigned int
+grub_abs (int x)
+{
+ if (x < 0)
+ return (unsigned int)(-x);
+ else
+ return (unsigned int)x;
+}
+
#endif /* ! GRUB_MISC_HEADER */
Index: include/grub/video.h
===================================================================
RCS file: include/grub/video.h
diff -N include/grub/video.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ include/grub/video.h 14 Mar 2006 17:00:53 -0000
@@ -0,0 +1,309 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006 Free Software Foundation, Inc.
+ *
+ * GRUB is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef GRUB_VIDEO_HEADER
+#define GRUB_VIDEO_HEADER 1
+
+#include <grub/err.h>
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+typedef grub_uint32_t grub_video_color_t;
+
+struct grub_video_render_target;
+
+/* Defines used to describe video mode or rendering target. */
+#define GRUB_VIDEO_MODE_TYPE_ALPHA 0x00000008
+#define GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED 0x00000004
+#define GRUB_VIDEO_MODE_TYPE_INDEX_COLOR 0x00000002
+#define GRUB_VIDEO_MODE_TYPE_RGB 0x00000001
+
+/* Defines used to mask flags. */
+#define GRUB_VIDEO_MODE_TYPE_COLOR_MASK 0x00000003
+
+/* Defines used to specify requested bit depth. */
+#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)
+
+struct grub_video_mode_info
+{
+ /* Width of the screen. */
+ unsigned int width;
+
+ /* Height of the screen. */
+ unsigned int height;
+
+ /* Mode type bitmask. Contains information like is it Index color or
+ RGB mode. */
+ unsigned int mode_type;
+
+ /* Bits per pixel. */
+ unsigned int bpp;
+
+ /* Bytes per pixel. */
+ unsigned int bytes_per_pixel;
+
+ /* Pitch of one scanline. How many bytes there are for scanline. */
+ unsigned int pitch;
+
+ /* In index color mode, number of colors. In RGB mode this is 256. */
+ unsigned int number_of_colors;
+
+ /* How many bits are reserved for red color. */
+ unsigned int red_mask_size;
+
+ /* What is location of red color bits. In Index Color mode, this is 0. */
+ unsigned int red_field_pos;
+
+ /* How many bits are reserved for green color. */
+ unsigned int green_mask_size;
+
+ /* What is location of green color bits. In Index Color mode, this is 0. */
+ unsigned int green_field_pos;
+
+ /* How many bits are reserved for blue color. */
+ unsigned int blue_mask_size;
+
+ /* What is location of blue color bits. In Index Color mode, this is 0. */
+ unsigned int blue_field_pos;
+
+ /* How many bits are reserved in color. */
+ unsigned int reserved_mask_size;
+
+ /* What is location of reserved color bits. In Index Color mode,
+ this is 0. */
+ unsigned int reserved_field_pos;
+};
+
+struct grub_video_render_target
+{
+ /* Copy of the screen's mode info structure, except that width, height and
+ mode_type has been re-adjusted to requested render target settings. */
+ struct grub_video_mode_info mode_info;
+
+ struct
+ {
+ unsigned int x;
+ unsigned int y;
+ unsigned int width;
+ unsigned int height;
+ } viewport;
+
+ /* Indicates wether the data has been allocated by us and must be freed
+ when render target is destroyed. */
+ int is_allocated;
+
+ /* Pointer to data. Can either be in video card memory or in local host's
+ memory. */
+ void *data;
+};
+
+struct grub_video_palette_data
+{
+ grub_uint8_t r; /* Red color value (0-255). */
+ grub_uint8_t g; /* Green color value (0-255). */
+ grub_uint8_t b; /* Blue color value (0-255). */
+ grub_uint8_t a; /* Reserved bits value (0-255). */
+};
+
+struct grub_font_glyph;
+struct grub_video_bitmap;
+
+struct grub_video_adapter
+{
+ /* The video adapter name. */
+ const char *name;
+
+ /* Initialize the video adapter. */
+ grub_err_t (*init) (void);
+
+ /* Clean up the video adapter. */
+ grub_err_t (*fini) (void);
+
+ grub_err_t (*setup) (unsigned int width,
+ unsigned int height,
+ unsigned int mode_type);
+
+ grub_err_t (*get_info) (struct grub_video_mode_info *mode_info);
+
+ grub_err_t (*set_palette) (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data);
+
+ grub_err_t (*get_palette) (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data);
+
+ grub_err_t (*set_viewport) (unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height);
+
+ grub_err_t (*get_viewport) (unsigned int *x,
+ unsigned int *y,
+ unsigned int *width,
+ unsigned int *height);
+
+ grub_video_color_t (*map_color) (grub_uint32_t color_name);
+
+ grub_video_color_t (*map_rgb) (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue);
+
+ grub_video_color_t (*map_rgba) (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue,
+ grub_uint8_t alpha);
+
+ grub_err_t (*fill_rect) (grub_video_color_t color,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height);
+
+ grub_err_t (*blit_glyph) (struct grub_font_glyph *glyph,
+ grub_video_color_t color,
+ int x,
+ int y);
+
+ grub_err_t (*blit_bitmap) (struct grub_video_bitmap *bitmap,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height);
+
+ grub_err_t (*blit_render_target) (struct grub_video_render_target *source,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height);
+
+ grub_err_t (*scroll) (grub_video_color_t color,
+ int dx,
+ int dy);
+
+ grub_err_t (*swap_buffers) (void);
+
+ grub_err_t (*create_render_target) (struct grub_video_render_target **result,
+ unsigned int width,
+ unsigned int height,
+ unsigned int mode_type);
+
+ grub_err_t (*delete_render_target) (struct grub_video_render_target *target);
+
+ grub_err_t (*set_active_render_target) (struct grub_video_render_target *target);
+
+ /* The next video adapter. */
+ struct grub_video_adapter *next;
+};
+typedef struct grub_video_adapter *grub_video_adapter_t;
+
+void EXPORT_FUNC(grub_video_register) (grub_video_adapter_t adapter);
+void EXPORT_FUNC(grub_video_unregister) (grub_video_adapter_t adapter);
+void EXPORT_FUNC(grub_video_iterate) (int (*hook) (grub_video_adapter_t adapter));
+
+grub_err_t EXPORT_FUNC(grub_video_setup) (unsigned int width,
+ unsigned int height,
+ unsigned int mode_type);
+
+grub_err_t EXPORT_FUNC(grub_video_restore) (void);
+
+grub_err_t EXPORT_FUNC(grub_video_get_info) (struct grub_video_mode_info *mode_info);
+
+grub_err_t EXPORT_FUNC(grub_video_set_palette) (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data);
+
+grub_err_t EXPORT_FUNC(grub_video_get_palette) (unsigned int start,
+ unsigned int count,
+ struct grub_video_palette_data *palette_data);
+
+grub_err_t EXPORT_FUNC(grub_video_set_viewport) (unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_get_viewport) (unsigned int *x,
+ unsigned int *y,
+ unsigned int *width,
+ unsigned int *height);
+
+grub_video_color_t EXPORT_FUNC(grub_video_map_color) (grub_uint32_t color_name);
+
+grub_video_color_t EXPORT_FUNC(grub_video_map_rgb) (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue);
+
+grub_video_color_t EXPORT_FUNC(grub_video_map_rgba) (grub_uint8_t red,
+ grub_uint8_t green,
+ grub_uint8_t blue,
+ grub_uint8_t alpha);
+
+grub_err_t EXPORT_FUNC(grub_video_fill_rect) (grub_video_color_t color,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_blit_glyph) (struct grub_font_glyph *glyph,
+ grub_video_color_t color,
+ int x,
+ int y);
+
+grub_err_t EXPORT_FUNC(grub_video_blit_bitmap) (struct grub_video_bitmap *bitmap,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_blit_render_target) (struct grub_video_render_target *source,
+ int x,
+ int y,
+ int offset_x,
+ int offset_y,
+ unsigned int width,
+ unsigned int height);
+
+grub_err_t EXPORT_FUNC(grub_video_scroll) (grub_video_color_t color,
+ int dx,
+ int dy);
+
+grub_err_t EXPORT_FUNC(grub_video_swap_buffers) (void);
+
+grub_err_t EXPORT_FUNC(grub_video_create_render_target) (struct grub_video_render_target **result,
+ unsigned int width,
+ unsigned int height,
+ unsigned int mode_type);
+
+grub_err_t EXPORT_FUNC(grub_video_delete_render_target) (struct grub_video_render_target *target);
+
+grub_err_t EXPORT_FUNC(grub_video_set_active_render_target) (struct grub_video_render_target *target);
+
+#endif /* ! GRUB_VIDEO_HEADER */
Index: include/grub/i386/pc/vbe.h
===================================================================
RCS file: /sources/grub/grub2/include/grub/i386/pc/vbe.h,v
retrieving revision 1.3
diff -u -r1.3 vbe.h
--- include/grub/i386/pc/vbe.h 16 Aug 2005 18:34:17 -0000 1.3
+++ include/grub/i386/pc/vbe.h 14 Mar 2006 17:00:53 -0000
@@ -27,6 +27,13 @@
/* Default video mode to be used. */
#define GRUB_VBE_DEFAULT_VIDEO_MODE 0x101
+/* VBE status codes. */
+#define GRUB_VBE_STATUS_OK 0x004f
+
+/* VBE memory model types. */
+#define GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL 0x04
+#define GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR 0x06
+
/* Note:
Please refer to VESA BIOS Extension 3.0 Specification for more descriptive
@@ -117,7 +124,7 @@
/* Reserved field to make structure to be 256 bytes long, VESA BIOS
Extension 3.0 Specification says to reserve 189 bytes here but
- that doesn't make structure to be 256 bytes. So additional one is
+ that doesn't make structure to be 256 bytes. So additional one is
added here. */
grub_uint8_t reserved4[189 + 1];
} __attribute__ ((packed));
@@ -147,45 +154,45 @@
/* Prototypes for kernel real mode thunks. */
/* Call VESA BIOS 0x4f00 to get VBE Controller Information, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_controller_info) (struct grub_vbe_info_block *controller_info);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_controller_info) (struct grub_vbe_info_block *controller_info);
/* Call VESA BIOS 0x4f01 to get VBE Mode Information, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_mode_info) (grub_uint32_t mode,
- struct grub_vbe_mode_info_block *mode_info);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_mode_info) (grub_uint32_t mode,
+ struct grub_vbe_mode_info_block *mode_info);
/* Call VESA BIOS 0x4f02 to set video mode, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_mode) (grub_uint32_t mode,
- struct grub_vbe_crtc_info_block *crtc_info);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_mode) (grub_uint32_t mode,
+ struct grub_vbe_crtc_info_block *crtc_info);
/* Call VESA BIOS 0x4f03 to return current VBE Mode, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_mode) (grub_uint32_t *mode);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_mode) (grub_uint32_t *mode);
/* Call VESA BIOS 0x4f05 to set memory window, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_memory_window) (grub_uint32_t window,
- grub_uint32_t position);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_memory_window) (grub_uint32_t window,
+ grub_uint32_t position);
/* Call VESA BIOS 0x4f05 to return memory window, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_memory_window) (grub_uint32_t window,
- grub_uint32_t *position);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_memory_window) (grub_uint32_t window,
+ grub_uint32_t *position);
/* Call VESA BIOS 0x4f06 to set scanline length (in bytes), return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_scanline_length) (grub_uint32_t length);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_scanline_length) (grub_uint32_t length);
/* Call VESA BIOS 0x4f06 to return scanline length (in bytes), return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_scanline_length) (grub_uint32_t *length);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_scanline_length) (grub_uint32_t *length);
/* Call VESA BIOS 0x4f07 to set display start, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_display_start) (grub_uint32_t x,
- grub_uint32_t y);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_display_start) (grub_uint32_t x,
+ grub_uint32_t y);
/* Call VESA BIOS 0x4f07 to get display start, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_get_display_start) (grub_uint32_t *x,
- grub_uint32_t *y);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_display_start) (grub_uint32_t *x,
+ grub_uint32_t *y);
/* Call VESA BIOS 0x4f09 to set palette data, return status. */
-grub_vbe_status_t EXPORT_FUNC(grub_vbe_set_palette_data) (grub_uint32_t color_count,
- grub_uint32_t start_index,
- struct grub_vbe_palette_data *palette_data);
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_palette_data) (grub_uint32_t color_count,
+ grub_uint32_t start_index,
+ struct grub_vbe_palette_data *palette_data);
/* Prototypes for helper functions. */
@@ -195,13 +202,5 @@
grub_err_t grub_vbe_get_video_mode (grub_uint32_t *mode);
grub_err_t grub_vbe_get_video_mode_info (grub_uint32_t mode,
struct grub_vbe_mode_info_block *mode_info);
-void grub_vbe_set_pixel_rgb (grub_uint32_t x,
- grub_uint32_t y,
- grub_uint8_t red,
- grub_uint8_t green,
- grub_uint8_t blue);
-void grub_vbe_set_pixel_index (grub_uint32_t x,
- grub_uint32_t y,
- grub_uint8_t color);
#endif /* ! GRUB_VBE_MACHINE_HEADER */
Index: kern/i386/pc/startup.S
===================================================================
RCS file: /sources/grub/grub2/kern/i386/pc/startup.S,v
retrieving revision 1.19
diff -u -r1.19 startup.S
--- kern/i386/pc/startup.S 15 Oct 2005 17:28:36 -0000 1.19
+++ kern/i386/pc/startup.S 14 Mar 2006 17:00:54 -0000
@@ -1758,14 +1758,15 @@
ret
/*
- * grub_vbe_status_t grub_vbe_get_controller_info (struct grub_vbe_info_block *controller_info)
+ * grub_vbe_bios_status_t grub_vbe_get_controller_info (struct grub_vbe_info_block *controller_info)
*
* Register allocations for parameters:
* %eax *controller_info
*/
-FUNCTION(grub_vbe_get_controller_info)
+FUNCTION(grub_vbe_bios_get_controller_info)
pushl %ebp
pushl %edi
+ pushl %edx
movw %ax, %di /* Store *controller_info to %edx:%di. */
xorw %ax, %ax
@@ -1791,19 +1792,20 @@
movl %edx, %eax
andl $0x0FFFF, %eax /* Return value in %eax. */
+ pop %edx
popl %edi
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_get_mode_info (grub_uint32_t mode,
- * struct grub_vbe_mode_info_block *mode_info)
+ * grub_vbe_status_t grub_vbe_bios_get_mode_info (grub_uint32_t mode,
+ * struct grub_vbe_mode_info_block *mode_info)
*
* Register allocations for parameters:
* %eax mode
* %edx *mode_info
*/
-FUNCTION(grub_vbe_get_mode_info)
+FUNCTION(grub_vbe_bios_get_mode_info)
pushl %ebp
pushl %edi
@@ -1837,16 +1839,17 @@
ret
/*
- * grub_vbe_status_t grub_vbe_set_mode (grub_uint32_t mode,
- * struct grub_vbe_crtc_info_block *crtc_info)
+ * grub_vbe_status_t grub_vbe_bios_set_mode (grub_uint32_t mode,
+ * struct grub_vbe_crtc_info_block *crtc_info)
*
* Register allocations for parameters:
* %eax mode
* %edx *crtc_info
*/
-FUNCTION(grub_vbe_set_mode)
+FUNCTION(grub_vbe_bios_set_mode)
pushl %ebp
pushl %ebx
+ pushl %edi
movl %eax, %ebx /* Store mode in %ebx. */
@@ -1874,19 +1877,22 @@
movw %dx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edi
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_get_mode (grub_uint32_t *mode)
+ * grub_vbe_status_t grub_vbe_bios_get_mode (grub_uint32_t *mode)
*
* Register allocations for parameters:
* %eax *mode
*/
-FUNCTION(grub_vbe_get_mode)
+FUNCTION(grub_vbe_bios_get_mode)
pushl %ebp
pushl %ebx
+ pushl %edi
+ pushl %edx
pushl %eax /* Push *mode to stack. */
call prot_to_real
@@ -1907,19 +1913,21 @@
movw %dx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edx
+ popl %edi
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_set_memory_window (grub_uint32_t window,
- * grub_uint32_t position);
+ * grub_vbe_status_t grub_vbe_bios_set_memory_window (grub_uint32_t window,
+ * grub_uint32_t position);
*
* Register allocations for parameters:
* %eax window
* %edx position
*/
-FUNCTION(grub_vbe_set_memory_window)
+FUNCTION(grub_vbe_bios_set_memory_window)
pushl %ebp
pushl %ebx
@@ -1945,16 +1953,17 @@
ret
/*
- * grub_vbe_status_t grub_vbe_get_memory_window (grub_uint32_t window,
- * grub_uint32_t *position);
+ * grub_vbe_status_t grub_vbe_bios_get_memory_window (grub_uint32_t window,
+ * grub_uint32_t *position);
*
* Register allocations for parameters:
* %eax window
* %edx *position
*/
-FUNCTION(grub_vbe_get_memory_window)
+FUNCTION(grub_vbe_bios_get_memory_window)
pushl %ebp
pushl %ebx
+ pushl %edi
pushl %edx /* Push *position to stack. */
movl %eax, %ebx /* Store window in %ebx. */
@@ -1979,19 +1988,21 @@
movw %bx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edi
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_set_scanline_length (grub_uint32_t length)
+ * grub_vbe_status_t grub_vbe_bios_set_scanline_length (grub_uint32_t length)
*
* Register allocations for parameters:
* %eax length
*/
-FUNCTION(grub_vbe_set_scanline_length)
+FUNCTION(grub_vbe_bios_set_scanline_length)
pushl %ebp
pushl %ebx
+ pushl %edx
movl %eax, %ecx /* Store length in %ecx. */
@@ -2010,19 +2021,21 @@
movw %dx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edx
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_get_scanline_length (grub_uint32_t *length)
+ * grub_vbe_status_t grub_vbe_bios_get_scanline_length (grub_uint32_t *length)
*
* Register allocations for parameters:
* %eax *length
*/
-FUNCTION(grub_vbe_get_scanline_length)
+FUNCTION(grub_vbe_bios_get_scanline_length)
pushl %ebp
pushl %ebx
+ pushl %edi
pushl %edx /* Push *length to stack. */
call prot_to_real
@@ -2044,19 +2057,20 @@
movw %dx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edi
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_set_display_start (grub_uint32_t x,
- * grub_uint32_t y)
+ * grub_vbe_status_t grub_vbe_bios_set_display_start (grub_uint32_t x,
+ * grub_uint32_t y)
*
* Register allocations for parameters:
* %eax x
* %edx y
*/
-FUNCTION(grub_vbe_set_display_start)
+FUNCTION(grub_vbe_bios_set_display_start)
pushl %ebp
pushl %ebx
@@ -2083,16 +2097,17 @@
ret
/*
- * grub_vbe_status_t grub_vbe_get_display_start (grub_uint32_t *x,
- * grub_uint32_t *y)
+ * grub_vbe_status_t grub_vbe_bios_get_display_start (grub_uint32_t *x,
+ * grub_uint32_t *y)
*
* Register allocations for parameters:
* %eax *x
* %edx *y
*/
-FUNCTION(grub_vbe_get_display_start)
+FUNCTION(grub_vbe_bios_get_display_start)
pushl %ebp
pushl %ebx
+ pushl %edi
pushl %eax /* Push *x to stack. */
pushl %edx /* Push *y to stack. */
@@ -2119,23 +2134,25 @@
movw %bx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edi
popl %ebx
popl %ebp
ret
/*
- * grub_vbe_status_t grub_vbe_set_palette_data (grub_uint32_t color_count,
- * grub_uint32_t start_index,
- * struct grub_vbe_palette_data *palette_data)
+ * grub_vbe_status_t grub_vbe_bios_set_palette_data (grub_uint32_t color_count,
+ * grub_uint32_t start_index,
+ * struct grub_vbe_palette_data *palette_data)
*
* Register allocations for parameters:
* %eax color_count
* %edx start_index
* %ecx *palette_data
*/
-FUNCTION(grub_vbe_set_palette_data)
+FUNCTION(grub_vbe_bios_set_palette_data)
pushl %ebp
pushl %ebx
+ pushl %edi
movl %eax, %ebx /* Store color_count in %ebx. */
@@ -2165,6 +2182,7 @@
movw %dx, %ax
andl $0xFFFF, %eax /* Return value in %eax. */
+ popl %edi
popl %ebx
popl %ebp
ret
Index: normal/cmdline.c
===================================================================
RCS file: /sources/grub/grub2/normal/cmdline.c,v
retrieving revision 1.19
diff -u -r1.19 cmdline.c
--- normal/cmdline.c 28 Aug 2005 17:01:16 -0000 1.19
+++ normal/cmdline.c 14 Mar 2006 17:00:54 -0000
@@ -231,6 +231,8 @@
xpos = (plen + lpos) % 79;
ypos = ystart + (plen + lpos) / 79;
grub_gotoxy (xpos, ypos);
+
+ grub_refresh ();
}
void cl_print (int pos, int c)
@@ -271,6 +273,8 @@
cl_print (lpos - len, echo_char);
cl_set_pos ();
}
+
+ grub_refresh ();
}
void cl_delete (unsigned len)
@@ -290,6 +294,8 @@
cl_print (lpos, echo_char);
cl_set_pos ();
}
+
+ grub_refresh ();
}
plen = grub_strlen (prompt);
Index: term/gfxterm.c
===================================================================
RCS file: term/gfxterm.c
diff -N term/gfxterm.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ term/gfxterm.c 14 Mar 2006 17:00:54 -0000
@@ -0,0 +1,794 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/machine/memory.h>
+#include <grub/machine/console.h>
+#include <grub/term.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/font.h>
+#include <grub/arg.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+#include <grub/video.h>
+
+#define DEFAULT_VIDEO_WIDTH 640
+#define DEFAULT_VIDEO_HEIGHT 480
+#define DEFAULT_VIDEO_FLAGS 0
+
+#define DEFAULT_CHAR_WIDTH 8
+#define DEFAULT_CHAR_HEIGHT 16
+
+#define DEFAULT_BORDER_WIDTH 10
+
+#define DEFAULT_FG_COLOR 0x0a
+#define DEFAULT_BG_COLOR 0x00
+#define DEFAULT_CURSOR_COLOR 0x0f
+
+struct grub_dirty_region
+{
+ int top_left_x;
+ int top_left_y;
+ int bottom_right_x;
+ int bottom_right_y;
+};
+
+struct grub_colored_char
+{
+ /* An Unicode codepoint. */
+ grub_uint32_t code;
+
+ /* Color values. */
+ grub_video_color_t fg_color;
+ grub_video_color_t bg_color;
+
+ /* The width of this character minus one. */
+ unsigned char width;
+
+ /* The column index of this character. */
+ unsigned char index;
+};
+
+struct grub_virtual_screen
+{
+ /* Dimensions of the virtual screen. */
+ unsigned int width;
+ unsigned int height;
+
+ /* Offset in the display. */
+ unsigned int offset_x;
+ unsigned int offset_y;
+
+ /* TTY Character sizes. */
+ unsigned int char_width;
+ unsigned int char_height;
+
+ /* Virtual screen TTY size. */
+ unsigned int columns;
+ unsigned int rows;
+
+ /* Current cursor details. */
+ unsigned int cursor_x;
+ unsigned int cursor_y;
+ int cursor_state;
+
+ /* Color settings. */
+ grub_video_color_t fg_color_setting;
+ grub_video_color_t bg_color_setting;
+ grub_video_color_t fg_color;
+ grub_video_color_t bg_color;
+ grub_video_color_t cursor_color;
+
+ /* Text buffer for virtual screen. Contains (columns * rows) number
+ of entries. */
+ struct grub_colored_char *text_buffer;
+};
+
+static struct grub_virtual_screen virtual_screen;
+
+static grub_dl_t my_mod;
+static struct grub_video_mode_info mode_info;
+
+static struct grub_video_render_target *text_layer;
+
+static struct grub_dirty_region dirty_region;
+
+static void dirty_region_reset (void);
+
+static int dirty_region_is_empty (void);
+
+static void dirty_region_add (int x, int y,
+ unsigned int width, unsigned int height);
+
+static void
+grub_virtual_screen_free (void)
+{
+ /* If virtual screen has been allocated, free it. */
+ if (virtual_screen.text_buffer != 0)
+ grub_free (virtual_screen.text_buffer);
+
+ /* Reset virtual screen data. */
+ grub_memset (&virtual_screen, 0, sizeof (virtual_screen));
+
+ /* Free render targets. */
+ grub_video_delete_render_target (text_layer);
+ text_layer = 0;
+}
+
+static grub_err_t
+grub_virtual_screen_setup (unsigned int x, unsigned int y,
+ unsigned int width, unsigned int height)
+{
+ /* Free old virtual screen. */
+ grub_virtual_screen_free ();
+
+ /* Initialize with default data. */
+ virtual_screen.width = width;
+ virtual_screen.height = height;
+ virtual_screen.offset_x = x;
+ virtual_screen.offset_y = y;
+ virtual_screen.char_width = DEFAULT_CHAR_WIDTH;
+ virtual_screen.char_height = DEFAULT_CHAR_HEIGHT;
+ virtual_screen.cursor_x = 0;
+ virtual_screen.cursor_y = 0;
+ virtual_screen.cursor_state = 1;
+
+ /* Calculate size of text buffer. */
+ virtual_screen.columns = virtual_screen.width / virtual_screen.char_width;
+ virtual_screen.rows = virtual_screen.height / virtual_screen.char_height;
+
+ /* Allocate memory for text buffer. */
+ virtual_screen.text_buffer =
+ (struct grub_colored_char *) grub_malloc (virtual_screen.columns
+ * virtual_screen.rows
+ * sizeof (*virtual_screen.text_buffer));
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Create new render target for text layer. */
+ grub_video_create_render_target (&text_layer,
+ virtual_screen.width,
+ virtual_screen.height,
+ GRUB_VIDEO_MODE_TYPE_RGB
+ | 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. */
+ grub_video_set_active_render_target (text_layer);
+
+ virtual_screen.fg_color_setting = grub_video_map_color (DEFAULT_FG_COLOR);
+ virtual_screen.bg_color_setting = grub_video_map_color (DEFAULT_BG_COLOR);
+ virtual_screen.fg_color = virtual_screen.fg_color_setting;
+ virtual_screen.bg_color = virtual_screen.bg_color_setting;
+ virtual_screen.cursor_color = grub_video_map_color (DEFAULT_CURSOR_COLOR);
+
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ return grub_errno;
+}
+
+static grub_err_t
+grub_gfxterm_init (void)
+{
+ char *modevar;
+ int width = DEFAULT_VIDEO_WIDTH;
+ int height = DEFAULT_VIDEO_HEIGHT;
+ 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)
+ {
+ char *tmp;
+ char *param;
+ char *value;
+
+ /* Take copy of env.var. as we don't want to modify that. */
+ tmp = grub_strdup (modevar);
+ modevar = tmp;
+
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Skip whitespace. */
+ while (grub_isspace (*tmp))
+ tmp++;
+
+ /* Initialize token holders. */
+ param = tmp;
+ value = NULL;
+
+ /* Parse <width>x<height>[x<depth>]*/
+
+ /* Find width value. */
+ value = param;
+ param = grub_strchr(param, 'x');
+ if (param == NULL)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "Invalid argument: %s\n",
+ param);
+ }
+
+ *param = 0;
+ param++;
+
+ width = grub_strtoul (value, 0, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "Invalid argument: %s\n",
+ param);
+ }
+
+ /* Find height value. */
+ value = param;
+ param = grub_strchr(param, 'x');
+ if (param == NULL)
+ {
+ height = grub_strtoul (value, 0, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "Invalid argument: %s\n",
+ param);
+ }
+ }
+ else
+ {
+ /* We have optional color depth value. */
+ *param = 0;
+ param++;
+
+ height = grub_strtoul (value, 0, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "Invalid argument: %s\n",
+ param);
+ }
+
+ /* Convert color depth value. */
+ value = param;
+ depth = grub_strtoul (value, 0, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free memory before returning. */
+ grub_free (modevar);
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "Invalid argument: %s\n",
+ param);
+ }
+ }
+
+ /* Free memory. */
+ grub_free (modevar);
+ }
+
+ /* If we have 8 or less bits, then assuem that it is indexed color mode. */
+ if ((depth <= 8) && (depth != -1))
+ flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+
+ /* We have more than 8 bits, then assume that it is RGB color mode. */
+ if (depth > 8)
+ flags |= GRUB_VIDEO_MODE_TYPE_RGB;
+
+ /* If user requested specific depth, forward that information to driver. */
+ if (depth != -1)
+ flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
+ & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
+
+ /* Initialize user requested mode. */
+ if (grub_video_setup (width, height, flags) != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Figure out what mode we ended up. */
+ if (grub_video_get_info (&mode_info) != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Make sure screen is black. */
+ color = grub_video_map_rgb (0, 0, 0);
+ grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
+
+ /* Leave borders for virtual screen. */
+ width = mode_info.width - (2 * 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)
+ {
+ grub_video_restore ();
+ return grub_errno;
+ }
+
+ /* Mark whole screen as dirty. */
+ dirty_region_reset ();
+ dirty_region_add (0, 0, mode_info.width, mode_info.height);
+
+ return (grub_errno = GRUB_ERR_NONE);
+}
+
+static grub_err_t
+grub_gfxterm_fini (void)
+{
+ grub_virtual_screen_free ();
+
+ grub_video_restore ();
+
+ return GRUB_ERR_NONE;
+}
+
+static void
+redraw_screen_rect (unsigned int x, unsigned int y,
+ unsigned int width, unsigned int height)
+{
+ grub_video_color_t color;
+
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ /* Render background layer. */
+ color = virtual_screen.bg_color;
+ grub_video_fill_rect (color, x, y, width, height);
+
+ /* Render text layer. */
+ grub_video_blit_render_target (text_layer, x, y,
+ x - virtual_screen.offset_x,
+ y - virtual_screen.offset_y,
+ width, height);
+}
+
+static void
+dirty_region_reset (void)
+{
+ dirty_region.top_left_x = -1;
+ dirty_region.top_left_y = -1;
+ dirty_region.bottom_right_x = -1;
+ dirty_region.bottom_right_y = -1;
+}
+
+static int
+dirty_region_is_empty (void)
+{
+ if ((dirty_region.top_left_x == -1)
+ || (dirty_region.top_left_y == -1)
+ || (dirty_region.bottom_right_x == -1)
+ || (dirty_region.bottom_right_y == -1))
+ return 1;
+ return 0;
+}
+
+static void
+dirty_region_add (int x, int y, unsigned int width, unsigned int height)
+{
+ if ((width == 0) || (height == 0))
+ return;
+
+ if (dirty_region_is_empty ())
+ {
+ dirty_region.top_left_x = x;
+ dirty_region.top_left_y = y;
+ dirty_region.bottom_right_x = x + width - 1;
+ dirty_region.bottom_right_y = y + height - 1;
+ }
+ else
+ {
+ if (x < dirty_region.top_left_x)
+ dirty_region.top_left_x = x;
+ if (y < dirty_region.top_left_y)
+ dirty_region.top_left_y = y;
+ if ((x + (int)width - 1) > dirty_region.bottom_right_x)
+ dirty_region.bottom_right_x = x + width - 1;
+ if ((y + (int)height - 1) > dirty_region.bottom_right_y)
+ dirty_region.bottom_right_y = y + height - 1;
+ }
+}
+
+static void
+dirty_region_add_virtualscreen (void)
+{
+ /* Mark virtual screen as dirty. */
+ dirty_region_add (virtual_screen.offset_x, virtual_screen.offset_y,
+ virtual_screen.width, virtual_screen.height);
+}
+
+
+static void
+dirty_region_redraw (void)
+{
+ int x;
+ int y;
+ int width;
+ int height;
+
+ if (dirty_region_is_empty ())
+ return;
+
+ x = dirty_region.top_left_x;
+ y = dirty_region.top_left_y;
+
+ width = dirty_region.bottom_right_x - x + 1;
+ height = dirty_region.bottom_right_y - y + 1;
+
+ redraw_screen_rect (x, y, width, height);
+
+ dirty_region_reset ();
+}
+
+static void
+write_char (void)
+{
+ struct grub_colored_char *p;
+ struct grub_font_glyph glyph;
+ grub_video_color_t color;
+ grub_video_color_t bgcolor;
+ unsigned int x;
+ unsigned int y;
+
+ /* Find out active character. */
+ p = (virtual_screen.text_buffer
+ + virtual_screen.cursor_x
+ + (virtual_screen.cursor_y * virtual_screen.columns));
+
+ p -= p->index;
+
+ /* Get glyph for character. */
+ grub_font_get_glyph (p->code, &glyph);
+
+ color = p->fg_color;
+ bgcolor = p->bg_color;
+
+ x = virtual_screen.cursor_x * virtual_screen.char_width;
+ y = virtual_screen.cursor_y * virtual_screen.char_height;
+
+ /* Render glyph to text layer. */
+ grub_video_set_active_render_target (text_layer);
+ grub_video_fill_rect (bgcolor, x, y, glyph.width, glyph.height);
+ grub_video_blit_glyph (&glyph, color, x, y);
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ /* Mark character to be drawn. */
+ dirty_region_add (virtual_screen.offset_x + x, virtual_screen.offset_y + y,
+ glyph.width, glyph.height);
+}
+
+static void
+write_cursor (void)
+{
+ unsigned int x;
+ unsigned int y;
+ unsigned int width;
+ unsigned int height;
+ grub_video_color_t color;
+
+ /* Determine cursor properties and position on text layer. */
+ x = virtual_screen.cursor_x * virtual_screen.char_width;
+ y = ((virtual_screen.cursor_y + 1) * virtual_screen.char_height) - 3;
+ width = virtual_screen.char_width;
+ height = 2;
+
+ color = virtual_screen.cursor_color;
+
+ /* Render cursor to text layer. */
+ grub_video_set_active_render_target (text_layer);
+ grub_video_fill_rect (color, x, y, width, height);
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ /* Mark cursor to be redrawn. */
+ dirty_region_add (virtual_screen.offset_x + x, virtual_screen.offset_y + y,
+ width, height);
+}
+
+static void
+scroll_up (void)
+{
+ unsigned int i;
+ grub_video_color_t color;
+
+ /* Scroll text buffer with one line to up. */
+ grub_memmove (virtual_screen.text_buffer,
+ virtual_screen.text_buffer + virtual_screen.columns,
+ sizeof (*virtual_screen.text_buffer)
+ * virtual_screen.columns
+ * (virtual_screen.rows - 1));
+
+ /* Clear last line in text buffer. */
+ for (i = virtual_screen.columns * (virtual_screen.rows - 1);
+ i < virtual_screen.columns * virtual_screen.rows;
+ i++)
+ {
+ virtual_screen.text_buffer[i].code = ' ';
+ virtual_screen.text_buffer[i].fg_color = virtual_screen.fg_color;
+ virtual_screen.text_buffer[i].bg_color = virtual_screen.bg_color;
+ virtual_screen.text_buffer[i].width = 0;
+ virtual_screen.text_buffer[i].index = 0;
+ }
+
+ /* Scroll physical screen. */
+ grub_video_set_active_render_target (text_layer);
+ color = virtual_screen.bg_color;
+ grub_video_scroll (color, 0, -virtual_screen.char_height);
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ /* Mark virtual screen to be redrawn. */
+ dirty_region_add_virtualscreen ();
+}
+
+static void
+grub_gfxterm_putchar (grub_uint32_t c)
+{
+ if (c == '\a')
+ /* FIXME */
+ return;
+
+ if (c == '\b' || c == '\n' || c == '\r')
+ {
+ /* Erase current cursor, if any. */
+ if (virtual_screen.cursor_state)
+ write_char ();
+
+ switch (c)
+ {
+ case '\b':
+ if (virtual_screen.cursor_x > 0)
+ virtual_screen.cursor_x--;
+ break;
+
+ case '\n':
+ if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
+ scroll_up ();
+ else
+ virtual_screen.cursor_y++;
+ break;
+
+ case '\r':
+ virtual_screen.cursor_x = 0;
+ break;
+ }
+
+ /* Redraw cursor if visible. */
+ if (virtual_screen.cursor_state)
+ write_cursor ();
+ }
+ else
+ {
+ struct grub_font_glyph glyph;
+ struct grub_colored_char *p;
+
+ /* Get properties of the character. */
+ grub_font_get_glyph (c, &glyph);
+
+ /* If we are about to exceed line length, wrap to next line. */
+ if (virtual_screen.cursor_x + glyph.char_width > virtual_screen.columns)
+ grub_putchar ('\n');
+
+ /* Find position on virtual screen, and fill information. */
+ p = (virtual_screen.text_buffer +
+ virtual_screen.cursor_x +
+ virtual_screen.cursor_y * virtual_screen.columns);
+ p->code = c;
+ p->fg_color = virtual_screen.fg_color;
+ p->bg_color = virtual_screen.bg_color;
+ p->width = glyph.char_width - 1;
+ p->index = 0;
+
+ /* If we have large glyph, add fixup info. */
+ if (glyph.char_width > 1)
+ {
+ unsigned i;
+
+ for (i = 1; i < glyph.char_width; i++)
+ {
+ p[i].code = ' ';
+ p[i].width = glyph.char_width - 1;
+ p[i].index = i;
+ }
+ }
+
+ /* Draw glyph. */
+ write_char ();
+
+ /* Make sure we scroll screen when needed and wrap line correctly. */
+ virtual_screen.cursor_x += glyph.char_width;
+ if (virtual_screen.cursor_x >= virtual_screen.columns)
+ {
+ virtual_screen.cursor_x = 0;
+
+ if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
+ scroll_up ();
+ else
+ virtual_screen.cursor_y++;
+ }
+
+ /* Draw cursor if visible. */
+ if (virtual_screen.cursor_state)
+ write_cursor ();
+ }
+}
+
+static grub_ssize_t
+grub_gfxterm_getcharwidth (grub_uint32_t c)
+{
+ struct grub_font_glyph glyph;
+
+ if (! grub_font_get_glyph (c, &glyph))
+ return 0;
+
+ return glyph.char_width;
+}
+
+static grub_uint16_t
+grub_virtual_screen_getwh (void)
+{
+ return (virtual_screen.columns << 8) | virtual_screen.rows;
+}
+
+static grub_uint16_t
+grub_virtual_screen_getxy (void)
+{
+ return ((virtual_screen.cursor_x << 8) | virtual_screen.cursor_y);
+}
+
+static void
+grub_gfxterm_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+ if (x >= virtual_screen.columns)
+ x = virtual_screen.columns - 1;
+
+ if (y >= virtual_screen.rows)
+ y = virtual_screen.rows - 1;
+
+ if (virtual_screen.cursor_state)
+ write_char ();
+
+ virtual_screen.cursor_x = x;
+ virtual_screen.cursor_y = y;
+
+ if (virtual_screen.cursor_state)
+ write_cursor ();
+}
+
+static void
+grub_virtual_screen_cls (void)
+{
+ grub_uint32_t i;
+
+ for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++)
+ {
+ virtual_screen.text_buffer[i].code = ' ';
+ virtual_screen.text_buffer[i].fg_color = virtual_screen.fg_color;
+ virtual_screen.text_buffer[i].bg_color = virtual_screen.bg_color;
+ virtual_screen.text_buffer[i].width = 0;
+ virtual_screen.text_buffer[i].index = 0;
+ }
+
+ virtual_screen.cursor_x = virtual_screen.cursor_y = 0;
+}
+
+static void
+grub_gfxterm_cls (void)
+{
+ grub_video_color_t color;
+
+ /* Clear virtual screen. */
+ grub_virtual_screen_cls ();
+
+ /* Clear text layer. */
+ grub_video_set_active_render_target (text_layer);
+ color = virtual_screen.bg_color_setting;
+ grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
+ grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+ /* Mark virtual screen to be redrawn. */
+ dirty_region_add_virtualscreen ();
+}
+
+static void
+grub_virtual_screen_setcolorstate (grub_term_color_state state)
+{
+ switch (state)
+ {
+ case GRUB_TERM_COLOR_STANDARD:
+ case GRUB_TERM_COLOR_NORMAL:
+ virtual_screen.fg_color = virtual_screen.fg_color_setting;
+ virtual_screen.bg_color = virtual_screen.bg_color_setting;
+ break;
+ case GRUB_TERM_COLOR_HIGHLIGHT:
+ virtual_screen.fg_color = virtual_screen.bg_color_setting;
+ virtual_screen.bg_color = virtual_screen.fg_color_setting;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+grub_virtual_screen_setcolor (grub_uint8_t normal_color,
+ grub_uint8_t highlight_color)
+{
+ virtual_screen.fg_color_setting = grub_video_map_color (normal_color);
+ virtual_screen.bg_color_setting = grub_video_map_color (highlight_color);
+}
+
+static void
+grub_gfxterm_setcursor (int on)
+{
+ if (virtual_screen.cursor_state != on)
+ {
+ if (virtual_screen.cursor_state)
+ write_char ();
+ else
+ write_cursor ();
+
+ virtual_screen.cursor_state = on;
+ }
+}
+
+static void
+grub_gfxterm_refresh (void)
+{
+ /* Redraw only changed regions. */
+ dirty_region_redraw ();
+}
+
+static struct grub_term grub_video_term =
+ {
+ .name = "gfxterm",
+ .init = grub_gfxterm_init,
+ .fini = grub_gfxterm_fini,
+ .putchar = grub_gfxterm_putchar,
+ .getcharwidth = grub_gfxterm_getcharwidth,
+ .checkkey = grub_console_checkkey,
+ .getkey = grub_console_getkey,
+ .getwh = grub_virtual_screen_getwh,
+ .getxy = grub_virtual_screen_getxy,
+ .gotoxy = grub_gfxterm_gotoxy,
+ .cls = grub_gfxterm_cls,
+ .setcolorstate = grub_virtual_screen_setcolorstate,
+ .setcolor = grub_virtual_screen_setcolor,
+ .setcursor = grub_gfxterm_setcursor,
+ .refresh = grub_gfxterm_refresh,
+ .flags = 0,
+ .next = 0
+ };
+
+GRUB_MOD_INIT(term_gfxterm)
+{
+ my_mod = mod;
+ grub_term_register (&grub_video_term);
+}
+
+GRUB_MOD_FINI(term_gfxterm)
+{
+ grub_term_unregister (&grub_video_term);
+}
Index: video/video.c
===================================================================
RCS file: video/video.c
diff -N video/video.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ video/video.c 14 Mar 2006 17:00:55 -0000
@@ -0,0 +1,306 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/video.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+
+/* The list of video adapters registerd to system. */
+static grub_video_adapter_t grub_video_adapter_list;
+
+/* Active video adapter. */
+static grub_video_adapter_t grub_video_adapter_active;
+
+void
+grub_video_register (grub_video_adapter_t adapter)
+{
+ adapter->next = grub_video_adapter_list;
+ grub_video_adapter_list = adapter;
+}
+
+void
+grub_video_unregister (grub_video_adapter_t adapter)
+{
+ grub_video_adapter_t *p, q;
+
+ for (p = &grub_video_adapter_list, q = *p; q; p = &(q->next), q = q->next)
+ if (q == adapter)
+ {
+ *p = q->next;
+ break;
+ }
+}
+
+void
+grub_video_iterate (int (*hook) (grub_video_adapter_t adapter))
+{
+ grub_video_adapter_t p;
+
+ for (p = grub_video_adapter_list; p; p = p->next)
+ if (hook (p))
+ break;
+}
+
+grub_err_t
+grub_video_setup (unsigned int width, unsigned int height,
+ unsigned int mode_type)
+{
+ grub_video_adapter_t p;
+
+ /* De-activate last set video adapter. */
+ if (grub_video_adapter_active)
+ {
+ /* Finalize adapter. */
+ grub_video_adapter_active->fini ();
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Mark active adapter as not set. */
+ grub_video_adapter_active = 0;
+ }
+
+ /* Loop thru all possible video adapter trying to find requested mode. */
+ for (p = grub_video_adapter_list; p; p = p->next)
+ {
+ /* Try to initialize adapter, if can't skip to next. */
+ p->init ();
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+
+ /* Try to initialize video mode. */
+ p->setup (width, height, mode_type);
+ if (grub_errno == GRUB_ERR_NONE)
+ {
+ /* Valid mode found from adapter, and it has been activated.
+ Specify it as active adapter. */
+ grub_video_adapter_active = p;
+ return GRUB_ERR_NONE;
+ }
+ else
+ grub_errno = GRUB_ERR_NONE;
+
+ /* No valid mode found in this adapter, finalize adapter. */
+ p->fini ();
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+ }
+
+ /* We couldn't find suitable adapter for specified mode. */
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+ "Can't locate valid adapter for mode");
+}
+
+grub_err_t
+grub_video_restore (void)
+{
+ if (grub_video_adapter_active)
+ {
+ grub_video_adapter_active->fini ();
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ grub_video_adapter_active = 0;
+ }
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_video_get_info (struct grub_video_mode_info *mode_info)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ return grub_video_adapter_active->get_info (mode_info);
+}
+
+grub_err_t
+grub_video_set_palette (unsigned int start, unsigned int count,
+ struct grub_video_palette_data *palette_data)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ return grub_video_adapter_active->set_palette (start, count, palette_data);
+}
+
+grub_err_t
+grub_video_get_palette (unsigned int start, unsigned int count,
+ struct grub_video_palette_data *palette_data)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ return grub_video_adapter_active->get_palette (start, count, palette_data);
+}
+
+grub_err_t
+grub_video_set_viewport (unsigned int x, unsigned int y,
+ unsigned int width, unsigned int height)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ return grub_video_adapter_active->set_viewport (x, y, width, height);
+}
+
+grub_err_t
+grub_video_get_viewport (unsigned int *x, unsigned int *y,
+ unsigned int *width, unsigned int *height)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ return grub_video_adapter_active->get_viewport (x, y, width, height);
+}
+
+grub_video_color_t
+grub_video_map_color (grub_uint32_t color_name)
+{
+ if (! grub_video_adapter_active)
+ return 0;
+
+ return grub_video_adapter_active->map_color (color_name);
+}
+
+grub_video_color_t
+grub_video_map_rgb (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue)
+{
+ if (! grub_video_adapter_active)
+ return 0;
+
+ return grub_video_adapter_active->map_rgb (red, green, blue);
+}
+
+grub_video_color_t
+grub_video_map_rgba (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue,
+ grub_uint8_t alpha)
+{
+ if (! grub_video_adapter_active)
+ return 0;
+
+ return grub_video_adapter_active->map_rgba (red, green, blue, alpha);
+}
+
+grub_err_t
+grub_video_fill_rect (grub_video_color_t color, int x, int y,
+ unsigned int width, unsigned int height)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ return grub_video_adapter_active->fill_rect (color, x, y, width, height);
+}
+
+grub_err_t
+grub_video_blit_glyph (struct grub_font_glyph *glyph,
+ grub_video_color_t color, int x, int y)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ return grub_video_adapter_active->blit_glyph (glyph, color, x, y);
+}
+
+grub_err_t
+grub_video_blit_bitmap (struct grub_video_bitmap *bitmap,
+ int x, int y, int offset_x, int offset_y,
+ unsigned int width, unsigned int height)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ return grub_video_adapter_active->blit_bitmap (bitmap, x, y,
+ offset_x, offset_y,
+ width, height);
+}
+
+grub_err_t
+grub_video_blit_render_target (struct grub_video_render_target *target,
+ int x, int y, int offset_x, int offset_y,
+ unsigned int width, unsigned int height)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ return grub_video_adapter_active->blit_render_target (target, x, y,
+ offset_x, offset_y,
+ width, height);
+}
+
+grub_err_t
+grub_video_scroll (grub_video_color_t color, int dx, int dy)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ return grub_video_adapter_active->scroll (color, dx, dy);
+}
+
+grub_err_t
+grub_video_swap_buffers (void)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ return grub_video_adapter_active->swap_buffers ();
+}
+
+grub_err_t
+grub_video_create_render_target (struct grub_video_render_target **result,
+ unsigned int width, unsigned int height,
+ unsigned int mode_type)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ return grub_video_adapter_active->create_render_target (result,
+ width, height,
+ mode_type);
+}
+
+grub_err_t
+grub_video_delete_render_target (struct grub_video_render_target *target)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ return grub_video_adapter_active->delete_render_target (target);
+}
+
+grub_err_t
+grub_video_set_active_render_target (struct grub_video_render_target *target)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ return grub_video_adapter_active->set_active_render_target (target);
+}
+
+GRUB_MOD_INIT(video_video)
+{
+ grub_video_adapter_active = 0;
+ grub_video_adapter_list = 0;
+}
+
+GRUB_MOD_FINI(video_video)
+{
+}
Index: video/i386/pc/vbe.c
===================================================================
RCS file: /sources/grub/grub2/video/i386/pc/vbe.c,v
retrieving revision 1.4
diff -u -r1.4 vbe.c
--- video/i386/pc/vbe.c 18 Sep 2005 21:04:41 -0000 1.4
+++ video/i386/pc/vbe.c 14 Mar 2006 17:00:55 -0000
@@ -1,6 +1,6 @@
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2005 Free Software Foundation, Inc.
+ * Copyright (C) 2005,2006 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,18 +19,13 @@
#include <grub/err.h>
#include <grub/machine/memory.h>
-#include <grub/machine/vga.h>
#include <grub/machine/vbe.h>
-#include <grub/machine/console.h>
-#include <grub/term.h>
#include <grub/types.h>
#include <grub/dl.h>
#include <grub/misc.h>
-#include <grub/normal.h>
#include <grub/font.h>
-#include <grub/arg.h>
#include <grub/mm.h>
-#include <grub/env.h>
+#include <grub/video.h>
/* Specify "standard" VGA palette, some video cards may
need this and this will also be used when using RGB modes. */
@@ -57,15 +52,47 @@
};
static int vbe_detected = -1;
-static int index_color_mode = 0;
static struct grub_vbe_info_block controller_info;
static struct grub_vbe_mode_info_block active_mode_info;
-static grub_uint32_t active_mode = 0;
+static struct
+{
+ struct grub_video_render_target render_target;
+
+ unsigned int bytes_per_scan_line;
+ unsigned int bytes_per_pixel;
+ grub_uint32_t active_mode;
+ grub_uint8_t *ptr;
+ int index_color_mode;
+ struct grub_video_palette_data palette[256];
+} framebuffer;
+
+static struct grub_video_render_target *render_target;
+static grub_uint32_t initial_mode;
+static grub_uint32_t mode_in_use = 0x55aa;
+static grub_uint16_t *mode_list;
+
+static grub_video_color_t
+grub_video_vbe_map_rgb (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue);
+
+static grub_video_color_t
+grub_video_vbe_map_rgba (grub_uint8_t red, grub_uint8_t green,
+ grub_uint8_t blue, grub_uint8_t alpha);
+
+static void
+grub_video_vbe_unmap_color (struct grub_video_render_target * source,
+ grub_video_color_t color,
+ grub_uint8_t *red, grub_uint8_t *green,
+ grub_uint8_t *blue, grub_uint8_t *alpha);
+
-static grub_uint8_t *framebuffer = 0;
-static grub_uint32_t bytes_per_scan_line = 0;
+static void *
+real2pm (grub_vbe_farptr_t ptr)
+{
+ return (void *) ((((unsigned long) ptr & 0xFFFF0000) >> 12UL)
+ + ((unsigned long) ptr & 0x0000FFFF));
+}
grub_err_t
grub_vbe_probe (struct grub_vbe_info_block *info_block)
@@ -99,7 +126,7 @@
vbe_ib->signature[3] = '2';
/* Try to get controller info block. */
- status = grub_vbe_get_controller_info (vbe_ib);
+ status = grub_vbe_bios_get_controller_info (vbe_ib);
if (status == 0x004F)
{
/* Copy it for later usage. */
@@ -128,11 +155,13 @@
grub_uint32_t old_mode;
/* Make sure that VBE is supported. */
- if (grub_vbe_probe (0) != GRUB_ERR_NONE)
+ grub_vbe_probe (0);
+ if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* Try to get mode info. */
- if (grub_vbe_get_video_mode_info (mode, &active_mode_info) != GRUB_ERR_NONE)
+ grub_vbe_get_video_mode_info (mode, &active_mode_info);
+ if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* For all VESA BIOS modes, force linear frame buffer. */
@@ -144,12 +173,12 @@
/* Determine frame buffer pixel format. */
switch (active_mode_info.memory_model)
{
- case 0x04:
- index_color_mode = 1;
+ case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL:
+ framebuffer.index_color_mode = 1;
break;
- case 0x06:
- index_color_mode = 0;
+ case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR:
+ framebuffer.index_color_mode = 0;
break;
default:
@@ -160,51 +189,68 @@
}
/* Get current mode. */
- if (grub_vbe_get_video_mode (&old_mode) != GRUB_ERR_NONE)
+ grub_vbe_get_video_mode (&old_mode);
+ if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* Try to set video mode. */
- status = grub_vbe_set_mode (mode, 0);
- if (status != 0x004F)
+ status = grub_vbe_bios_set_mode (mode, 0);
+ if (status != GRUB_VBE_STATUS_OK)
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot set VBE mode %x", mode);
/* Save information for later usage. */
- active_mode = mode;
+ framebuffer.active_mode = mode;
if (mode < 0x100)
{
/* If this is not a VESA mode, guess address. */
- framebuffer = (grub_uint8_t *) 0xA0000;
- index_color_mode = 1;
+ framebuffer.ptr = (grub_uint8_t *) 0xA0000;
+ framebuffer.index_color_mode = 1;
}
else
{
- framebuffer = (grub_uint8_t *) active_mode_info.phys_base_addr;
+ framebuffer.ptr = (grub_uint8_t *) active_mode_info.phys_base_addr;
if (controller_info.version >= 0x300)
- bytes_per_scan_line = active_mode_info.lin_bytes_per_scan_line;
+ framebuffer.bytes_per_scan_line = active_mode_info.lin_bytes_per_scan_line;
else
- bytes_per_scan_line = active_mode_info.bytes_per_scan_line;
+ framebuffer.bytes_per_scan_line = active_mode_info.bytes_per_scan_line;
+ }
+
+ /* Calculate bytes_per_pixel value. */
+ switch(active_mode_info.bits_per_pixel)
+ {
+ case 32: framebuffer.bytes_per_pixel = 4; break;
+ case 24: framebuffer.bytes_per_pixel = 3; break;
+ case 16: framebuffer.bytes_per_pixel = 2; break;
+ case 15: framebuffer.bytes_per_pixel = 2; break;
+ case 8: framebuffer.bytes_per_pixel = 1; break;
+ default:
+ grub_vbe_bios_set_mode (old_mode, 0);
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ "cannot set VBE mode %x",
+ mode);
+ break;
}
/* If video mode is in indexed color, setup default VGA palette. */
- if (index_color_mode)
+ if (framebuffer.index_color_mode)
{
struct grub_vbe_palette_data *palette
= (struct grub_vbe_palette_data *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
/* Make sure that the BIOS can reach the palette. */
grub_memcpy (palette, vga_colors, sizeof (vga_colors));
- status = grub_vbe_set_palette_data (sizeof (vga_colors)
- / sizeof (struct grub_vbe_palette_data),
- 0,
- palette);
+ status = grub_vbe_bios_set_palette_data (sizeof (vga_colors)
+ / sizeof (struct grub_vbe_palette_data),
+ 0,
+ palette);
- /* For now, ignore the status. Not sure if this is fatal. */
+ /* For now, ignore the status. Not sure if this is fatal. */
#if 0
- if (status != 0x004F)
+ if (status != GRUB_VBE_STATUS_OK)
{
- grub_vbe_set_mode (old_mode, 0);
+ grub_vbe_bios_set_mode (old_mode, 0);
return grub_error (GRUB_ERR_BAD_DEVICE,
"cannot set the default VGA palette");
}
@@ -224,12 +270,13 @@
grub_vbe_status_t status;
/* Make sure that VBE is supported. */
- if (grub_vbe_probe (0) != GRUB_ERR_NONE)
+ grub_vbe_probe (0);
+ if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* Try to query current mode from VESA BIOS. */
- status = grub_vbe_get_mode (mode);
- if (status != 0x004F)
+ status = grub_vbe_bios_get_mode (mode);
+ if (status != GRUB_VBE_STATUS_OK)
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot get current VBE mode");
return GRUB_ERR_NONE;
@@ -244,15 +291,16 @@
grub_vbe_status_t status;
/* Make sure that VBE is supported. */
- if (grub_vbe_probe (0) != GRUB_ERR_NONE)
+ grub_vbe_probe (0);
+ if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* If mode is not VESA mode, skip mode info query. */
if (mode >= 0x100)
{
/* Try to get mode info from VESA BIOS. */
- status = grub_vbe_get_mode_info (mode, mi_tmp);
- if (status != 0x004F)
+ status = grub_vbe_bios_get_mode_info (mode, mi_tmp);
+ if (status != GRUB_VBE_STATUS_OK)
return grub_error (GRUB_ERR_BAD_DEVICE,
"cannot get information on the mode %x", mode);
@@ -266,60 +314,72 @@
return GRUB_ERR_NONE;
}
-void
-grub_vbe_set_pixel_rgb (grub_uint32_t x,
- grub_uint32_t y,
- grub_uint8_t red,
- grub_uint8_t green,
- grub_uint8_t blue)
+static grub_uint8_t *
+grub_video_vbe_get_video_ptr (struct grub_video_render_target *source,
+ grub_uint32_t x, grub_uint32_t y)
{
- grub_uint32_t value;
+ grub_uint8_t *ptr = 0;
+
+ switch (source->mode_info.bpp)
+ {
+ case 32:
+ ptr = (grub_uint8_t *)source->data
+ + y * source->mode_info.pitch
+ + x * 4;
+ break;
- if (x >= active_mode_info.x_resolution)
- return;
+ case 24:
+ ptr = (grub_uint8_t *)source->data
+ + y * source->mode_info.pitch
+ + x * 3;
+ break;
- if (y >= active_mode_info.y_resolution)
- return;
+ case 16:
+ case 15:
+ ptr = (grub_uint8_t *)source->data
+ + y * source->mode_info.pitch
+ + x * 2;
+ break;
- if (controller_info.version >= 0x300)
- {
- red >>= 8 - active_mode_info.lin_red_mask_size;
- green >>= 8 - active_mode_info.lin_green_mask_size;
- blue >>= 8 - active_mode_info.lin_blue_mask_size;
-
- value = red << active_mode_info.lin_red_field_position;
- value |= green << active_mode_info.lin_green_field_position;
- value |= blue << active_mode_info.lin_blue_field_position;
+ case 8:
+ ptr = (grub_uint8_t *)source->data
+ + y * source->mode_info.pitch
+ + x;
+ break;
}
- else
- {
- red >>= 8 - active_mode_info.red_mask_size;
- green >>= 8 - active_mode_info.green_mask_size;
- blue >>= 8 - active_mode_info.blue_mask_size;
+
+ return ptr;
+}
- value = red << active_mode_info.red_field_position;
- value |= green << active_mode_info.green_field_position;
- value |= blue << active_mode_info.blue_field_position;
- }
+static void
+grub_video_vbe_draw_pixel (grub_uint32_t x, grub_uint32_t y,
+ grub_video_color_t color)
+{
+ if (x >= render_target->mode_info.width)
+ return;
- switch (active_mode_info.bits_per_pixel)
+ if (y >= render_target->mode_info.height)
+ return;
+
+ switch (render_target->mode_info.bpp)
{
case 32:
{
- grub_uint32_t *ptr = (grub_uint32_t *) (framebuffer
- + y * bytes_per_scan_line
- + x * 4);
+ grub_uint32_t *ptr;
+
+ ptr = (grub_uint32_t *)grub_video_vbe_get_video_ptr (render_target,
+ x, y);
- *ptr = value;
+ *ptr = color;
}
break;
case 24:
{
- grub_uint8_t *ptr = (grub_uint8_t *) (framebuffer
- + y * bytes_per_scan_line
- + x * 3);
- grub_uint8_t *ptr2 = (grub_uint8_t *) &value;
+ grub_uint8_t *ptr;
+ grub_uint8_t *ptr2 = (grub_uint8_t *) &color;
+
+ ptr = grub_video_vbe_get_video_ptr (render_target, x, y);
ptr[0] = ptr2[0];
ptr[1] = ptr2[1];
@@ -330,11 +390,23 @@
case 16:
case 15:
{
- grub_uint16_t *ptr = (grub_uint16_t *) (framebuffer
- + y * bytes_per_scan_line
- + x * 2);
+ grub_uint16_t *ptr;
- *ptr = (grub_uint16_t) (value & 0xFFFF);
+ 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;
@@ -343,44 +415,1068 @@
}
}
-void
-grub_vbe_set_pixel_index (grub_uint32_t x,
- grub_uint32_t y,
- grub_uint8_t color)
+static grub_video_color_t
+grub_video_vbe_get_pixel (struct grub_video_render_target *source,
+ grub_uint32_t x, grub_uint32_t y)
{
- if (x >= active_mode_info.x_resolution)
- return;
+ grub_video_color_t color = 0;
+
+ if (x >= source->mode_info.width)
+ return 0;
- if (y >= active_mode_info.y_resolution)
- return;
+ if (y >= source->mode_info.height)
+ return 0;
+
+ 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)
+{
+ grub_uint16_t *rm_mode_list;
+ grub_uint16_t *p;
+ grub_size_t mode_list_size;
+ struct grub_vbe_info_block info_block;
+
+ /* Check if there is adapter present.
+
+ Firmware note: There has been a report that some cards store video mode
+ list in temporary memory. So we must first use vbe probe to get
+ refreshed information to receive valid pointers and data, and then
+ copy this information to somewhere safe. */
+ grub_vbe_probe (&info_block);
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Copy modelist to local memory. */
+ p = rm_mode_list = real2pm (info_block.video_mode_ptr);
+ while(*p++ != 0xFFFF)
+ ;
+
+ mode_list_size = (grub_addr_t) p - (grub_addr_t) rm_mode_list;
+ mode_list = grub_malloc (mode_list_size);
+ if (! mode_list)
+ return grub_errno;
+ grub_memcpy (mode_list, rm_mode_list, mode_list_size);
+
+ /* Adapter could be found, figure out initial video mode. */
+ grub_vbe_get_video_mode (&initial_mode);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Free allocated resources. */
+ grub_free (mode_list);
+ mode_list = 0;
+
+ return grub_errno;
+ }
+
+ /* Reset frame buffer and render target variables. */
+ grub_memset (&framebuffer, 0, sizeof(framebuffer));
+ render_target = &framebuffer.render_target;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_fini (void)
+{
+ grub_vbe_status_t status;
+
+ /* Restore old video mode. */
+ status = grub_vbe_bios_set_mode (initial_mode, 0);
+ if (status != GRUB_VBE_STATUS_OK)
+ /* TODO: Decide, is this something we want to do. */
+ return grub_errno;
+
+ /* TODO: Free any resources allocated by driver. */
+ grub_free (mode_list);
+ mode_list = 0;
- if (index_color_mode == 1)
+ /* TODO: destroy render targets. */
+
+ /* Return success to caller. */
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_setup (unsigned int width, unsigned int height,
+ unsigned int mode_type)
+{
+ grub_uint16_t *p;
+ struct grub_vbe_mode_info_block mode_info;
+ struct grub_vbe_mode_info_block best_mode_info;
+ grub_uint32_t best_mode = 0;
+ 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)
+ >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS;
+
+ /* Walk thru mode list and try to find matching mode. */
+ for (p = mode_list; *p != 0xFFFF; p++)
{
- grub_uint8_t *ptr = (grub_uint8_t *) (framebuffer
- + y * bytes_per_scan_line
- + x);
+ grub_uint32_t mode = *p;
+
+ grub_vbe_get_video_mode_info (mode, &mode_info);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ /* Could not retrieve mode info, retreat. */
+ grub_errno = GRUB_ERR_NONE;
+ break;
+ }
+
+ if ((mode_info.mode_attributes & 0x001) == 0)
+ /* If not available, skip it. */
+ continue;
+
+ if ((mode_info.mode_attributes & 0x002) == 0)
+ /* Not enough information. */
+ continue;
+
+ if ((mode_info.mode_attributes & 0x008) == 0)
+ /* Monochrome is unusable. */
+ continue;
+
+ if ((mode_info.mode_attributes & 0x080) == 0)
+ /* We support only linear frame buffer modes. */
+ continue;
+
+ if ((mode_info.mode_attributes & 0x010) == 0)
+ /* We allow only graphical modes. */
+ continue;
+
+ if ((mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL)
+ && (mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR))
+ /* Not compatible memory model. */
+ continue;
+
+ if ((mode_info.x_resolution != width)
+ || (mode_info.y_resolution != height))
+ /* Non matching resolution. */
+ continue;
+
+ /* Check if user requested RGB or index color mode. */
+ if ((mode_type & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0)
+ {
+ if (((mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ && (mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL))
+ /* Requested only index color modes. */
+ continue;
+
+ if (((mode_type & GRUB_VIDEO_MODE_TYPE_RGB) != 0)
+ && (mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR))
+ /* Requested only RGB modes. */
+ continue;
+ }
+
+ /* If there is a request for specific depth, ignore others. */
+ if ((depth != 0) && (mode_info.bits_per_pixel != depth))
+ continue;
+
+ /* Select mode with most number of bits per pixel. */
+ if (best_mode != 0)
+ if (mode_info.bits_per_pixel < best_mode_info.bits_per_pixel)
+ continue;
+
+ /* Save so far best mode information for later use. */
+ best_mode = mode;
+ grub_memcpy (&best_mode_info, &mode_info, sizeof (mode_info));
+ }
- *ptr = color;
+ /* Try to initialize best mode found. */
+ if (best_mode != 0)
+ {
+ /* If this fails, then we have mode selection heuristics problem,
+ or adapter failure. */
+ grub_vbe_set_video_mode (best_mode, &active_mode_info);
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Now we are happily in requested video mode. Cache some info
+ in order to fasten later operations. */
+ mode_in_use = best_mode;
+
+ /* Reset render target to framebuffer one. */
+ render_target = &framebuffer.render_target;
+
+ /* Fill mode info details in framebuffer's render target. */
+ render_target->mode_info.width = active_mode_info.x_resolution;
+ render_target->mode_info.height = active_mode_info.y_resolution;
+
+ if (framebuffer.index_color_mode)
+ render_target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+ else
+ render_target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
+
+ render_target->mode_info.bpp = active_mode_info.bits_per_pixel;
+ render_target->mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel;
+ render_target->mode_info.pitch = framebuffer.bytes_per_scan_line;
+ render_target->mode_info.number_of_colors = 256; /* TODO: fix me. */
+ render_target->mode_info.red_mask_size = active_mode_info.red_mask_size;
+ render_target->mode_info.red_field_pos = active_mode_info.red_field_position;
+ render_target->mode_info.green_mask_size = active_mode_info.green_mask_size;
+ render_target->mode_info.green_field_pos = active_mode_info.green_field_position;
+ render_target->mode_info.blue_mask_size = active_mode_info.blue_mask_size;
+ render_target->mode_info.blue_field_pos = active_mode_info.blue_field_position;
+ render_target->mode_info.reserved_mask_size = active_mode_info.rsvd_mask_size;
+ render_target->mode_info.reserved_field_pos = active_mode_info.rsvd_field_position;
+
+ /* Reset viewport to match new mode. */
+ render_target->viewport.x = 0;
+ render_target->viewport.y = 0;
+ render_target->viewport.width = active_mode_info.x_resolution;
+ render_target->viewport.height = active_mode_info.y_resolution;
+
+ /* Set framebuffer pointer and mark it as non allocated. */
+ render_target->is_allocated = 0;
+ render_target->data = framebuffer.ptr;
+
+ /* Copy default palette to initialize emulated palette. */
+ for (i = 0;
+ i < (sizeof (vga_colors)
+ / sizeof (struct grub_vbe_palette_data));
+ i++)
+ {
+ framebuffer.palette[i].r = vga_colors[i].red;
+ framebuffer.palette[i].g = vga_colors[i].green;
+ framebuffer.palette[i].b = vga_colors[i].blue;
+ framebuffer.palette[i].a = 0xFF;
+ }
+
+ return GRUB_ERR_NONE;
+ }
+
+ /* Couldn't found matching mode. */
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found.");
+}
+
+static grub_err_t
+grub_video_vbe_get_info (struct grub_video_mode_info *mode_info)
+{
+ /* Copy mode info from active render target. */
+ grub_memcpy (mode_info, &render_target->mode_info,
+ sizeof (struct grub_video_mode_info));
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_palette (unsigned int start, unsigned int count,
+ struct grub_video_palette_data *palette_data)
+{
+ unsigned int i;
+
+ if (framebuffer.index_color_mode)
+ {
+ /* TODO: Implement setting indexed color mode palette to hardware. */
+ //status = grub_vbe_bios_set_palette_data (sizeof (vga_colors)
+ // / sizeof (struct grub_vbe_palette_data),
+ // 0,
+ // palette);
+
+ }
+
+ /* Then set color to emulated palette. */
+ for (i = 0; (i < count) && ((i + start) < 256); i++)
+ framebuffer.palette[start + i] = palette_data[i];
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_get_palette (unsigned int start, unsigned int count,
+ struct grub_video_palette_data *palette_data)
+{
+ unsigned int i;
+
+ /* Assume that we know everything from index color palette. */
+ for (i = 0; (i < count) && ((i + start) < 256); i++)
+ palette_data[i] = framebuffer.palette[start + i];
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_viewport (unsigned int x, unsigned int y,
+ unsigned int width, unsigned int height)
+{
+ /* Make sure viewport is withing screen dimensions. If viewport was set
+ to be out of the reqion, mark its size as zero. */
+ if (x > active_mode_info.x_resolution)
+ {
+ x = 0;
+ width = 0;
+ }
+
+ if (y > active_mode_info.y_resolution)
+ {
+ y = 0;
+ height = 0;
+ }
+
+ if (x + width > active_mode_info.x_resolution)
+ width = active_mode_info.x_resolution - x;
+
+ if (y + height > active_mode_info.y_resolution)
+ height = active_mode_info.y_resolution - y;
+
+ render_target->viewport.x = x;
+ render_target->viewport.y = y;
+ render_target->viewport.width = width;
+ render_target->viewport.height = height;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_get_viewport (unsigned int *x, unsigned int *y,
+ unsigned int *width, unsigned int *height)
+{
+ if (x) *x = render_target->viewport.x;
+ if (y) *y = render_target->viewport.y;
+ if (width) *width = render_target->viewport.width;
+ if (height) *height = render_target->viewport.height;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_video_color_t
+grub_video_vbe_map_color (grub_uint32_t color_name)
+{
+ /* TODO: implement color theme mapping code. */
+
+ if (color_name < 256)
+ {
+ if ((render_target->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ return color_name;
+ else
+ {
+ grub_video_color_t color;
+
+ color = grub_video_vbe_map_rgb (framebuffer.palette[color_name].r,
+ framebuffer.palette[color_name].g,
+ framebuffer.palette[color_name].b);
+
+ return color;
+ }
+ }
+
+ return 0;
+}
+
+static grub_video_color_t
+grub_video_vbe_map_rgb (grub_uint8_t red, grub_uint8_t green,
+ grub_uint8_t blue)
+{
+ if ((render_target->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ {
+ int minindex = 0;
+ int delta = 0;
+ int tmp;
+ int val;
+ int i;
+
+ /* Find best matching color. */
+ for (i = 0; i < 256; i++)
+ {
+ val = framebuffer.palette[i].r - red;
+ tmp = val * val;
+ val = framebuffer.palette[i].g - green;
+ tmp += val * val;
+ val = framebuffer.palette[i].b - blue;
+ tmp += val * val;
+
+ if (i == 0)
+ delta = tmp;
+
+ if (tmp < delta)
+ {
+ delta = tmp;
+ minindex = i;
+ if (tmp == 0)
+ break;
+ }
+ }
+
+ return minindex;
}
else
{
- color &= 0x0F;
+ grub_uint32_t value;
+ grub_uint8_t alpha = 255; /* Opaque color. */
- if (color < 16)
- {
- grub_vbe_set_pixel_rgb (x,
- y,
- vga_colors[color].red,
- vga_colors[color].green,
- vga_colors[color].blue);
- }
+ red >>= 8 - render_target->mode_info.red_mask_size;
+ green >>= 8 - render_target->mode_info.green_mask_size;
+ blue >>= 8 - render_target->mode_info.blue_mask_size;
+ alpha >>= 8 - render_target->mode_info.reserved_mask_size;
+
+ value = red << render_target->mode_info.red_field_pos;
+ value |= green << render_target->mode_info.green_field_pos;
+ value |= blue << render_target->mode_info.blue_field_pos;
+ value |= alpha << render_target->mode_info.reserved_field_pos;
+
+ return value;
+ }
+
+}
+
+static grub_video_color_t
+grub_video_vbe_map_rgba (grub_uint8_t red, grub_uint8_t green,
+ grub_uint8_t blue, grub_uint8_t alpha)
+{
+ if ((render_target->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ /* No alpha available in index color modes, just use
+ same value as in only RGB modes. */
+ return grub_video_vbe_map_rgb (red, green, blue);
+ else
+ {
+ grub_uint32_t value;
+
+ red >>= 8 - render_target->mode_info.red_mask_size;
+ green >>= 8 - render_target->mode_info.green_mask_size;
+ blue >>= 8 - render_target->mode_info.blue_mask_size;
+ alpha >>= 8 - render_target->mode_info.reserved_mask_size;
+
+ value = red << render_target->mode_info.red_field_pos;
+ value |= green << render_target->mode_info.green_field_pos;
+ value |= blue << render_target->mode_info.blue_field_pos;
+ value |= alpha << render_target->mode_info.reserved_field_pos;
+
+ return value;
+ }
+}
+
+static void
+grub_video_vbe_unmap_color (struct grub_video_render_target * source,
+ grub_video_color_t color,
+ grub_uint8_t *red, grub_uint8_t *green,
+ grub_uint8_t *blue, grub_uint8_t *alpha)
+{
+ if ((source->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+ {
+ /* If we have out of bounds color, return trasnparent black. */
+ if (color > 255)
+ {
+ *red = 0;
+ *green = 0;
+ *blue = 0;
+ *alpha = 0;
+ return;
+ }
+
+ *red = framebuffer.palette[color].r;
+ *green = framebuffer.palette[color].g;
+ *blue = framebuffer.palette[color].b;
+ *alpha = framebuffer.palette[color].a;
+ return;
+ }
+ else
+ {
+ grub_uint32_t tmp;
+
+ /* Get red component. */
+ tmp = color >> source->mode_info.red_field_pos;
+ tmp &= (1 << source->mode_info.red_mask_size) - 1;
+ tmp <<= 8 - source->mode_info.red_mask_size;
+ tmp |= (1 << (8 - source->mode_info.red_mask_size)) - 1;
+ *red = tmp & 0xFF;
+
+ /* Get green component. */
+ tmp = color >> source->mode_info.green_field_pos;
+ tmp &= (1 << source->mode_info.green_mask_size) - 1;
+ tmp <<= 8 - source->mode_info.green_mask_size;
+ tmp |= (1 << (8 - source->mode_info.green_mask_size)) - 1;
+ *green = tmp & 0xFF;
+
+ /* Get blue component. */
+ tmp = color >> source->mode_info.blue_field_pos;
+ tmp &= (1 << source->mode_info.blue_mask_size) - 1;
+ tmp <<= 8 - source->mode_info.blue_mask_size;
+ tmp |= (1 << (8 - source->mode_info.blue_mask_size)) - 1;
+ *blue = tmp & 0xFF;
+
+ /* Get alpha component. */
+ if (source->mode_info.reserved_mask_size > 0)
+ {
+ tmp = color >> source->mode_info.reserved_field_pos;
+ tmp &= (1 << source->mode_info.reserved_mask_size) - 1;
+ tmp <<= 8 - source->mode_info.reserved_mask_size;
+ tmp |= (1 << (8 - source->mode_info.reserved_mask_size)) - 1;
+ }
else
- {
- grub_vbe_set_pixel_rgb (x,
- y,
- 0,
- 0,
- 0);
- }
+ /* If there is no alpha component, assume it opaque. */
+ tmp = 255;
+
+ *alpha = tmp & 0xFF;
+ }
+}
+
+static grub_err_t
+grub_video_vbe_fill_rect (grub_video_color_t color, int x, int y,
+ unsigned int width, unsigned int height)
+{
+ unsigned int i, j;
+
+ /* Make sure there is something to do. */
+ if ((x > (int)render_target->viewport.width) || (x + (int)width < 0))
+ return GRUB_ERR_NONE;
+ if ((y > (int)render_target->viewport.height) || (y + (int)height < 0))
+ return GRUB_ERR_NONE;
+
+ /* Do not allow drawing out of viewport. */
+ if (x < 0)
+ {
+ width += x;
+ x = 0;
+ }
+ if (y < 0)
+ {
+ height += y;
+ y = 0;
+ }
+
+ if ((x + width) > render_target->viewport.width)
+ width = render_target->viewport.width - x;
+ if ((y + height) > render_target->viewport.height)
+ height = render_target->viewport.height - y;
+
+ /* Add viewport offset. */
+ x += render_target->viewport.x;
+ y += render_target->viewport.y;
+
+ /* Fill area. */
+ for (j = 0; j < height; j++)
+ for (i = 0; i < width; i++)
+ grub_video_vbe_draw_pixel (x+i, y+j, color);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_blit_glyph (struct grub_font_glyph * glyph,
+ grub_video_color_t color, int x, int y)
+{
+ unsigned int width;
+ unsigned int charwidth;
+ unsigned int height;
+ unsigned int i;
+ unsigned int j;
+ unsigned int x_offset = 0;
+ unsigned int y_offset = 0;
+
+ /* Make sure there is something to do. */
+ if (x > (int)render_target->viewport.width)
+ return GRUB_ERR_NONE;
+
+ if (y > (int)render_target->viewport.height)
+ return GRUB_ERR_NONE;
+
+ /* Calculate glyph dimensions. */
+ width = ((glyph->width + 7) / 8) * 8;
+ charwidth = width;
+ height = glyph->height;
+
+ if (x + (int)width < 0)
+ return GRUB_ERR_NONE;
+
+ if (y + (int)height < 0)
+ return GRUB_ERR_NONE;
+
+ /* Do not allow drawing out of viewport. */
+ if (x < 0)
+ {
+ width += x;
+ x_offset = (unsigned int)-x;
+ x = 0;
+ }
+ if (y < 0)
+ {
+ height += y;
+ y_offset = (unsigned int)-y;
+ y = 0;
}
+
+ if ((x + width) > render_target->viewport.width)
+ width = render_target->viewport.width - x;
+ if ((y + height) > render_target->viewport.height)
+ height = render_target->viewport.height - y;
+
+ /* Add viewport offset. */
+ x += render_target->viewport.x;
+ y += render_target->viewport.y;
+
+ /* Draw glyph. */
+ for (j = 0; j < height; j++)
+ for (i = 0; i < width; i++)
+ if ((glyph->bitmap[((i + x_offset) / 8)
+ + (j + y_offset) * (charwidth / 8)]
+ & (1 << ((charwidth - (i + x_offset) - 1) % 8))))
+ grub_video_vbe_draw_pixel (x+i, y+j, color);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_blit_bitmap (struct grub_video_bitmap * bitmap,
+ int x, int y, int offset_x, int offset_y,
+ unsigned int width, unsigned int height)
+{
+ /* Make sure there is something to do. */
+ if ((x > (int)render_target->viewport.width) || (x + (int)width < 0))
+ return GRUB_ERR_NONE;
+ if ((y > (int)render_target->viewport.height) || (y + (int)height < 0))
+ return GRUB_ERR_NONE;
+
+ /* Do not allow drawing out of viewport. */
+ if (offset_x < 0)
+ {
+ width += offset_x;
+ x -= offset_x;
+ offset_x = 0;
+ }
+
+ if (offset_y < 0)
+ {
+ height += offset_y;
+ y -= offset_y;
+ offset_y = 0;
+ }
+
+ if (x < 0)
+ {
+ width += x;
+ offset_x += (unsigned int)-x;
+ x = 0;
+ }
+ if (y < 0)
+ {
+ height += y;
+ offset_y += (unsigned int)-y;
+ y = 0;
+ }
+
+ if ((x + width) > render_target->viewport.width)
+ width = render_target->viewport.width - x;
+ if ((y + height) > render_target->viewport.height)
+ height = render_target->viewport.height - y;
+
+ /* TODO: Limit drawing to bitmap dimensions. */
+
+ /* Add viewport offset. */
+ x += render_target->viewport.x;
+ y += render_target->viewport.y;
+
+ /* TODO: Render bitmap. */
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_blit_render_target (struct grub_video_render_target *source,
+ int x, int y, int offset_x, int offset_y,
+ unsigned int width, unsigned int height)
+{
+ unsigned int i;
+ unsigned int j;
+
+ /* Make sure there is something to do. */
+ if ((width == 0) || (height == 0))
+ return GRUB_ERR_NONE;
+ if ((x > (int)render_target->viewport.width) || (x + (int)width < 0))
+ return GRUB_ERR_NONE;
+ if ((y > (int)render_target->viewport.height) || (y + (int)height < 0))
+ return GRUB_ERR_NONE;
+ if ((x + (int)source->mode_info.width) < 0)
+ return GRUB_ERR_NONE;
+ if ((y + (int)source->mode_info.height) < 0)
+ return GRUB_ERR_NONE;
+ if ((offset_x > (int)source->mode_info.width)
+ || (offset_x + (int)source->mode_info.width < 0))
+ return GRUB_ERR_NONE;
+ if ((offset_y > (int)source->mode_info.height)
+ || (offset_y + (int)source->mode_info.height < 0))
+ return GRUB_ERR_NONE;
+
+ /* If we have negative coordinates, optimize drawing to minimum. */
+ if (offset_x < 0)
+ {
+ width += offset_x;
+ x -= offset_x;
+ offset_x = 0;
+ }
+
+ if (offset_y < 0)
+ {
+ height += offset_y;
+ y -= offset_y;
+ offset_y = 0;
+ }
+
+ if (x < 0)
+ {
+ width += x;
+ offset_x += (unsigned int)-x;
+ x = 0;
+ }
+
+ if (y < 0)
+ {
+ height += y;
+ offset_y += (unsigned int)-y;
+ y = 0;
+ }
+
+ /* Do not allow drawing out of viewport. */
+ if ((x + width) > render_target->viewport.width)
+ width = render_target->viewport.width - x;
+ if ((y + height) > render_target->viewport.height)
+ height = render_target->viewport.height - y;
+
+ if ((offset_x + width) > source->mode_info.width)
+ width = source->mode_info.width - offset_x;
+ if ((offset_y + height) > source->mode_info.height)
+ height = source->mode_info.height - offset_y;
+
+ /* Limit drawing to source render target dimensions. */
+ if (width > source->mode_info.width)
+ width = source->mode_info.width;
+
+ if (height > source->mode_info.height)
+ height = source->mode_info.height;
+
+ /* Add viewport offset. */
+ x += render_target->viewport.x;
+ y += render_target->viewport.y;
+
+ /* Render. */
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ grub_uint8_t src_red;
+ grub_uint8_t src_green;
+ grub_uint8_t src_blue;
+ grub_uint8_t src_alpha;
+ grub_uint8_t dst_red;
+ grub_uint8_t dst_green;
+ grub_uint8_t dst_blue;
+ grub_uint8_t dst_alpha;
+ grub_video_color_t src_color;
+ grub_video_color_t dst_color;
+
+ src_color = grub_video_vbe_get_pixel (source, i + offset_x, j + offset_y);
+ grub_video_vbe_unmap_color (source, src_color, &src_red, &src_green,
+ &src_blue, &src_alpha);
+
+ if (src_alpha == 0)
+ continue;
+
+ if (src_alpha == 255)
+ {
+ dst_color = grub_video_vbe_map_rgba (src_red, src_green,
+ src_blue, src_alpha);
+ grub_video_vbe_draw_pixel (x + i, y + j, dst_color);
+ continue;
+ }
+
+ dst_color = grub_video_vbe_get_pixel (render_target, x + i, y + j);
+
+ grub_video_vbe_unmap_color (render_target, dst_color, &dst_red,
+ &dst_green, &dst_blue, &dst_alpha);
+
+ dst_red = (((src_red * src_alpha)
+ + (dst_red * (255 - src_alpha))) / 255);
+ dst_green = (((src_green * src_alpha)
+ + (dst_green * (255 - src_alpha))) / 255);
+ dst_blue = (((src_blue * src_alpha)
+ + (dst_blue * (255 - src_alpha))) / 255);
+
+ dst_alpha = src_alpha;
+ dst_color = grub_video_vbe_map_rgba (dst_red, dst_green, dst_blue,
+ dst_alpha);
+
+ grub_video_vbe_draw_pixel (x + i, y + j, dst_color);
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_scroll (grub_video_color_t color, int dx, int dy)
+{
+ int width;
+ int height;
+ int src_x;
+ int src_y;
+ int dst_x;
+ int dst_y;
+
+ /* 1. Check if we have something to do. */
+ if ((dx == 0) && (dy == 0))
+ return GRUB_ERR_NONE;
+
+ width = render_target->viewport.width - grub_abs (dx);
+ height = render_target->viewport.height - grub_abs (dy);
+
+ if (dx < 0)
+ {
+ src_x = render_target->viewport.x - dx;
+ dst_x = render_target->viewport.x;
+ }
+ else
+ {
+ src_x = render_target->viewport.x;
+ dst_x = render_target->viewport.x + dx;
+ }
+
+ if (dy < 0)
+ {
+ src_y = render_target->viewport.y - dy;
+ dst_y = render_target->viewport.y;
+ }
+ else
+ {
+ src_y = render_target->viewport.y;
+ dst_y = render_target->viewport.y + dy;
+ }
+
+ /* 2. Check if there is need to copy data. */
+ if ((grub_abs (dx) < render_target->viewport.width)
+ && (grub_abs (dy) < render_target->viewport.height))
+ {
+ /* 3. Move data in render target. */
+ grub_uint8_t *src;
+ grub_uint8_t *dst;
+ int j;
+
+ for (j = 0; j < height; j++)
+ {
+ dst = grub_video_vbe_get_video_ptr (render_target, dst_x, dst_y + j);
+ src = grub_video_vbe_get_video_ptr (render_target, src_x, src_y + j);
+ grub_memmove (dst, src,
+ width * render_target->mode_info.bytes_per_pixel);
+ }
+ }
+
+ /* 4. Fill empty space with specified color. In this implementation
+ there might be colliding areas but at the moment there is no need
+ to optimize this. */
+
+ /* 4a. Fill top & bottom parts. */
+ if (dy > 0)
+ grub_video_vbe_fill_rect (color, 0, 0, render_target->viewport.width, dy);
+ else if (dy < 0)
+ {
+ if (render_target->viewport.height < grub_abs (dy))
+ dy = -render_target->viewport.height;
+
+ grub_video_vbe_fill_rect (color, 0, render_target->viewport.height + dy,
+ render_target->viewport.width, -dy);
+ }
+
+ /* 4b. Fill left & right parts. */
+ if (dx > 0)
+ grub_video_vbe_fill_rect (color, 0, 0,
+ dx, render_target->viewport.height);
+ else if (dx < 0)
+ {
+ if (render_target->viewport.width < grub_abs (dx))
+ dx = -render_target->viewport.width;
+
+ grub_video_vbe_fill_rect (color, render_target->viewport.width + dx, 0,
+ -dx, render_target->viewport.height);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_swap_buffers (void)
+{
+ /* TODO: Implement buffer swapping. */
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_create_render_target (struct grub_video_render_target **result,
+ unsigned int width, unsigned int height,
+ unsigned int mode_type)
+{
+ struct grub_video_render_target *target;
+ unsigned int size;
+
+ /* Validate arguments. */
+ if ((! result)
+ || (width == 0)
+ || (height == 0))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "invalid argument given.");
+
+ /* Allocate memory for render target. */
+ target = grub_malloc (sizeof (struct grub_video_render_target));
+ if (! target)
+ return grub_errno;
+
+ /* TODO: Implement other types too.
+ Currently only 32bit render targets are supported. */
+
+ /* Mark render target as allocated. */
+ target->is_allocated = 1;
+
+ /* Maximize viewport. */
+ target->viewport.x = 0;
+ target->viewport.y = 0;
+ target->viewport.width = width;
+ target->viewport.height = height;
+
+ /* Setup render target format. */
+ target->mode_info.width = width;
+ target->mode_info.height = height;
+ target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB
+ | GRUB_VIDEO_MODE_TYPE_ALPHA;
+ target->mode_info.bpp = 32;
+ target->mode_info.bytes_per_pixel = 4;
+ target->mode_info.pitch = target->mode_info.bytes_per_pixel * width;
+ target->mode_info.number_of_colors = 256; /* Emulated paletted. */
+ target->mode_info.red_mask_size = 8;
+ target->mode_info.red_field_pos = 0;
+ target->mode_info.green_mask_size = 8;
+ target->mode_info.green_field_pos = 8;
+ target->mode_info.blue_mask_size = 8;
+ target->mode_info.blue_field_pos = 16;
+ target->mode_info.reserved_mask_size = 8;
+ target->mode_info.reserved_field_pos = 24;
+
+ /* Calculate size needed for the data. */
+ size = (width * target->mode_info.bytes_per_pixel) * height;
+
+ target->data = grub_malloc (size);
+ if (! target->data)
+ {
+ grub_free (target);
+ return grub_errno;
+ }
+
+ /* Clear render target with black and maximum transparency. */
+ grub_memset (target->data, 0, size);
+
+ /* TODO: Add render target to render target list. */
+
+ /* Save result to caller. */
+ *result = target;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_delete_render_target (struct grub_video_render_target *target)
+{
+ /* If there is no target, then just return without error. */
+ if (! target)
+ return GRUB_ERR_NONE;
+
+ /* TODO: Delist render target fron render target list. */
+
+ /* If this is software render target, free it's memory. */
+ if (target->is_allocated)
+ grub_free (target->data);
+
+ /* Free render target. */
+ grub_free (target);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_active_render_target (struct grub_video_render_target *target)
+{
+ if (target == GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER)
+ {
+ render_target = &framebuffer.render_target;
+
+ return GRUB_ERR_NONE;
+ }
+
+ if (target == GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "double buffering not implemented yet.");
+
+ if (! target->data)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "invalid render target given.");
+
+ render_target = target;
+
+ return GRUB_ERR_NONE;
+}
+
+static struct grub_video_adapter grub_video_vbe_adapter =
+ {
+ .name = "VESA BIOS Extension Video Driver",
+
+ .init = grub_video_vbe_init,
+ .fini = grub_video_vbe_fini,
+ .setup = grub_video_vbe_setup,
+ .get_info = grub_video_vbe_get_info,
+ .set_palette = grub_video_vbe_set_palette,
+ .get_palette = grub_video_vbe_get_palette,
+ .set_viewport = grub_video_vbe_set_viewport,
+ .get_viewport = grub_video_vbe_get_viewport,
+ .map_color = grub_video_vbe_map_color,
+ .map_rgb = grub_video_vbe_map_rgb,
+ .map_rgba = grub_video_vbe_map_rgba,
+ .fill_rect = grub_video_vbe_fill_rect,
+ .blit_glyph = grub_video_vbe_blit_glyph,
+ .blit_bitmap = grub_video_vbe_blit_bitmap,
+ .blit_render_target = grub_video_vbe_blit_render_target,
+ .scroll = grub_video_vbe_scroll,
+ .swap_buffers = grub_video_vbe_swap_buffers,
+ .create_render_target = grub_video_vbe_create_render_target,
+ .delete_render_target = grub_video_vbe_delete_render_target,
+ .set_active_render_target = grub_video_vbe_set_active_render_target,
+
+ .next = 0
+ };
+
+GRUB_MOD_INIT(video_i386_pc_vbe)
+{
+ grub_video_register (&grub_video_vbe_adapter);
+}
+
+GRUB_MOD_FINI(video_i386_pc_vbe)
+{
+ grub_video_unregister (&grub_video_vbe_adapter);
}
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: New patch for video subsystem...
2006-03-02 19:28 New patch for video subsystem Vesa Jääskeläinen
2006-03-03 11:49 ` Marco Gerards
@ 2006-05-04 22:27 ` Johan Rydberg
2006-05-05 8:21 ` Vesa Jääskeläinen
1 sibling, 1 reply; 14+ messages in thread
From: Johan Rydberg @ 2006-05-04 22:27 UTC (permalink / raw)
To: The development of GRUB 2
Vesa Jääskeläinen <chaac@nic.fi> writes:
> Here is the newest modifications to video subsystem.
Hi Vesa. What a suitable name :)
Sorry for the delay, and lack of earlier comments, but I've been out
of the GRUB loop for a while. But I have a few comments on the video
subsystem;
Correct me if I am wrong here, but what you call "render target" seems
to be what other video systems call "surface" or "drawable".
Why use the concept of a "active" render target? Why not instead let
all functions that operate on the active render target take a pointer
to a specific render target? Poking through your patch, it seems that
there a lot of the following (forgive my pseudo-code)
grub_video_set_active_render_target (target);
// .. fill it with something ..
grub_video_fill_rect (color, 0, 0, width, height);
grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
grub_video_blit_render_target (target, 0, 0, 0, 0, width, height);
I would feel more comfortable with the following workflow:
grub_video_fill_rect (target, color, 0, 0, width, height);
grub_video_blit_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY,
target, 0, 0, 0, 0, width, height);
Also, I think it is important the user can get hold of a pointer to
the render targets data, and an exact pixel format, to do private
rendering. It would be hard to make a perfect gradient using fill_rect.
I'm not sure the concept of "viewports" are needed at all; instead let
the 'application' (e.g, the terminal) render into a render target, and
blit that to the screen at the desired position. To minimize memory,
the videport-render target can be a sub-render target of the main
render target (ie, they share the same buffer) unless the user wants
any fancy stuff like a background picture.
Thanks,
Johan
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: New patch for video subsystem...
2006-05-04 22:27 ` Johan Rydberg
@ 2006-05-05 8:21 ` Vesa Jääskeläinen
2006-05-05 11:06 ` Johan Rydberg
0 siblings, 1 reply; 14+ messages in thread
From: Vesa Jääskeläinen @ 2006-05-05 8:21 UTC (permalink / raw)
To: The development of GRUB 2
Johan Rydberg wrote:
> Vesa Jääskeläinen <chaac@nic.fi> writes:
>
>> Here is the newest modifications to video subsystem.
>
> Hi Vesa. What a suitable name :)
:)
> Sorry for the delay, and lack of earlier comments, but I've been out
> of the GRUB loop for a while. But I have a few comments on the video
> subsystem;
>
> Correct me if I am wrong here, but what you call "render target" seems
> to be what other video systems call "surface" or "drawable".
Yes they are called by different names and they have a bit different
semantics depending on a place they are used.
> Why use the concept of a "active" render target? Why not instead let
> all functions that operate on the active render target take a pointer
> to a specific render target? Poking through your patch, it seems that
> there a lot of the following (forgive my pseudo-code)
>
> grub_video_set_active_render_target (target);
> // .. fill it with something ..
> grub_video_fill_rect (color, 0, 0, width, height);
>
> grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
> grub_video_blit_render_target (target, 0, 0, 0, 0, width, height);
>
> I would feel more comfortable with the following workflow:
>
> grub_video_fill_rect (target, color, 0, 0, width, height);
> grub_video_blit_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY,
> target, 0, 0, 0, 0, width, height);
Actually that patch is already on CVS :]... so you might find it easier
to read from there.
But the idea here was to make it easier to make function that operates
on different render targets without knowing about it. eg:
set_target a
call common_func
set target b
call common_func
set target c
With your proposal this would require to pass this render target pointer
all around and would make video function calls longer.
There is also another problem in your proposal. What happens if video
driver get's changed and you still have pointers to render targets (or
to raw memory)?
> Also, I think it is important the user can get hold of a pointer to
> the render targets data, and an exact pixel format, to do private
> rendering. It would be hard to make a perfect gradient using fill_rect.
That might not be possible on all architectures. That's the reason there
is a bitmap support (which I am working on currently). Bitmaps are
located on host memory so they can be modified.
Render targets can be located on host memory or on video memory
depending on arch. If they are located on video memory then there is
only need to have video-video blit functionality and some archs might
even provide hardware accelerated helper functions.
One idea of the render targets are that they hide the real bitmap data
format. So one could make a 24 bit RGB picture and then just blit it to
render target and underlying video driver would convert it to correct
format. This frees API user from thinking all possible formats and can
concentrate to make one working implementation.
If one needs to modify render target on all platforms there should be
support to direct access to memory or ability to read contents of frame
buffer to host memory and then write it back or requirement to store
data on host memory and then do blit from there to video memory, but
that is a bit costy on performance.
> I'm not sure the concept of "viewports" are needed at all; instead let
> the 'application' (e.g, the terminal) render into a render target, and
> blit that to the screen at the desired position. To minimize memory,
> the videport-render target can be a sub-render target of the main
> render target (ie, they share the same buffer) unless the user wants
> any fancy stuff like a background picture.
Dropping support for viewports would indeed make driver code a bit
simplier. It were originally designed to problems like this:
Let's assume you have window on your screen. Then you have scroll bars
there so the actual window contents are bigger than what is shown on
screen. Now you just set viewport on target render target and it's easy
to render new contents and you don't need to worry that it would be
rendered out of bounds of target rectangle. And as coordinates are now
related to viewport you don't need to take account that.
But now that I think, one could just give screen coordinates and size
and then use offset to scroll within that area.
Now that I have really used the api for gfxterm and working on bitmap
support I have noticed that it might be better to handle those
operations on one render target and then blit the changed data to
visible render target.
I am not fond to your sub-render-target idea. You can always use
coordinates and offsets to play with it. And the background image or
color would most likely to be present.
> Thanks,
> Johan
Thanks for your comments,
Vesa Jääskeläinen
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: New patch for video subsystem...
2006-05-05 8:21 ` Vesa Jääskeläinen
@ 2006-05-05 11:06 ` Johan Rydberg
0 siblings, 0 replies; 14+ messages in thread
From: Johan Rydberg @ 2006-05-05 11:06 UTC (permalink / raw)
To: The development of GRUB 2
Vesa Jääskeläinen <chaac@nic.fi> writes:
> But the idea here was to make it easier to make function that operates
> on different render targets without knowing about it. eg:
>
> set_target a
> call common_func
> set target b
> call common_func
> set target c
>
> With your proposal this would require to pass this render target pointer
> all around and would make video function calls longer.
I do not see a problem with that. The overhead for passing of an
extra argument is probably less than the overhead of the function
calls (esp since set_active_render_target is an indirect call)
> There is also another problem in your proposal. What happens if video
> driver get's changed and you still have pointers to render targets (or
> to raw memory)?
Possibly the same thing as with the current method; I do not see how
this would make things different?
>> Also, I think it is important the user can get hold of a pointer to
>> the render targets data, and an exact pixel format, to do private
>> rendering. It would be hard to make a perfect gradient using fill_rect.
>
> That might not be possible on all architectures. That's the reason there
> is a bitmap support (which I am working on currently). Bitmaps are
> located on host memory so they can be modified.
I'm not sure "bitmap" is a good word here; maybe "image" would be better.
> Render targets can be located on host memory or on video memory
> depending on arch. If they are located on video memory then there is
> only need to have video-video blit functionality and some archs might
> even provide hardware accelerated helper functions.
If the architecture does not support direct access to the video
memory, it just falls back on returning a render target with
malloc()ed memory.
> One idea of the render targets are that they hide the real bitmap data
> format. So one could make a 24 bit RGB picture and then just blit it to
> render target and underlying video driver would convert it to correct
> format. This frees API user from thinking all possible formats and can
> concentrate to make one working implementation.
Iter-format blits can of course also be supported if you have direct
access to the render target pixel data.
> If one needs to modify render target on all platforms there should be
> support to direct access to memory or ability to read contents of frame
> buffer to host memory and then write it back or requirement to store
> data on host memory and then do blit from there to video memory, but
> that is a bit costy on performance.
I do not see why that should be needed.
Have you looked at for example DirectFB's API? Even through their
coding style is fucked up, the overall design of the API is quite
nice.
I'm just afraid that we will see the exact same thing that happened to
legacy GRUB; a lot of distribution vendors hack up something of their
own. Therefor it is important that we get this right.
~j
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2006-05-05 11:05 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-03-02 19:28 New patch for video subsystem Vesa Jääskeläinen
2006-03-03 11:49 ` Marco Gerards
2006-03-03 15:23 ` Vesa Jääskeläinen
2006-03-05 22:25 ` Yoshinori K. Okuji
2006-03-06 19:56 ` Vesa Jääskeläinen
2006-03-09 20:43 ` Vesa Jääskeläinen
2006-03-10 12:21 ` Vesa Jääskeläinen
2006-03-12 14:49 ` Marco Gerards
2006-03-12 21:23 ` Vesa Jääskeläinen
2006-03-14 17:09 ` Vesa Jääskeläinen
2006-03-12 14:50 ` Marco Gerards
2006-05-04 22:27 ` Johan Rydberg
2006-05-05 8:21 ` Vesa Jääskeläinen
2006-05-05 11:06 ` Johan Rydberg
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.