From 1ffb45ac9c603e32a7422c7205d11a4ed1d19d2a Mon Sep 17 00:00:00 2001 From: mintsuki <mintsuki@protonmail.com> Date: Sun, 4 Apr 2021 03:38:38 +0200 Subject: [PATCH] video: Do not switch video modes when unnecessary to avoid flickering and screen blanking out --- stage23/drivers/gop.c | 16 ++++++++++++++++ stage23/drivers/vbe.c | 17 ++++++++++++++++- stage23/drivers/vga_textmode.s2.c | 28 ++++++++++++++++++++++------ stage23/lib/term.h | 1 + stage23/lib/term.s2.c | 9 ++------- 5 files changed, 57 insertions(+), 14 deletions(-) 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; }