video: Do not switch video modes when unnecessary to avoid flickering and screen blanking out
diff --git a/stage23/drivers/gop.c b/stage23/drivers/gop.c
index 2f574f91..d42d72e8 100644
--- a/stage23/drivers/gop.c
+++ b/stage23/drivers/gop.c
@@ -2,6 +2,7 @@
#include <efi.h>
#include <lib/blib.h>
+#include <lib/term.h>
#include <drivers/gop.h>
#include <drivers/edid.h>
#include <lib/print.h>
@@ -98,19 +99,34 @@ static bool try_mode(struct fb_info *ret, size_t mode, int width, int height, in
print("gop: Found matching mode %x, attempting to set...\n", mode);
+ if ((int)mode == current_video_mode) {
+ print("gop: Mode was already set, perfect!\n");
+ }
+
status = uefi_call_wrapper(gop->SetMode, 2, gop, mode);
if (status) {
+ current_video_mode = -2;
print("gop: Failed to set video mode %x, moving on...\n", mode);
return false;
}
+ current_video_mode = mode;
+
ret->memory_model = 0x06;
ret->framebuffer_addr = gop->Mode->FrameBufferBase;
ret->framebuffer_pitch = gop->Mode->Info->PixelsPerScanLine * 4;
ret->framebuffer_width = gop->Mode->Info->HorizontalResolution;
ret->framebuffer_height = gop->Mode->Info->VerticalResolution;
+ // Clear framebuffer
+ for (size_t y = 0; y < ret->framebuffer_height; y++) {
+ for (size_t x = 0; x < ret->framebuffer_pitch; x++) {
+ uint8_t *fbp = (uint8_t *)(uintptr_t)ret->framebuffer_addr;
+ fbp[y * ret->framebuffer_pitch + x] = 0;
+ }
+ }
+
return true;
}
diff --git a/stage23/drivers/vbe.c b/stage23/drivers/vbe.c
index 6876c652..489db752 100644
--- a/stage23/drivers/vbe.c
+++ b/stage23/drivers/vbe.c
@@ -12,6 +12,7 @@
#include <lib/image.h>
#include <lib/config.h>
#include <lib/uri.h>
+#include <lib/term.h>
#include <mm/pmm.h>
struct vbe_info_struct {
@@ -175,10 +176,15 @@ retry:
if (!(vbe_mode_info.mode_attributes & (1 << 7)))
continue;
print("vbe: Found matching mode %x, attempting to set...\n", vid_modes[i]);
- if (set_vbe_mode(vid_modes[i]) == 0x01) {
+ if (vid_modes[i] == current_video_mode) {
+ print("vbe: Mode was already set, perfect!\n");
+ } else if (set_vbe_mode(vid_modes[i]) == 0x01) {
+ current_video_mode = -2;
print("vbe: Failed to set video mode %x, moving on...\n", vid_modes[i]);
continue;
}
+ current_video_mode = vid_modes[i];
+
print("vbe: Framebuffer address: %x\n", vbe_mode_info.framebuffer_addr);
ret->memory_model = vbe_mode_info.memory_model;
ret->framebuffer_addr = vbe_mode_info.framebuffer_addr;
@@ -202,6 +208,15 @@ retry:
ret->blue_mask_size = vbe_mode_info.lin_blue_mask_size;
ret->blue_mask_shift = vbe_mode_info.lin_blue_mask_shift;
}
+
+ // Clear framebuffer
+ for (size_t y = 0; y < ret->framebuffer_height; y++) {
+ for (size_t x = 0; x < ret->framebuffer_pitch; x++) {
+ uint8_t *fbp = (uint8_t *)(uintptr_t)ret->framebuffer_addr;
+ fbp[y * ret->framebuffer_pitch + x] = 0;
+ }
+ }
+
return true;
}
}
diff --git a/stage23/drivers/vga_textmode.s2.c b/stage23/drivers/vga_textmode.s2.c
index 99cad37f..c580453b 100644
--- a/stage23/drivers/vga_textmode.s2.c
+++ b/stage23/drivers/vga_textmode.s2.c
@@ -7,6 +7,7 @@
#include <sys/cpu.h>
#include <lib/real.h>
#include <lib/libc.h>
+#include <lib/term.h>
#include <mm/pmm.h>
#define VIDEO_BOTTOM ((VD_ROWS * VD_COLS) - 1)
@@ -19,10 +20,10 @@ static uint8_t *video_mem = (uint8_t *)0xb8000;
static uint8_t *current_buffer;
-static size_t cursor_offset = 0;
-static int cursor_status = 1;
-static uint8_t text_palette = 0x07;
-static uint8_t cursor_palette = 0x70;
+static size_t cursor_offset;
+static int cursor_status;
+static uint8_t text_palette;
+static uint8_t cursor_palette;
static void clear_cursor(void) {
current_buffer[cursor_offset + 1] = text_palette;
@@ -75,13 +76,28 @@ void text_disable_cursor(void) {
// VGA cursor code taken from: https://wiki.osdev.org/Text_Mode_Cursor
void init_vga_textmode(int *_rows, int *_cols) {
+ if (current_video_mode != -1) {
+ struct rm_regs r = {0};
+ r.eax = 0x0003;
+ rm_int(0x10, &r, &r);
+
+ current_video_mode = -1;
+ }
+
outb(0x3d4, 0x0a);
outb(0x3d5, 0x20);
- *_rows = VD_ROWS;
- *_cols = VD_COLS / 2;
+ cursor_offset = 0;
+ cursor_status = 1;
+ text_palette = 0x07;
+ cursor_palette = 0x70;
text_double_buffer(false);
+
+ text_clear(false);
+
+ *_rows = VD_ROWS;
+ *_cols = VD_COLS / 2;
}
void text_double_buffer(bool state) {
diff --git a/stage23/lib/term.h b/stage23/lib/term.h
index 63680e8c..03c4bebf 100644
--- a/stage23/lib/term.h
+++ b/stage23/lib/term.h
@@ -31,5 +31,6 @@ enum {
};
extern int term_backend;
+extern int current_video_mode;
#endif
diff --git a/stage23/lib/term.s2.c b/stage23/lib/term.s2.c
index 469fafe0..23b3c973 100644
--- a/stage23/lib/term.s2.c
+++ b/stage23/lib/term.s2.c
@@ -7,6 +7,8 @@
#include <lib/blib.h>
#include <drivers/vga_textmode.h>
+int current_video_mode = -1;
+
int term_backend = NOT_READY;
void (*raw_putchar)(uint8_t c);
@@ -25,7 +27,6 @@ int term_rows, term_cols;
#if defined (bios)
void term_textmode(void) {
- term_deinit();
init_vga_textmode(&term_rows, &term_cols);
raw_putchar = text_putchar;
@@ -45,12 +46,6 @@ void term_textmode(void) {
#endif
void term_deinit(void) {
-#if defined (bios)
- struct rm_regs r = {0};
- r.eax = 0x0003;
- rm_int(0x10, &r, &r);
-#endif
-
term_backend = NOT_READY;
}
