From 293e03e5005ecdaf7a70b63faf6d8a61a3fc5fa9 Mon Sep 17 00:00:00 2001 From: chlorospingus Date: Sun, 27 Apr 2025 01:12:29 -0700 Subject: [PATCH] Graphics namespace includes rectangle, rounded rectangle, and circle Also added methods to make writing to shm pool easier --- src/graphics/mod.rs | 2 ++ src/graphics/rectangle.rs | 43 +++++++++++++++++++++++++++++++++++++++ src/main.rs | 1 + src/wayland/shm.rs | 40 ++++++++++++++++++++++++++---------- src/wayland/wl_shm.rs | 7 +++++-- 5 files changed, 80 insertions(+), 13 deletions(-) create mode 100644 src/graphics/mod.rs create mode 100644 src/graphics/rectangle.rs diff --git a/src/graphics/mod.rs b/src/graphics/mod.rs new file mode 100644 index 0000000..5b2aff3 --- /dev/null +++ b/src/graphics/mod.rs @@ -0,0 +1,2 @@ + +pub mod rectangle; diff --git a/src/graphics/rectangle.rs b/src/graphics/rectangle.rs new file mode 100644 index 0000000..b790d3a --- /dev/null +++ b/src/graphics/rectangle.rs @@ -0,0 +1,43 @@ + +use crate::wayland::shm::ShmPool; + +// l_row means local row and g_row means global row +impl ShmPool { + + // x and y are topleft corner of rect + pub fn rectangle(&mut self, x: usize, y: usize, w: usize, h: usize, color: u32) { + for g_row in y..y+h { + self.write(&vec![color; w], g_row*self.width+x); + } + } + + // x and y and topleft corner of rect + pub fn rounded_rectangle( + &mut self, + x: usize, + y: usize, + w: usize, + h: usize, + radius: usize, + color: u32 + ) { + for l_row in 0..radius+1 { + let x_diff = radius - ((radius*radius - l_row*l_row) as f64).sqrt() as usize; + self.write(&vec![color; w - (2*x_diff)], (y+radius-l_row)*self.width + x + x_diff); + self.write(&vec![color; w - (2*x_diff)], (y+h-radius+l_row)*self.width + x + x_diff); + } + for g_row in y+radius..y+h-radius { + self.write(&vec![color; w], g_row*self.width+x); + } + } + + // x and y are center of circle + pub fn circle(&mut self, x: usize, y: usize, radius: usize, color: u32) { + for l_row in 0..radius { + let x_diff = ((radius*radius - l_row*l_row) as f64).sqrt(); + let mut row: Vec = vec![color; 2*x_diff as usize]; + self.write(&row, (y+l_row)*self.width + x - x_diff as usize); + self.write(&row, (y-l_row)*self.width + x - x_diff as usize); + } + } +} diff --git a/src/main.rs b/src/main.rs index 4c47391..3011346 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ use std::error::Error; mod wayland; use wayland::wl_client::WlClient; +mod graphics; fn main() -> Result<(), Box> { let mut wl_client = WlClient::new()?; diff --git a/src/wayland/shm.rs b/src/wayland/shm.rs index 28ca335..2e499ed 100644 --- a/src/wayland/shm.rs +++ b/src/wayland/shm.rs @@ -2,14 +2,17 @@ use libc::{c_void, ftruncate, mmap, munmap, shm_open, shm_unlink, MAP_FAILED, MA #[derive(Clone)] pub struct ShmPool { - pub fd: i32, - pub id: u32, - pub addr: *mut c_void, - pub size: usize, + pub fd: i32, + pub id: u32, + pub addr: *mut c_void, + pub size: usize, + pub width: usize, } impl ShmPool { - pub fn new(size: usize, id: u32) -> std::io::Result { + pub fn new(width: usize, height: usize, id: u32) -> std::io::Result { + let size = width * height * 4; + let shm_path: *const i8 = b"/chlorostart\0".as_ptr() as *const i8; let fd = unsafe { shm_open(shm_path, O_RDWR | O_EXCL | O_CREAT, 0o600) }; if fd == -1 { @@ -37,7 +40,8 @@ impl ShmPool { fd, id, addr, - size + size, + width, }) } @@ -50,17 +54,31 @@ impl ShmPool { Ok(()) } - pub fn write(&mut self, data: &Vec, offset: isize) -> std::io::Result<()> { - // TODO: Bounds check + pub fn write(&mut self, data: &Vec, offset: usize) { + if offset > self.size { + return; + } unsafe { std::ptr::copy_nonoverlapping( data.as_ptr() as *const u32, // src: data as *const u32 - self.addr.offset(offset*4) as *mut u32, // dst: ShmPool address as *mut u32 - data.len() + self.addr.offset(4*offset as isize) as *mut u32, // dst: ShmPool address as *mut u32 + if offset + data.len() * 4 <= self.size { + data.len() + } else { + data.len() - offset + } ); } + } - Ok(()) + pub fn write_pixel(&mut self, data: u32, offset: isize) { + // TODO: Bounds check + unsafe {*(self.addr.offset(offset*4) as *mut u32) = data;} + } + + pub fn read_pixel(&self, offset: usize) -> u32 { + // TODO: Bounds check + return unsafe {*(self.addr.offset(4*offset as isize) as *const u32)}; } } diff --git a/src/wayland/wl_shm.rs b/src/wayland/wl_shm.rs index dc3df8a..85ea468 100644 --- a/src/wayland/wl_shm.rs +++ b/src/wayland/wl_shm.rs @@ -11,8 +11,11 @@ impl WlClient { pub fn wl_shm_create_pool(&mut self, width: usize, height: usize) -> Result<(), Box> { self.current_id += 1; - self.shm_pool = Some(shm::ShmPool::new(width * height * STRIDE, self.current_id)?); - self.shm_pool.as_mut().unwrap().write(&vec![0xffff0000; width * height], 0)?; + self.shm_pool = Some(shm::ShmPool::new(width, height, self.current_id)?); + self.shm_pool.as_mut().unwrap().write(&vec![0xffff0000; width * height], 0); + self.shm_pool.as_mut().unwrap().rectangle(50, 50, 50, 50, 0xff00ff00); + self.shm_pool.as_mut().unwrap().circle(200, 200, 50, 0xff0000ff); + self.shm_pool.as_mut().unwrap().rounded_rectangle(400, 200, 200, 100, 14, 0xffffff00); let object = self.shm_id.ok_or(UnsetErr("shm_id".to_string()))?; const OPCODE: u16 = 0;