提交 b543a037 编写于 作者: Y Yifan Wu

feat: simple drawing board GUI

上级 971a9a9c
...@@ -9,5 +9,6 @@ os/src/link_app.S ...@@ -9,5 +9,6 @@ os/src/link_app.S
os/src/linker.ld os/src/linker.ld
os/last-* os/last-*
os/.gdb_history os/.gdb_history
os/virt.out
tools/ tools/
pushall.sh pushall.sh
...@@ -19,5 +19,6 @@ virtio-input-decoder = "0.1.4" ...@@ -19,5 +19,6 @@ virtio-input-decoder = "0.1.4"
embedded-graphics = "0.7.1" embedded-graphics = "0.7.1"
tinybmp = "0.3.1" tinybmp = "0.3.1"
[profile.release] [profile.release]
debug = true debug = true
...@@ -12,6 +12,12 @@ BOARD := qemu ...@@ -12,6 +12,12 @@ BOARD := qemu
SBI ?= rustsbi SBI ?= rustsbi
BOOTLOADER := ../bootloader/$(SBI)-$(BOARD).bin BOOTLOADER := ../bootloader/$(SBI)-$(BOARD).bin
# GUI
GUI ?= off
ifeq ($(GUI), off)
GUI_OPTION := -display none
endif
# Building mode argument # Building mode argument
ifeq ($(MODE), release) ifeq ($(MODE), release)
MODE_ARG := --release MODE_ARG := --release
...@@ -67,27 +73,12 @@ disasm-vim: kernel ...@@ -67,27 +73,12 @@ disasm-vim: kernel
run: run-inner run: run-inner
gui: build
ifeq ($(BOARD),qemu)
@qemu-system-riscv64 \
-M 128m \
-machine virt \
-bios $(BOOTLOADER) \
-device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) \
-drive file=$(FS_IMG),if=none,format=raw,id=x0 \
-device virtio-blk-device,drive=x0 \
-device virtio-gpu-device \
-device virtio-keyboard-device \
-device virtio-mouse-device \
-serial stdio
endif
run-inner: build run-inner: build
@qemu-system-riscv64 \ @qemu-system-riscv64 \
-M 128m \ -M 128m \
-machine virt \ -machine virt \
-bios $(BOOTLOADER) \ -bios $(BOOTLOADER) \
-display none \ $(GUI_OPTION) \
-device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) \ -device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) \
-drive file=$(FS_IMG),if=none,format=raw,id=x0 \ -drive file=$(FS_IMG),if=none,format=raw,id=x0 \
-device virtio-blk-device,drive=x0 \ -device virtio-blk-device,drive=x0 \
...@@ -96,6 +87,10 @@ run-inner: build ...@@ -96,6 +87,10 @@ run-inner: build
-device virtio-mouse-device \ -device virtio-mouse-device \
-serial stdio -serial stdio
fdt:
@qemu-system-riscv64 -M 128m -machine virt,dumpdtb=virt.out
fdtdump virt.out
debug: build debug: build
@tmux new-session -d \ @tmux new-session -d \
"qemu-system-riscv64 -machine virt -nographic -bios $(BOOTLOADER) -device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) -s -S" && \ "qemu-system-riscv64 -machine virt -nographic -bios $(BOOTLOADER) -device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) -s -S" && \
...@@ -109,4 +104,4 @@ gdbserver: build ...@@ -109,4 +104,4 @@ gdbserver: build
gdbclient: gdbclient:
@riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234' @riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234'
.PHONY: build env kernel clean disasm disasm-vim run-inner fs-img gdbserver gdbclient .PHONY: build env kernel clean disasm disasm-vim run-inner fs-img gdbserver gdbclient fdt
qemu-system-riscv64 -M 128m -machine virt,dumpdtb=virt.out \
-bios ../bootloader/rustsbi-qemu.bin \
-device loader,file=target/riscv64gc-unknown-none-elf/release/os.bin,addr=0x80200000 \
-drive file=../user/target/riscv64gc-unknown-none-elf/release/fs.img,if=none,format=raw,id=x0 \
-device virtio-blk-device,drive=x0 \
-device virtio-gpu-device \
-device virtio-keyboard-device \
-device virtio-mouse-device \
-serial stdio
fdtdump virt.out
\ No newline at end of file
qemu-system-riscv64 -M 128m -machine virt \
-bios ../bootloader/rustsbi-qemu.bin \
-display none \
-device loader,file=target/riscv64gc-unknown-none-elf/release/os.bin,addr=0x80200000 \
-drive file=../user/target/riscv64gc-unknown-none-elf/release/fs.img,if=none,format=raw,id=x0 \
-device virtio-blk-device,drive=x0 \
-device virtio-gpu-device \
-device virtio-keyboard-device \
-device virtio-mouse-device \
-serial stdio
qemu-system-riscv64 -M 128m -machine virt \
-bios ../bootloader/rustsbi-qemu.bin \
-device loader,file=target/riscv64gc-unknown-none-elf/release/os.bin,addr=0x80200000 \
-drive file=../user/target/riscv64gc-unknown-none-elf/release/fs.img,if=none,format=raw,id=x0 \
-device virtio-blk-device,drive=x0 \
-device virtio-gpu-device \
-device virtio-keyboard-device \
-device virtio-mouse-device \
-serial stdio
...@@ -14,6 +14,7 @@ pub const VIRT_PLIC: usize = 0xC00_0000; ...@@ -14,6 +14,7 @@ pub const VIRT_PLIC: usize = 0xC00_0000;
pub const VIRT_UART: usize = 0x1000_0000; pub const VIRT_UART: usize = 0x1000_0000;
pub const VIRTGPU_XRES: u32 = 1280; pub const VIRTGPU_XRES: u32 = 1280;
#[allow(unused)]
pub const VIRTGPU_YRES: u32 = 800; pub const VIRTGPU_YRES: u32 = 800;
use crate::drivers::block::BLOCK_DEVICE; use crate::drivers::block::BLOCK_DEVICE;
...@@ -30,7 +31,7 @@ pub fn device_init() { ...@@ -30,7 +31,7 @@ pub fn device_init() {
plic.set_threshold(hart_id, supervisor, 0); plic.set_threshold(hart_id, supervisor, 0);
plic.set_threshold(hart_id, machine, 1); plic.set_threshold(hart_id, machine, 1);
//irq nums: 5 keyboard, 6 mouse, 8 block, 10 uart //irq nums: 5 keyboard, 6 mouse, 8 block, 10 uart
for intr_src_id in [5usize, 6, 8 , 10] { for intr_src_id in [5usize, 6, 8, 10] {
plic.enable(hart_id, supervisor, intr_src_id); plic.enable(hart_id, supervisor, intr_src_id);
plic.set_priority(intr_src_id, 1); plic.set_priority(intr_src_id, 1);
} }
......
use super::BlockDevice; use super::BlockDevice;
use crate::drivers::bus::virtio::VirtioHal;
use crate::sync::{Condvar, UPIntrFreeCell}; use crate::sync::{Condvar, UPIntrFreeCell};
use crate::task::schedule; use crate::task::schedule;
use crate::DEV_NON_BLOCKING_ACCESS; use crate::DEV_NON_BLOCKING_ACCESS;
use alloc::collections::BTreeMap; use alloc::collections::BTreeMap;
use virtio_drivers::{BlkResp, RespStatus, VirtIOBlk, VirtIOHeader}; use virtio_drivers::{BlkResp, RespStatus, VirtIOBlk, VirtIOHeader};
use crate::drivers::bus::virtio::VirtioHal;
#[allow(unused)] #[allow(unused)]
const VIRTIO0: usize = 0x10008000; const VIRTIO0: usize = 0x10008000;
...@@ -69,7 +69,9 @@ impl BlockDevice for VirtIOBlock { ...@@ -69,7 +69,9 @@ impl BlockDevice for VirtIOBlock {
impl VirtIOBlock { impl VirtIOBlock {
pub fn new() -> Self { pub fn new() -> Self {
let virtio_blk = unsafe { let virtio_blk = unsafe {
UPIntrFreeCell::new(VirtIOBlk::<VirtioHal>::new(&mut *(VIRTIO0 as *mut VirtIOHeader)).unwrap()) UPIntrFreeCell::new(
VirtIOBlk::<VirtioHal>::new(&mut *(VIRTIO0 as *mut VirtIOHeader)).unwrap(),
)
}; };
let mut condvars = BTreeMap::new(); let mut condvars = BTreeMap::new();
let channels = virtio_blk.exclusive_access().virt_queue_size(); let channels = virtio_blk.exclusive_access().virt_queue_size();
...@@ -83,4 +85,3 @@ impl VirtIOBlock { ...@@ -83,4 +85,3 @@ impl VirtIOBlock {
} }
} }
} }
pub mod virtio; pub mod virtio;
\ No newline at end of file
use alloc::vec::Vec;
use crate::mm::{ use crate::mm::{
frame_alloc, frame_dealloc, kernel_token, FrameTracker, PageTable, PhysAddr, PhysPageNum, frame_alloc, frame_dealloc, kernel_token, FrameTracker, PageTable, PhysAddr, PhysPageNum,
StepByOne, VirtAddr, StepByOne, VirtAddr,
}; };
use crate::sync::UPIntrFreeCell; use crate::sync::UPIntrFreeCell;
use alloc::vec::Vec;
use lazy_static::*; use lazy_static::*;
use virtio_drivers::Hal; use virtio_drivers::Hal;
...@@ -49,4 +49,4 @@ impl Hal for VirtioHal { ...@@ -49,4 +49,4 @@ impl Hal for VirtioHal {
.unwrap() .unwrap()
.0 .0
} }
} }
\ No newline at end of file
use crate::drivers::bus::virtio::VirtioHal;
use crate::sync::UPIntrFreeCell; use crate::sync::UPIntrFreeCell;
use alloc::{sync::Arc, vec::Vec}; use alloc::{sync::Arc, vec::Vec};
use core::any::Any; use core::any::Any;
use embedded_graphics::pixelcolor::Rgb888; use embedded_graphics::pixelcolor::Rgb888;
use tinybmp::Bmp; use tinybmp::Bmp;
use virtio_drivers::{VirtIOGpu, VirtIOHeader}; use virtio_drivers::{VirtIOGpu, VirtIOHeader};
use crate::drivers::bus::virtio::VirtioHal;
const VIRTIO7: usize = 0x10007000; const VIRTIO7: usize = 0x10007000;
pub trait GPUDevice: Send + Sync + Any { pub trait GpuDevice: Send + Sync + Any {
fn update_cursor(&self); fn update_cursor(&self);
fn getfreambuffer(&self) -> &mut [u8]; fn get_framebuffer(&self) -> &mut [u8];
fn flush(&self); fn flush(&self);
} }
lazy_static::lazy_static!( lazy_static::lazy_static!(
pub static ref GPU_DEVICE: Arc<dyn GPUDevice> = Arc::new(VirtIOGPU::new()); pub static ref GPU_DEVICE: Arc<dyn GpuDevice> = Arc::new(VirtIOGpuWrapper::new());
); );
pub struct VirtIOGPU { pub struct VirtIOGpuWrapper {
gpu: UPIntrFreeCell<VirtIOGpu<'static, VirtioHal>>, gpu: UPIntrFreeCell<VirtIOGpu<'static, VirtioHal>>,
fb: &'static [u8], fb: &'static [u8],
} }
static BMP_DATA: &[u8] = include_bytes!("../../assert/mouse.bmp"); static BMP_DATA: &[u8] = include_bytes!("../../assert/mouse.bmp");
impl VirtIOGPU { impl VirtIOGpuWrapper {
pub fn new() -> Self { pub fn new() -> Self {
unsafe { unsafe {
let mut virtio = VirtIOGpu::<VirtioHal>::new(&mut *(VIRTIO7 as *mut VirtIOHeader)).unwrap(); let mut virtio =
VirtIOGpu::<VirtioHal>::new(&mut *(VIRTIO7 as *mut VirtIOHeader)).unwrap();
let fbuffer = virtio.setup_framebuffer().unwrap(); let fbuffer = virtio.setup_framebuffer().unwrap();
let len = fbuffer.len(); let len = fbuffer.len();
...@@ -53,11 +54,11 @@ impl VirtIOGPU { ...@@ -53,11 +54,11 @@ impl VirtIOGPU {
} }
} }
impl GPUDevice for VirtIOGPU { impl GpuDevice for VirtIOGpuWrapper {
fn flush(&self) { fn flush(&self) {
self.gpu.exclusive_access().flush().unwrap(); self.gpu.exclusive_access().flush().unwrap();
} }
fn getfreambuffer(&self) -> &mut [u8] { fn get_framebuffer(&self) -> &mut [u8] {
unsafe { unsafe {
let ptr = self.fb.as_ptr() as *const _ as *mut u8; let ptr = self.fb.as_ptr() as *const _ as *mut u8;
core::slice::from_raw_parts_mut(ptr, self.fb.len()) core::slice::from_raw_parts_mut(ptr, self.fb.len())
......
use crate::drivers::bus::virtio::VirtioHal;
use crate::{ use crate::{
gui::{Button, Component}, gui::{move_rect, reset},
sync::UPIntrFreeCell, sync::UPIntrFreeCell,
syscall::PAD,
}; };
use alloc::{string::ToString, sync::Arc}; use alloc::sync::Arc;
use core::any::Any; use core::any::Any;
use embedded_graphics::{
prelude::{Point, Size},
text::Text,
};
use virtio_drivers::{VirtIOHeader, VirtIOInput}; use virtio_drivers::{VirtIOHeader, VirtIOInput};
use crate::drivers::bus::virtio::VirtioHal;
use virtio_input_decoder::{Decoder, Key, KeyType}; use virtio_input_decoder::{Decoder, Key, KeyType};
use super::GPU_DEVICE;
const VIRTIO5: usize = 0x10005000; const VIRTIO5: usize = 0x10005000;
const VIRTIO6: usize = 0x10006000; const VIRTIO6: usize = 0x10006000;
struct VirtIOINPUT(UPIntrFreeCell<VirtIOInput<'static, VirtioHal>>); struct VirtIOInputWrapper(UPIntrFreeCell<VirtIOInput<'static, VirtioHal>>);
pub trait INPUTDevice: Send + Sync + Any { pub trait InputDevice: Send + Sync + Any {
fn handle_irq(&self); fn handle_irq(&self);
} }
lazy_static::lazy_static!( lazy_static::lazy_static!(
pub static ref KEYBOARD_DEVICE: Arc<dyn INPUTDevice> = Arc::new(VirtIOINPUT::new(VIRTIO5)); pub static ref KEYBOARD_DEVICE: Arc<dyn InputDevice> = Arc::new(VirtIOInputWrapper::new(VIRTIO5));
pub static ref MOUSE_DEVICE: Arc<dyn INPUTDevice> = Arc::new(VirtIOINPUT::new(VIRTIO6)); pub static ref MOUSE_DEVICE: Arc<dyn InputDevice> = Arc::new(VirtIOInputWrapper::new(VIRTIO6));
); );
impl VirtIOINPUT { impl VirtIOInputWrapper {
pub fn new(addr: usize) -> Self { pub fn new(addr: usize) -> Self {
Self(unsafe { Self(unsafe {
UPIntrFreeCell::new(VirtIOInput::<VirtioHal>::new(&mut *(addr as *mut VirtIOHeader)).unwrap()) UPIntrFreeCell::new(
VirtIOInput::<VirtioHal>::new(&mut *(addr as *mut VirtIOHeader)).unwrap(),
)
}) })
} }
} }
impl INPUTDevice for VirtIOINPUT { impl InputDevice for VirtIOInputWrapper {
fn handle_irq(&self) { fn handle_irq(&self) {
let mut input = self.0.exclusive_access(); let mut input = self.0.exclusive_access();
input.ack_interrupt(); input.ack_interrupt();
let event = input.pop_pending_event().unwrap(); while let Some(event) = input.pop_pending_event() {
let dtype = match Decoder::decode( let dtype = match Decoder::decode(
event.event_type as usize, event.event_type as usize,
event.code as usize, event.code as usize,
event.value as usize, event.value as usize,
) { ) {
Ok(dtype) => dtype, Ok(dtype) => dtype,
Err(_) => return, Err(_) => break,
}; };
match dtype { match dtype {
virtio_input_decoder::DecodeType::Key(key, r#type) => { virtio_input_decoder::DecodeType::Key(key, r#type) => {
println!("{:?} {:?}", key, r#type); if r#type == KeyType::Press {
if r#type == KeyType::Press { match key {
let mut inner = PAD.exclusive_access(); Key::C | Key::MouseLeft => {
let a = inner.as_ref().unwrap(); reset();
match key.to_char() { }
Ok(mut k) => { Key::W => {
if k == '\r' { move_rect(0, -10);
a.repaint(k.to_string() + "\n") }
} else { Key::S => {
a.repaint(k.to_string()) move_rect(0, 10);
}
Key::A => {
move_rect(-10, 0);
}
Key::D => {
move_rect(10, 0);
} }
_ => {}
} }
Err(_) => {}
} }
} }
_ => {}
} }
virtio_input_decoder::DecodeType::Mouse(mouse) => println!("{:?}", mouse),
} }
} }
} }
pub mod block; pub mod block;
pub mod bus;
pub mod chardev; pub mod chardev;
pub mod gpu; pub mod gpu;
pub mod input; pub mod input;
pub mod bus;
pub mod plic; pub mod plic;
pub use block::BLOCK_DEVICE; pub use block::BLOCK_DEVICE;
pub use bus::*;
pub use chardev::UART; pub use chardev::UART;
pub use gpu::*; pub use gpu::*;
pub use input::*; pub use input::*;
pub use bus::*;
use alloc::{string::String, sync::Arc};
use embedded_graphics::{
mono_font::{
ascii::{FONT_10X20, FONT_6X10},
MonoTextStyle,
},
pixelcolor::Rgb888,
prelude::{Dimensions, Point, Primitive, RgbColor, Size},
primitives::{PrimitiveStyle, Rectangle},
text::{Alignment, Text},
Drawable,
};
use crate::{drivers::GPU_DEVICE, sync::UPIntrFreeCell};
use super::{Component, Graphics};
pub struct Button {
inner: UPIntrFreeCell<ButtonInner>,
}
pub struct ButtonInner {
graphic: Graphics,
text: String,
parent: Option<Arc<dyn Component>>,
}
impl Button {
pub fn new(size: Size, point: Point, parent: Option<Arc<dyn Component>>, text: String) -> Self {
let point = match &parent {
Some(p) => {
let (_, p) = p.bound();
Point::new(p.x + point.x, p.y + point.y)
}
None => point,
};
Self {
inner: unsafe {
UPIntrFreeCell::new(ButtonInner {
graphic: Graphics {
size,
point,
drv: GPU_DEVICE.clone(),
},
text,
parent,
})
},
}
}
}
impl Component for Button {
fn paint(&self) {
let mut inner = self.inner.exclusive_access();
let text = inner.text.clone();
Text::with_alignment(
text.as_str(),
inner.graphic.bounding_box().center(),
MonoTextStyle::new(&FONT_10X20, Rgb888::BLACK),
Alignment::Center,
)
.draw(&mut inner.graphic);
}
fn add(&self, comp: alloc::sync::Arc<dyn Component>) {
unreachable!()
}
fn bound(
&self,
) -> (
embedded_graphics::prelude::Size,
embedded_graphics::prelude::Point,
) {
let inner = self.inner.exclusive_access();
(inner.graphic.size, inner.graphic.point)
}
}
...@@ -5,14 +5,14 @@ use embedded_graphics::{ ...@@ -5,14 +5,14 @@ use embedded_graphics::{
prelude::{OriginDimensions, Point, RgbColor, Size}, prelude::{OriginDimensions, Point, RgbColor, Size},
}; };
use crate::drivers::{GPUDevice, GPU_DEVICE,}; use crate::board::VIRTGPU_XRES;
use crate::board::{VIRTGPU_XRES, VIRTGPU_YRES}; use crate::drivers::{GpuDevice, GPU_DEVICE};
#[derive(Clone)] #[derive(Clone)]
pub struct Graphics { pub struct Graphics {
pub size: Size, pub size: Size,
pub point: Point, pub point: Point,
pub drv: Arc<dyn GPUDevice>, pub drv: Arc<dyn GpuDevice>,
} }
impl Graphics { impl Graphics {
...@@ -23,6 +23,10 @@ impl Graphics { ...@@ -23,6 +23,10 @@ impl Graphics {
drv: GPU_DEVICE.clone(), drv: GPU_DEVICE.clone(),
} }
} }
pub fn reset(&self) {
let fb = self.drv.get_framebuffer();
fb.fill(0u8);
}
} }
impl OriginDimensions for Graphics { impl OriginDimensions for Graphics {
...@@ -40,10 +44,12 @@ impl DrawTarget for Graphics { ...@@ -40,10 +44,12 @@ impl DrawTarget for Graphics {
where where
I: IntoIterator<Item = embedded_graphics::Pixel<Self::Color>>, I: IntoIterator<Item = embedded_graphics::Pixel<Self::Color>>,
{ {
let fb = self.drv.getfreambuffer(); let fb = self.drv.get_framebuffer();
pixels.into_iter().for_each(|px| { 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; let idx = ((self.point.y + px.0.y) * VIRTGPU_XRES as i32 + self.point.x + px.0.x)
as usize
* 4;
if idx + 2 >= fb.len() { if idx + 2 >= fb.len() {
return; return;
} }
......
use alloc::{string::String, sync::Arc, vec::Vec};
use embedded_graphics::{
image::Image,
mono_font::{ascii::FONT_10X20, iso_8859_13::FONT_6X12, MonoTextStyle},
pixelcolor::Rgb888,
prelude::{Point, RgbColor, Size},
text::Text,
Drawable,
};
use tinybmp::Bmp;
use crate::{drivers::GPU_DEVICE, sync::UPIntrFreeCell};
use crate::board::{VIRTGPU_XRES, VIRTGPU_YRES};
use super::{Component, Graphics, ImageComp};
static FILEICON: &[u8] = include_bytes!("../assert/file.bmp");
pub struct IconController {
inner: UPIntrFreeCell<IconControllerInner>,
}
pub struct IconControllerInner {
files: Vec<String>,
graphic: Graphics,
parent: Option<Arc<dyn Component>>,
}
impl IconController {
pub fn new(files: Vec<String>, parent: Option<Arc<dyn Component>>) -> Self {
IconController {
inner: unsafe {
UPIntrFreeCell::new(IconControllerInner {
files,
graphic: Graphics {
size: Size::new(VIRTGPU_XRES, VIRTGPU_YRES),
point: Point::new(0, 0),
drv: GPU_DEVICE.clone(),
},
parent,
})
},
}
}
}
impl Component for IconController {
fn paint(&self) {
println!("demo");
let mut inner = self.inner.exclusive_access();
let mut x = 10;
let mut y = 10;
let v = inner.files.clone();
for file in v {
println!("file");
let bmp = Bmp::<Rgb888>::from_slice(FILEICON).unwrap();
Image::new(&bmp, Point::new(x, y)).draw(&mut inner.graphic);
let text = Text::new(
file.as_str(),
Point::new(x + 20, y + 80),
MonoTextStyle::new(&FONT_10X20, Rgb888::BLACK),
);
text.draw(&mut inner.graphic);
if y >= 600 {
x = x + 70;
y = 10;
} else {
y = y + 90;
}
}
}
fn add(&self, comp: Arc<dyn Component>) {
todo!()
}
fn bound(&self) -> (Size, Point) {
todo!()
}
}
use alloc::{sync::Arc, vec::Vec};
use embedded_graphics::{
image::Image,
pixelcolor::Rgb888,
prelude::{Point, Size},
Drawable,
};
use tinybmp::Bmp;
use crate::{
drivers::{BLOCK_DEVICE, GPU_DEVICE},
sync::UPIntrFreeCell,
};
use super::{Component, Graphics};
pub struct ImageComp {
inner: UPIntrFreeCell<ImageInner>,
}
pub struct ImageInner {
image: &'static [u8],
graphic: Graphics,
parent: Option<Arc<dyn Component>>,
}
impl ImageComp {
pub fn new(
size: Size,
point: Point,
v: &'static [u8],
parent: Option<Arc<dyn Component>>,
) -> Self {
unsafe {
ImageComp {
inner: UPIntrFreeCell::new(ImageInner {
parent,
image: v,
graphic: Graphics {
size,
point,
drv: GPU_DEVICE.clone(),
},
}),
}
}
}
}
impl Component for ImageComp {
fn paint(&self) {
let mut inner = self.inner.exclusive_access();
let b = unsafe {
let len = inner.image.len();
let ptr = inner.image.as_ptr() as *const u8;
core::slice::from_raw_parts(ptr, len)
};
let bmp = Bmp::<Rgb888>::from_slice(b).unwrap();
let point = match &inner.parent {
Some(parent) => {
let (_, point) = parent.bound();
Point::new(
point.x + inner.graphic.point.x,
point.y + inner.graphic.point.y,
)
}
None => inner.graphic.point,
};
Image::new(&bmp, point).draw(&mut inner.graphic);
}
fn add(&self, comp: alloc::sync::Arc<dyn Component>) {
todo!()
}
fn bound(&self) -> (Size, Point) {
let inner = self.inner.exclusive_access();
(inner.graphic.size, inner.graphic.point)
}
}
mod button;
mod graphic; mod graphic;
mod icon; mod paint;
mod image;
mod panel;
mod terminal;
use alloc::sync::Arc; use graphic::Graphics;
pub use button::*; pub use paint::{init_paint, move_rect, reset};
use core::any::Any;
use embedded_graphics::prelude::{Point, Size};
pub use graphic::*;
pub use icon::*;
pub use image::*;
pub use panel::*;
pub use terminal::*;
pub trait Component: Send + Sync + Any {
fn paint(&self);
fn add(&self, comp: Arc<dyn Component>);
fn bound(&self) -> (Size, Point);
}
use super::Graphics;
use crate::sync::UPIntrFreeCell;
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 lazy_static::*;
const INIT_X: i32 = 640;
const INIT_Y: i32 = 400;
const RECT_SIZE: u32 = 40;
pub struct DrawingBoard {
graphics: Graphics,
latest_pos: Point,
}
impl DrawingBoard {
pub fn new() -> Self {
Self {
graphics: Graphics::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.graphics)
.ok();
}
pub fn move_rect(&mut self, dx: i32, dy: i32) {
self.latest_pos.x += dx;
self.latest_pos.y += dy;
self.paint();
}
pub fn reset(&mut self) {
self.latest_pos = Point::new(INIT_X, INIT_Y);
self.graphics.reset();
}
}
lazy_static! {
pub static ref DRAWING_BOARD: UPIntrFreeCell<DrawingBoard> = unsafe { UPIntrFreeCell::new(DrawingBoard::new()) };
}
pub fn init_paint() {
DRAWING_BOARD.exclusive_session(|ripple| {
ripple.paint();
});
}
pub fn move_rect(dx: i32, dy: i32) {
DRAWING_BOARD.exclusive_session(|ripple| {
ripple.move_rect(dx, dy);
});
}
pub fn reset() {
DRAWING_BOARD.exclusive_session(|ripple| {
ripple.reset();
});
}
use alloc::{collections::VecDeque, rc::Weak, sync::Arc};
use embedded_graphics::{
pixelcolor::Rgb888,
prelude::{Point, Primitive, RgbColor, Size},
primitives::{PrimitiveStyle, Rectangle},
Drawable,
};
use crate::{drivers::GPU_DEVICE, sync::UPIntrFreeCell};
use super::{Component, Graphics};
pub struct Panel {
inner: UPIntrFreeCell<PanelInner>,
}
struct PanelInner {
graphic: Graphics,
comps: VecDeque<Arc<dyn Component>>,
}
impl Panel {
pub fn new(size: Size, point: Point) -> Self {
Self {
inner: unsafe {
UPIntrFreeCell::new(PanelInner {
graphic: Graphics {
size,
point,
drv: GPU_DEVICE.clone(),
},
comps: VecDeque::new(),
})
},
}
}
}
impl Component for Panel {
fn paint(&self) {
let mut inner = self.inner.exclusive_access();
Rectangle::new(Point::new(0, 0), inner.graphic.size)
.into_styled(PrimitiveStyle::with_fill(Rgb888::WHITE))
.draw(&mut inner.graphic)
.unwrap();
let len = inner.comps.len();
drop(inner);
for i in 0..len {
let mut inner = self.inner.exclusive_access();
let comp = Arc::downgrade(&inner.comps[i]);
drop(inner);
comp.upgrade().unwrap().paint();
}
}
fn add(&self, comp: alloc::sync::Arc<dyn Component>) {
let mut inner = self.inner.exclusive_access();
inner.comps.push_back(comp);
}
fn bound(&self) -> (Size, Point) {
let inner = self.inner.exclusive_access();
(inner.graphic.size, inner.graphic.point)
}
}
use alloc::{
collections::VecDeque,
string::{String, ToString},
sync::Arc,
};
use embedded_graphics::{
mono_font::{ascii::FONT_10X20, MonoTextStyle},
pixelcolor::Rgb888,
prelude::{Dimensions, Point, Primitive, RgbColor, Size},
primitives::{PrimitiveStyle, Rectangle},
text::{Alignment, Text},
Drawable,
};
use crate::{drivers::GPU_DEVICE, sync::UPIntrFreeCell};
use super::{button::Button, Component, Graphics, Panel};
pub struct Terminal {
inner: UPIntrFreeCell<TerminalInner>,
}
pub struct TerminalInner {
pub text: String,
titel: Option<String>,
graphic: Graphics,
comps: VecDeque<Arc<dyn Component>>,
}
impl Terminal {
pub fn new(
size: Size,
point: Point,
parent: Option<Arc<dyn Component>>,
titel: Option<String>,
text: String,
) -> Self {
Self {
inner: unsafe {
UPIntrFreeCell::new(TerminalInner {
text,
titel,
graphic: Graphics {
size,
point,
drv: GPU_DEVICE.clone(),
},
comps: VecDeque::new(),
})
},
}
}
pub fn repaint(&self, text: String) {
let mut inner = self.inner.exclusive_access();
inner.text += text.as_str();
Text::with_alignment(
inner.text.clone().as_str(),
Point::new(20, 50),
MonoTextStyle::new(&FONT_10X20, Rgb888::BLACK),
Alignment::Left,
)
.draw(&mut inner.graphic);
}
}
impl Component for Terminal {
fn paint(&self) {
let mut inner = self.inner.exclusive_access();
let len = inner.comps.len();
drop(inner);
for i in 0..len {
let mut inner = self.inner.exclusive_access();
let comp = Arc::downgrade(&inner.comps[i]);
drop(inner);
comp.upgrade().unwrap().paint();
}
let mut inner = self.inner.exclusive_access();
let titel = inner.titel.get_or_insert("No Titel".to_string()).clone();
let text = Text::new(
titel.as_str(),
Point::new(20, 20),
MonoTextStyle::new(&FONT_10X20, Rgb888::BLACK),
);
text.draw(&mut inner.graphic);
Text::with_alignment(
inner.text.clone().as_str(),
Point::new(20, 50),
MonoTextStyle::new(&FONT_10X20, Rgb888::BLACK),
Alignment::Left,
)
.draw(&mut inner.graphic);
}
fn add(&self, comp: Arc<dyn Component>) {
let mut inner = self.inner.exclusive_access();
inner.comps.push_back(comp);
}
fn bound(&self) -> (Size, Point) {
let inner = self.inner.exclusive_access();
(inner.graphic.size, inner.graphic.point)
}
}
...@@ -28,7 +28,7 @@ mod task; ...@@ -28,7 +28,7 @@ mod task;
mod timer; mod timer;
mod trap; mod trap;
// use syscall::create_desktop; //for test //use syscall::create_desktop; //for test
core::arch::global_asm!(include_str!("entry.asm")); core::arch::global_asm!(include_str!("entry.asm"));
...@@ -56,18 +56,18 @@ pub fn rust_main() -> ! { ...@@ -56,18 +56,18 @@ pub fn rust_main() -> ! {
clear_bss(); clear_bss();
mm::init(); mm::init();
println!("KERN: init gpu"); println!("KERN: init gpu");
GPU_DEVICE.clone(); let _gpu = GPU_DEVICE.clone();
println!("KERN: init keyboard"); println!("KERN: init keyboard");
KEYBOARD_DEVICE.clone(); let _keyboard = KEYBOARD_DEVICE.clone();
println!("KERN: init mouse"); println!("KERN: init mouse");
MOUSE_DEVICE.clone(); let _mouse = MOUSE_DEVICE.clone();
println!("KERN: init trap"); println!("KERN: init trap");
trap::init(); trap::init();
trap::enable_timer_interrupt(); trap::enable_timer_interrupt();
timer::set_next_trigger(); timer::set_next_trigger();
board::device_init(); board::device_init();
fs::list_apps(); fs::list_apps();
//syscall::create_desktop(); //for test gui::init_paint();
task::add_initproc(); task::add_initproc();
*DEV_NON_BLOCKING_ACCESS.exclusive_access() = true; *DEV_NON_BLOCKING_ACCESS.exclusive_access() = true;
task::run_tasks(); task::run_tasks();
......
...@@ -48,7 +48,7 @@ impl StackFrameAllocator { ...@@ -48,7 +48,7 @@ impl StackFrameAllocator {
pub fn init(&mut self, l: PhysPageNum, r: PhysPageNum) { pub fn init(&mut self, l: PhysPageNum, r: PhysPageNum) {
self.current = l.0; self.current = l.0;
self.end = r.0; self.end = r.0;
println!("last {} Physical Frames.", self.end - self.current); // println!("last {} Physical Frames.", self.end - self.current);
} }
} }
impl FrameAllocator for StackFrameAllocator { impl FrameAllocator for StackFrameAllocator {
......
...@@ -92,14 +92,14 @@ impl MemorySet { ...@@ -92,14 +92,14 @@ impl MemorySet {
// map trampoline // map trampoline
memory_set.map_trampoline(); memory_set.map_trampoline();
// map kernel sections // map kernel sections
println!(".text [{:#x}, {:#x})", stext as usize, etext as usize); // println!(".text [{:#x}, {:#x})", stext as usize, etext as usize);
println!(".rodata [{:#x}, {:#x})", srodata as usize, erodata as usize); // println!(".rodata [{:#x}, {:#x})", srodata as usize, erodata as usize);
println!(".data [{:#x}, {:#x})", sdata as usize, edata as usize); // println!(".data [{:#x}, {:#x})", sdata as usize, edata as usize);
println!( // println!(
".bss [{:#x}, {:#x})", // ".bss [{:#x}, {:#x})",
sbss_with_stack as usize, ebss as usize // sbss_with_stack as usize, ebss as usize
); // );
println!("mapping .text section"); // println!("mapping .text section");
memory_set.push( memory_set.push(
MapArea::new( MapArea::new(
(stext as usize).into(), (stext as usize).into(),
...@@ -109,7 +109,7 @@ impl MemorySet { ...@@ -109,7 +109,7 @@ impl MemorySet {
), ),
None, None,
); );
println!("mapping .rodata section"); // println!("mapping .rodata section");
memory_set.push( memory_set.push(
MapArea::new( MapArea::new(
(srodata as usize).into(), (srodata as usize).into(),
...@@ -119,7 +119,7 @@ impl MemorySet { ...@@ -119,7 +119,7 @@ impl MemorySet {
), ),
None, None,
); );
println!("mapping .data section"); // println!("mapping .data section");
memory_set.push( memory_set.push(
MapArea::new( MapArea::new(
(sdata as usize).into(), (sdata as usize).into(),
...@@ -129,7 +129,7 @@ impl MemorySet { ...@@ -129,7 +129,7 @@ impl MemorySet {
), ),
None, None,
); );
println!("mapping .bss section"); // println!("mapping .bss section");
memory_set.push( memory_set.push(
MapArea::new( MapArea::new(
(sbss_with_stack as usize).into(), (sbss_with_stack as usize).into(),
...@@ -139,7 +139,7 @@ impl MemorySet { ...@@ -139,7 +139,7 @@ impl MemorySet {
), ),
None, None,
); );
println!("mapping physical memory"); // println!("mapping physical memory");
memory_set.push( memory_set.push(
MapArea::new( MapArea::new(
(ekernel as usize).into(), (ekernel as usize).into(),
...@@ -149,7 +149,7 @@ impl MemorySet { ...@@ -149,7 +149,7 @@ impl MemorySet {
), ),
None, None,
); );
println!("mapping memory-mapped registers"); //println!("mapping memory-mapped registers");
for pair in MMIO { for pair in MMIO {
memory_set.push( memory_set.push(
MapArea::new( MapArea::new(
......
use alloc::{string::ToString, sync::Arc, vec::Vec};
use embedded_graphics::{
prelude::{Point, Size},
primitives::arc,
};
use crate::{
fs::ROOT_INODE,
gui::{Button, Component, IconController, ImageComp, Panel, Terminal},
sync::UPIntrFreeCell,
};
use crate::board::{VIRTGPU_XRES, VIRTGPU_YRES};
static DT: &[u8] = include_bytes!("../assert/desktop.bmp");
lazy_static::lazy_static!(
pub static ref DESKTOP:UPIntrFreeCell<Arc<dyn Component>> = unsafe {
UPIntrFreeCell::new(Arc::new(Panel::new(Size::new(VIRTGPU_XRES, VIRTGPU_YRES), Point::new(0, 0))))
};
pub static ref PAD:UPIntrFreeCell<Option<Arc<Terminal>>> = unsafe {
UPIntrFreeCell::new(None)
};
);
pub fn create_desktop() -> isize {
let mut p: Arc<dyn Component + 'static> =
Arc::new(Panel::new(Size::new(VIRTGPU_XRES, VIRTGPU_YRES), Point::new(0, 0)));
let image = ImageComp::new(Size::new(VIRTGPU_XRES, VIRTGPU_YRES), Point::new(0, 0), DT, Some(p.clone()));
let icon = IconController::new(ROOT_INODE.ls(), Some(p.clone()));
p.add(Arc::new(image));
p.add(Arc::new(icon));
let mut desktop = DESKTOP.exclusive_access();
*desktop = p;
desktop.paint();
drop(desktop);
create_terminal();
1
}
pub fn create_terminal() {
let desktop = DESKTOP.exclusive_access();
let arc_t = Arc::new(Terminal::new(
Size::new(400, 400),
Point::new(200, 100),
Some(desktop.clone()),
Some("demo.txt".to_string()),
"".to_string(),
));
let text = Panel::new(Size::new(400, 400), Point::new(200, 100));
let button = Button::new(
Size::new(20, 20),
Point::new(370, 10),
Some(arc_t.clone()),
"X".to_string(),
);
arc_t.add(Arc::new(text));
arc_t.add(Arc::new(button));
arc_t.paint();
desktop.add(arc_t.clone());
let mut pad = PAD.exclusive_access();
*pad = Some(arc_t);
}
...@@ -25,16 +25,13 @@ const SYSCALL_SEMAPHORE_DOWN: usize = 1022; ...@@ -25,16 +25,13 @@ const SYSCALL_SEMAPHORE_DOWN: usize = 1022;
const SYSCALL_CONDVAR_CREATE: usize = 1030; const SYSCALL_CONDVAR_CREATE: usize = 1030;
const SYSCALL_CONDVAR_SIGNAL: usize = 1031; const SYSCALL_CONDVAR_SIGNAL: usize = 1031;
const SYSCALL_CONDVAR_WAIT: usize = 1032; const SYSCALL_CONDVAR_WAIT: usize = 1032;
const SYSCALL_CREATE_DESKTOP: usize = 2000;
mod fs; mod fs;
mod gui;
mod process; mod process;
mod sync; mod sync;
mod thread; mod thread;
pub use self::gui::create_desktop;
use fs::*;
pub use gui::PAD; use fs::*;
use process::*; use process::*;
use sync::*; use sync::*;
use thread::*; use thread::*;
...@@ -68,8 +65,6 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { ...@@ -68,8 +65,6 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
SYSCALL_CONDVAR_CREATE => sys_condvar_create(args[0]), SYSCALL_CONDVAR_CREATE => sys_condvar_create(args[0]),
SYSCALL_CONDVAR_SIGNAL => sys_condvar_signal(args[0]), SYSCALL_CONDVAR_SIGNAL => sys_condvar_signal(args[0]),
SYSCALL_CONDVAR_WAIT => sys_condvar_wait(args[0], args[1]), SYSCALL_CONDVAR_WAIT => sys_condvar_wait(args[0], args[1]),
SYSCALL_CREATE_DESKTOP => create_desktop(),
_ => panic!("Unsupported syscall_id: {}", syscall_id), _ => panic!("Unsupported syscall_id: {}", syscall_id),
} }
} }
...@@ -61,13 +61,14 @@ pub fn add_timer(expire_ms: usize, task: Arc<TaskControlBlock>) { ...@@ -61,13 +61,14 @@ pub fn add_timer(expire_ms: usize, task: Arc<TaskControlBlock>) {
pub fn check_timer() { pub fn check_timer() {
let current_ms = get_time_ms(); let current_ms = get_time_ms();
let mut timers = TIMERS.exclusive_access(); TIMERS.exclusive_session(|timers| {
while let Some(timer) = timers.peek() { while let Some(timer) = timers.peek() {
if timer.expire_ms <= current_ms { if timer.expire_ms <= current_ms {
add_task(Arc::clone(&timer.task)); add_task(Arc::clone(&timer.task));
timers.pop(); timers.pop();
} else { } else {
break; break;
}
} }
} });
} }
...@@ -61,7 +61,7 @@ pub fn trap_handler() -> ! { ...@@ -61,7 +61,7 @@ pub fn trap_handler() -> ! {
set_kernel_trap_entry(); set_kernel_trap_entry();
let scause = scause::read(); let scause = scause::read();
let stval = stval::read(); let stval = stval::read();
//println!("into {:?}", scause.cause()); // println!("into {:?}", scause.cause());
match scause.cause() { match scause.cause() {
Trap::Exception(Exception::UserEnvCall) => { Trap::Exception(Exception::UserEnvCall) => {
// jump to next instruction anyway // jump to next instruction anyway
......
#![no_std]
#![no_main]
use user_lib::create_desktop;
#[macro_use]
extern crate user_lib;
#[no_mangle]
pub fn main() -> i32 {
println!("gui");
create_desktop();
println!("exit pass.");
loop{}
0
}
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
extern crate user_lib; extern crate user_lib;
extern crate alloc; extern crate alloc;
use alloc::{fmt::format, string::String, vec::Vec}; use alloc::{fmt::format, vec::Vec};
use user_lib::{close, get_time, gettid, open, write, OpenFlags}; use user_lib::{close, get_time, gettid, open, write, OpenFlags};
use user_lib::{exit, thread_create, waittid}; use user_lib::{exit, thread_create, waittid};
......
#![no_std] #![no_std]
#![no_main] #![no_main]
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
#![feature(asm)]
#[macro_use] #[macro_use]
extern crate user_lib; extern crate user_lib;
......
...@@ -198,9 +198,7 @@ pub fn condvar_signal(condvar_id: usize) { ...@@ -198,9 +198,7 @@ pub fn condvar_signal(condvar_id: usize) {
pub fn condvar_wait(condvar_id: usize, mutex_id: usize) { pub fn condvar_wait(condvar_id: usize, mutex_id: usize) {
sys_condvar_wait(condvar_id, mutex_id); sys_condvar_wait(condvar_id, mutex_id);
} }
pub fn create_desktop() {
sys_create_desktop();
}
#[macro_export] #[macro_export]
macro_rules! vstore { macro_rules! vstore {
($var_ref: expr, $value: expr) => { ($var_ref: expr, $value: expr) => {
......
...@@ -154,6 +154,3 @@ pub fn sys_condvar_signal(condvar_id: usize) -> isize { ...@@ -154,6 +154,3 @@ pub fn sys_condvar_signal(condvar_id: usize) -> isize {
pub fn sys_condvar_wait(condvar_id: usize, mutex_id: usize) -> isize { pub fn sys_condvar_wait(condvar_id: usize, mutex_id: usize) -> isize {
syscall(SYSCALL_CONDVAR_WAIT, [condvar_id, mutex_id, 0]) syscall(SYSCALL_CONDVAR_WAIT, [condvar_id, mutex_id, 0])
} }
pub fn sys_create_desktop() -> isize {
syscall(2000, [0, 0, 0])
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册