improve screen flickering on fbcons

This commit is contained in:
husky 2025-09-12 13:22:15 -07:00
parent c64f8d4de2
commit d7b75cf462
3 changed files with 45 additions and 9 deletions

View file

@ -1,4 +1,4 @@
use crate::dev::framebuffer::{fb_clearscreen, fb_write_char_array}; use crate::dev::framebuffer::{fb_clear_area, fb_clearscreen, fb_write_char_array};
use crate::spinlock::Spinlock; use crate::spinlock::Spinlock;
use crate::trafficcontrol::TrafficControl; use crate::trafficcontrol::TrafficControl;
@ -6,6 +6,7 @@ pub struct FramebufferConsole {
pub buffer: [[char; 20]; 15], // our font is 16x16, 320x240 is the standard res, so 20x15 pub buffer: [[char; 20]; 15], // our font is 16x16, 320x240 is the standard res, so 20x15
pub cursor: (usize, usize), // (x, y) pub cursor: (usize, usize), // (x, y)
pub need_screen_clear: bool, pub need_screen_clear: bool,
pub need_line_clear: bool,
} }
pub static FBCONSOLE: Spinlock<FramebufferConsole> = Spinlock::new(FramebufferConsole::empty()); pub static FBCONSOLE: Spinlock<FramebufferConsole> = Spinlock::new(FramebufferConsole::empty());
@ -16,6 +17,7 @@ impl FramebufferConsole {
buffer: [[' '; 20]; 15], buffer: [[' '; 20]; 15],
cursor: (0, 0), cursor: (0, 0),
need_screen_clear: true, need_screen_clear: true,
need_line_clear: false,
} }
} }
@ -31,10 +33,10 @@ impl FramebufferConsole {
// DOES send a framebuffer update! // DOES send a framebuffer update!
pub fn clear_terminal(&mut self, tc: &mut TrafficControl) { pub fn clear_terminal(&mut self, tc: &mut TrafficControl) {
self.need_screen_clear = false; self.need_screen_clear = true;
self.buffer = [[' '; 20]; 15]; self.buffer = [[' '; 20]; 15];
self.cursor = (0, 0); self.cursor = (0, 0);
self.render(tc); self.render(tc, true);
} }
// DOES send a framebuffer update! // DOES send a framebuffer update!
@ -54,7 +56,7 @@ impl FramebufferConsole {
if c == '\x08' { if c == '\x08' {
was_special_char = true; was_special_char = true;
// we don't clear the character, that's up to the terminal // we don't clear the character, that's up to the terminal
self.need_screen_clear = true; self.need_line_clear = true;
if self.cursor.0 > 0 { if self.cursor.0 > 0 {
self.cursor.0 -= 1; self.cursor.0 -= 1;
} else { } else {
@ -79,14 +81,18 @@ impl FramebufferConsole {
} }
} }
self.render(tc); self.render(tc, false);
} }
pub fn render(&mut self, tc: &mut TrafficControl) { pub fn render(&mut self, tc: &mut TrafficControl, refresh_whole_screen: bool) {
if self.need_screen_clear { if self.need_screen_clear {
fb_clearscreen(tc); fb_clearscreen(tc, refresh_whole_screen);
self.need_screen_clear = false; self.need_screen_clear = false;
} }
if self.need_line_clear {
fb_clear_area(tc, 0, self.cursor.1 * 16, 320, 16);
self.need_line_clear = false;
}
for (y, line) in self.buffer.iter().enumerate() { for (y, line) in self.buffer.iter().enumerate() {
fb_write_char_array(tc, 0, y * 16, line); fb_write_char_array(tc, 0, y * 16, line);

View file

@ -81,7 +81,7 @@ pub fn fb_write_char_array(tc: &mut TrafficControl, mut x: usize, y: usize, char
); );
} }
pub fn fb_clearscreen(tc: &mut TrafficControl) { pub fn fb_clearscreen(tc: &mut TrafficControl, send_refresh: bool) {
const BYTES: [u8; 3] = FB_BG_COLOR.to_bytes(); const BYTES: [u8; 3] = FB_BG_COLOR.to_bytes();
let fbaddr = FRAMEBUFFER_ADDR.load(Ordering::Relaxed); let fbaddr = FRAMEBUFFER_ADDR.load(Ordering::Relaxed);
if fbaddr == 0 { if fbaddr == 0 {
@ -96,6 +96,34 @@ pub fn fb_clearscreen(tc: &mut TrafficControl) {
} }
} }
} }
if send_refresh {
framebuffer_update(
tc,
0,
0,
FRAMEBUFFER_WIDTH as u32,
FRAMEBUFFER_HEIGHT as u32,
);
}
}
pub fn fb_clear_area(tc: &mut TrafficControl, x: usize, y: usize, w: usize, h: usize) {
const BYTES: [u8; 3] = FB_BG_COLOR.to_bytes();
let fbaddr = FRAMEBUFFER_ADDR.load(Ordering::Relaxed);
if fbaddr == 0 {
return;
}
let fbstride = FRAMEBUFFER_BPP.load(Ordering::Relaxed) * FRAMEBUFFER_WIDTH;
for row in 0..h {
for col in 0..w {
unsafe {
unsafe {
let fb = (fbaddr as *mut u8).add(((y+row) * fbstride) + ((x+col) * 4)) as *mut u32;
fb.write_volatile(u32::from_ne_bytes([0, BYTES[0], BYTES[1], BYTES[2]]));
}
}
}
}
framebuffer_update( framebuffer_update(
tc, tc,
0, 0,
@ -103,4 +131,4 @@ pub fn fb_clearscreen(tc: &mut TrafficControl) {
FRAMEBUFFER_WIDTH as u32, FRAMEBUFFER_WIDTH as u32,
FRAMEBUFFER_HEIGHT as u32, FRAMEBUFFER_HEIGHT as u32,
); );
} }

View file

@ -251,6 +251,8 @@ pub fn handle_syscall(
uart.putstr("using framebuffer console\n"); uart.putstr("using framebuffer console\n");
} }
} }
let mut fbcons = crate::dev::framebuffer::console::FBCONSOLE.lock();
fbcons.clear_terminal(&mut tc);
} }
0 0
} }