improve screen flickering on fbcons
This commit is contained in:
parent
c64f8d4de2
commit
d7b75cf462
3 changed files with 45 additions and 9 deletions
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue