[SeaBIOS] [PATCH 2/2] vgabios: Add software cursor capability
Kevin O'Connor
kevin at koconnor.net
Sat Oct 18 20:56:25 CEST 2014
Add mechanism for drawing a cursor to the framebuffer to implement a
cursor in software. This can be useful for "coreboot native vga".
Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
vgasrc/Kconfig | 5 +++++
vgasrc/vgabios.c | 2 +-
vgasrc/vgabios.h | 1 +
vgasrc/vgafb.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/vgasrc/Kconfig b/vgasrc/Kconfig
index 6474c22..5f3cc9d 100644
--- a/vgasrc/Kconfig
+++ b/vgasrc/Kconfig
@@ -51,6 +51,7 @@ menu "VGA ROM"
depends on COREBOOT
bool "coreboot linear framebuffer"
select VGA_EMULATE_TEXTATTR
+ select VGA_SOFTWARE_CURSOR
help
Build support for a vgabios wrapper around video
devices initialized using coreboot native vga init.
@@ -89,6 +90,10 @@ menu "VGA ROM"
help
Try to emulate text mode attributes when writing text in
graphics mode.
+ config VGA_SOFTWARE_CURSOR
+ bool
+ help
+ Emulate a cursor by modifying the framebuffer.
config VGA_ALLOCATE_EXTRA_STACK
depends on BUILD_VGABIOS
diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c
index 85a060e..ab9f4a0 100644
--- a/vgasrc/vgabios.c
+++ b/vgasrc/vgabios.c
@@ -111,7 +111,7 @@ set_cursor_pos(struct cursorpos cp)
stdvga_set_cursor_pos((int)text_address(cp));
}
-static struct cursorpos
+struct cursorpos
get_cursor_pos(u8 page)
{
if (page == 0xff)
diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h
index e07309a..5abbe4e 100644
--- a/vgasrc/vgabios.h
+++ b/vgasrc/vgabios.h
@@ -115,6 +115,7 @@ struct cursorpos {
};
int vga_bpp(struct vgamode_s *vmode_g);
u16 calc_page_size(u8 memmodel, u16 width, u16 height);
+struct cursorpos get_cursor_pos(u8 page);
int bda_save_restore(int cmd, u16 seg, void *data);
struct vgamode_s *get_current_mode(void);
int vga_set_mode(int mode, int flags);
diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c
index f179584..85ff184 100644
--- a/vgasrc/vgafb.c
+++ b/vgasrc/vgafb.c
@@ -454,6 +454,32 @@ gfx_write_char(struct vgamode_s *vmode_g
}
}
+// Draw/undraw a cursor on the framebuffer by xor'ing the cursor cell
+void
+gfx_set_swcursor(struct vgamode_s *vmode_g, int enable)
+{
+ struct cursorpos cp = get_cursor_pos(0xff);
+ if (cp.x >= GET_BDA(video_cols))
+ return;
+
+ struct gfx_op op;
+ init_gfx_op(&op, vmode_g);
+ op.x = cp.x * 8;
+ int cheight = GET_BDA(char_height);
+ op.y = cp.y * cheight;
+
+ int i;
+ for (i = 0; i < cheight; i++, op.y++) {
+ op.op = GO_READ8;
+ handle_gfx_op(&op);
+ int j;
+ for (j = 0; j < 8; j++)
+ op.pixels[j] ^= 0x07;
+ op.op = GO_WRITE8;
+ handle_gfx_op(&op);
+ }
+}
+
// Set the pixel at the given position.
void
vgafb_write_pixel(u8 color, u16 x, u16 y)
@@ -599,4 +625,22 @@ fail: ;
void
vgafb_set_swcursor(int enable)
{
+ if (!CONFIG_VGA_SOFTWARE_CURSOR)
+ return;
+
+ struct vgamode_s *vmode_g = get_current_mode();
+ if (!vmode_g)
+ return;
+
+ if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) {
+ gfx_set_swcursor(vmode_g, enable);
+ return;
+ }
+
+ // In text mode, swap foreground and background attributes for cursor
+ struct cursorpos cp = get_cursor_pos(0xff);
+ void *dest_far = text_address(cp) + 1;
+ u8 attr = GET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)dest_far);
+ attr = (attr >> 4) | (attr << 4);
+ SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)dest_far, attr);
}
--
1.9.3
More information about the SeaBIOS
mailing list