From 81d10f2f78e26b410577129b1a2117b9f8ac1ce3 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Sun, 30 Jun 2024 18:46:02 +0800 Subject: [PATCH] user: bugfix #148: Optimize GUI User should call sys_framebuffer_flush only once after the modification on the framebuffer has been completed. This commit also renames some gui apps. --- user/src/bin/gui_move.rs | 82 ++++++++++++++ user/src/bin/{gui_rect.rs => gui_shape.rs} | 14 +-- user/src/bin/gui_snake.rs | 5 +- user/src/bin/{gui_simple.rs => gui_tri.rs} | 1 + user/src/bin/gui_uart.rs | 125 --------------------- user/src/io.rs | 3 +- 6 files changed, 89 insertions(+), 141 deletions(-) create mode 100644 user/src/bin/gui_move.rs rename user/src/bin/{gui_rect.rs => gui_shape.rs} (78%) rename user/src/bin/{gui_simple.rs => gui_tri.rs} (97%) delete mode 100644 user/src/bin/gui_uart.rs diff --git a/user/src/bin/gui_move.rs b/user/src/bin/gui_move.rs new file mode 100644 index 00000000..240ff8f4 --- /dev/null +++ b/user/src/bin/gui_move.rs @@ -0,0 +1,82 @@ +#![no_std] +#![no_main] + +extern crate user_lib; +extern crate alloc; + +use user_lib::console::getchar; +use user_lib::{Display, VIRTGPU_XRES, VIRTGPU_YRES}; + +use embedded_graphics::pixelcolor::Rgb888; +use embedded_graphics::prelude::{Drawable, Point, RgbColor, Size}; +use embedded_graphics::primitives::Primitive; +use embedded_graphics::primitives::{PrimitiveStyle, Rectangle}; +use embedded_graphics::draw_target::DrawTarget; + +const INIT_X: i32 = 640; +const INIT_Y: i32 = 400; +const RECT_SIZE: u32 = 40; + +pub struct DrawingBoard { + disp: Display, + latest_pos: Point, +} + +impl DrawingBoard { + pub fn new() -> Self { + Self { + disp: Display::new(Size::new(VIRTGPU_XRES, VIRTGPU_YRES)), + latest_pos: Point::new(INIT_X, INIT_Y), + } + } + fn paint(&mut self) { + Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE)) + .into_styled(PrimitiveStyle::with_stroke(Rgb888::WHITE, 1)) + .draw(&mut self.disp) + .ok(); + } + fn unpaint(&mut self) { + Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE)) + .into_styled(PrimitiveStyle::with_stroke(Rgb888::BLACK, 1)) + .draw(&mut self.disp) + .ok(); + } + pub fn move_rect(&mut self, dx: i32, dy: i32) { + let new_x = self.latest_pos.x + dx; + let new_y = self.latest_pos.y + dy; + let r = (RECT_SIZE / 2) as i32; + if new_x > r && new_x + r < (VIRTGPU_XRES as i32) && new_y > r && new_y + r < (VIRTGPU_YRES as i32) { + self.unpaint(); + self.latest_pos.x = new_x; + self.latest_pos.y = new_y; + self.paint(); + } + } +} + +const LF: u8 = 0x0au8; +const CR: u8 = 0x0du8; +#[no_mangle] +pub fn main() -> i32 { + let mut board = DrawingBoard::new(); + let _ = board.disp.clear(Rgb888::BLACK).unwrap(); + board.disp.flush(); + loop { + let c = getchar(); + if c == LF || c == CR { + break; + } + let mut moved = true; + match c { + b'w' => board.move_rect(0, -10), + b'a' => board.move_rect(-10, 0), + b's' => board.move_rect(0, 10), + b'd' => board.move_rect(10, 0), + _ => moved = false, + } + if moved { + board.disp.flush(); + } + } + 0 +} diff --git a/user/src/bin/gui_rect.rs b/user/src/bin/gui_shape.rs similarity index 78% rename from user/src/bin/gui_rect.rs rename to user/src/bin/gui_shape.rs index 1f377dec..df03df35 100644 --- a/user/src/bin/gui_rect.rs +++ b/user/src/bin/gui_shape.rs @@ -44,18 +44,6 @@ impl DrawingBoard { .draw(&mut self.disp) .ok(); } - fn unpaint(&mut self) { - Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE)) - .into_styled(PrimitiveStyle::with_stroke(Rgb888::BLACK, 10)) - .draw(&mut self.disp) - .ok(); - } - pub fn move_rect(&mut self, dx: i32, dy: i32) { - self.unpaint(); - self.latest_pos.x += dx; - self.latest_pos.y += dy; - self.paint(); - } } #[no_mangle] @@ -64,8 +52,8 @@ pub fn main() -> i32 { let _ = board.disp.clear(Rgb888::BLACK).unwrap(); for _ in 0..5 { board.latest_pos.x += RECT_SIZE as i32 + 20; - //board.latest_pos.y += i; board.paint(); } + board.disp.flush(); 0 } diff --git a/user/src/bin/gui_snake.rs b/user/src/bin/gui_snake.rs index 0411824f..6dd4052f 100644 --- a/user/src/bin/gui_snake.rs +++ b/user/src/bin/gui_snake.rs @@ -328,7 +328,7 @@ const CR: u8 = 0x0du8; #[no_mangle] pub fn main() -> i32 { let mut disp = Display::new(Size::new(VIRTGPU_XRES, VIRTGPU_YRES)); - let mut game = SnakeGame::<20, Rgb888>::new(1280, 800, 20, 20, Rgb888::RED, Rgb888::YELLOW, 50); + let mut game = SnakeGame::<20, Rgb888>::new(1280, 800, 20, 20, Rgb888::RED, Rgb888::YELLOW, 200); let _ = disp.clear(Rgb888::BLACK).unwrap(); loop { if key_pressed() { @@ -345,7 +345,8 @@ pub fn main() -> i32 { } let _ = disp.clear(Rgb888::BLACK).unwrap(); game.draw(&mut disp); - sleep(10); + disp.flush(); + sleep(40); } 0 } diff --git a/user/src/bin/gui_simple.rs b/user/src/bin/gui_tri.rs similarity index 97% rename from user/src/bin/gui_simple.rs rename to user/src/bin/gui_tri.rs index f30b1fc8..69d47f56 100644 --- a/user/src/bin/gui_simple.rs +++ b/user/src/bin/gui_tri.rs @@ -19,5 +19,6 @@ pub fn main() -> i32 { } } }); + disp.flush(); 0 } diff --git a/user/src/bin/gui_uart.rs b/user/src/bin/gui_uart.rs deleted file mode 100644 index 8e9c9b8c..00000000 --- a/user/src/bin/gui_uart.rs +++ /dev/null @@ -1,125 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; -extern crate alloc; - -use user_lib::console::getchar; -use user_lib::{framebuffer, framebuffer_flush}; - -use embedded_graphics::pixelcolor::Rgb888; -use embedded_graphics::prelude::{Drawable, Point, RgbColor, Size}; -use embedded_graphics::primitives::Primitive; -use embedded_graphics::primitives::{PrimitiveStyle, Rectangle}; -use embedded_graphics::{draw_target::DrawTarget, prelude::OriginDimensions}; - -pub const VIRTGPU_XRES: usize = 1280; -pub const VIRTGPU_YRES: usize = 800; -pub const VIRTGPU_LEN: usize = VIRTGPU_XRES * VIRTGPU_YRES * 4; - -const INIT_X: i32 = 640; -const INIT_Y: i32 = 400; -const RECT_SIZE: u32 = 40; - -pub struct Display { - pub size: Size, - pub point: Point, - //pub fb: Arc<&'static mut [u8]>, - pub fb: &'static mut [u8], -} - -impl Display { - pub fn new(size: Size, point: Point) -> Self { - let fb_ptr = framebuffer() as *mut u8; - println!( - "Hello world from user mode program! 0x{:X} , len {}", - fb_ptr as usize, VIRTGPU_LEN - ); - let fb = - unsafe { core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_LEN as usize) }; - Self { size, point, fb } - } -} - -impl OriginDimensions for Display { - fn size(&self) -> Size { - self.size - } -} - -impl DrawTarget for Display { - type Color = Rgb888; - - type Error = core::convert::Infallible; - - fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> - where - I: IntoIterator>, - { - pixels.into_iter().for_each(|px| { - let idx = ((self.point.y + px.0.y) * VIRTGPU_XRES as i32 + self.point.x + px.0.x) - as usize - * 4; - if idx + 2 >= self.fb.len() { - return; - } - self.fb[idx] = px.1.b(); - self.fb[idx + 1] = px.1.g(); - self.fb[idx + 2] = px.1.r(); - }); - framebuffer_flush(); - Ok(()) - } -} - -pub struct DrawingBoard { - disp: Display, - latest_pos: Point, -} - -impl DrawingBoard { - pub fn new() -> Self { - Self { - disp: Display::new(Size::new(1280, 800), Point::new(0, 0)), - latest_pos: Point::new(INIT_X, INIT_Y), - } - } - fn paint(&mut self) { - Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE)) - .into_styled(PrimitiveStyle::with_stroke(Rgb888::WHITE, 1)) - .draw(&mut self.disp) - .ok(); - } - fn unpaint(&mut self) { - Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE)) - .into_styled(PrimitiveStyle::with_stroke(Rgb888::BLACK, 1)) - .draw(&mut self.disp) - .ok(); - } - pub fn move_rect(&mut self, dx: i32, dy: i32) { - self.unpaint(); - self.latest_pos.x += dx; - self.latest_pos.y += dy; - self.paint(); - } -} - -const LF: u8 = 0x0au8; -const CR: u8 = 0x0du8; -#[no_mangle] -pub fn main() -> i32 { - // let fb_ptr = framebuffer() as *mut u8; - let mut board = DrawingBoard::new(); - let _ = board.disp.clear(Rgb888::BLACK).unwrap(); - for i in 0..20 { - let c = getchar(); - if c == LF || c == CR { - break; - } - board.latest_pos.x += i; - board.latest_pos.y += i; - board.paint(); - } - 0 -} diff --git a/user/src/io.rs b/user/src/io.rs index 30e7a1c1..d2c2a0ac 100644 --- a/user/src/io.rs +++ b/user/src/io.rs @@ -32,6 +32,8 @@ impl Display { } pub fn paint_on_framebuffer(&mut self, p: impl FnOnce(&mut [u8]) -> ()) { p(self.framebuffer()); + } + pub fn flush(&self) { framebuffer_flush(); } } @@ -60,7 +62,6 @@ impl DrawTarget for Display { self.fb[idx + 1] = px.1.g(); self.fb[idx + 2] = px.1.r(); }); - framebuffer_flush(); Ok(()) } }