From d7b75cf4627dcfe8b0e7daf6154c75fffd572fbc Mon Sep 17 00:00:00 2001 From: husky Date: Fri, 12 Sep 2025 13:22:15 -0700 Subject: [PATCH] improve screen flickering on fbcons --- src/dev/framebuffer/console.rs | 20 +++++++++++++------- src/dev/framebuffer/mod.rs | 32 ++++++++++++++++++++++++++++++-- src/trafficcontrol.rs | 2 ++ 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/dev/framebuffer/console.rs b/src/dev/framebuffer/console.rs index 5cc7ba2..77cc606 100644 --- a/src/dev/framebuffer/console.rs +++ b/src/dev/framebuffer/console.rs @@ -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::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 cursor: (usize, usize), // (x, y) pub need_screen_clear: bool, + pub need_line_clear: bool, } pub static FBCONSOLE: Spinlock = Spinlock::new(FramebufferConsole::empty()); @@ -16,6 +17,7 @@ impl FramebufferConsole { buffer: [[' '; 20]; 15], cursor: (0, 0), need_screen_clear: true, + need_line_clear: false, } } @@ -31,10 +33,10 @@ impl FramebufferConsole { // DOES send a framebuffer update! pub fn clear_terminal(&mut self, tc: &mut TrafficControl) { - self.need_screen_clear = false; + self.need_screen_clear = true; self.buffer = [[' '; 20]; 15]; self.cursor = (0, 0); - self.render(tc); + self.render(tc, true); } // DOES send a framebuffer update! @@ -54,7 +56,7 @@ impl FramebufferConsole { if c == '\x08' { was_special_char = true; // 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 { self.cursor.0 -= 1; } 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 { - fb_clearscreen(tc); + fb_clearscreen(tc, refresh_whole_screen); 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() { fb_write_char_array(tc, 0, y * 16, line); diff --git a/src/dev/framebuffer/mod.rs b/src/dev/framebuffer/mod.rs index d651117..576d7db 100644 --- a/src/dev/framebuffer/mod.rs +++ b/src/dev/framebuffer/mod.rs @@ -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(); let fbaddr = FRAMEBUFFER_ADDR.load(Ordering::Relaxed); 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( tc, 0, @@ -103,4 +131,4 @@ pub fn fb_clearscreen(tc: &mut TrafficControl) { FRAMEBUFFER_WIDTH as u32, FRAMEBUFFER_HEIGHT as u32, ); -} +} \ No newline at end of file diff --git a/src/trafficcontrol.rs b/src/trafficcontrol.rs index c38c386..4f63715 100644 --- a/src/trafficcontrol.rs +++ b/src/trafficcontrol.rs @@ -251,6 +251,8 @@ pub fn handle_syscall( uart.putstr("using framebuffer console\n"); } } + let mut fbcons = crate::dev::framebuffer::console::FBCONSOLE.lock(); + fbcons.clear_terminal(&mut tc); } 0 }