From 375b44beee6acf6ad4e1c394d0dd98b1a2fdda1b Mon Sep 17 00:00:00 2001 From: chlorospingus Date: Tue, 6 May 2025 11:57:35 -0700 Subject: [PATCH] current_id, registry_id, and ShmPool are atomic --- src/main.rs | 10 ------ src/wayland/layer_shell.rs | 8 ++--- src/wayland/shm.rs | 3 ++ src/wayland/surface.rs | 8 ++--- src/wayland/wl_client.rs | 62 +++++++++++++++----------------------- src/wayland/wl_registry.rs | 54 ++++++++++++++------------------- src/wayland/wl_shm.rs | 29 +++++++++--------- 7 files changed, 73 insertions(+), 101 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3011346..c762ad9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,15 +8,5 @@ mod graphics; fn main() -> Result<(), Box> { let mut wl_client = WlClient::new()?; - wl_client.wl_display_get_registry()?; - - loop { - wl_client.read_event()?; - - if false { - break - } - } - Ok(()) } diff --git a/src/wayland/layer_shell.rs b/src/wayland/layer_shell.rs index d12d3e6..54c0944 100644 --- a/src/wayland/layer_shell.rs +++ b/src/wayland/layer_shell.rs @@ -1,4 +1,4 @@ -use std::{error::Error, io::Write}; +use std::{error::Error, io::Write, sync::atomic::Ordering}; use crate::wayland::{vec_utils::WlMessage, wl_client::WlClient}; const NAMESPACE: &str = "chlorostart"; @@ -19,15 +19,15 @@ impl WlClient { request.write_u16(&OPCODE, &mut offset); request.write_u16(&msg_size, &mut offset); - self.current_id += 1; - request.write_u32(&self.current_id, &mut offset); - self.layer_surface_id = Some(self.current_id); + let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1; + request.write_u32(¤t_id, &mut offset); request.write_u32(&self.surface_id.unwrap(), &mut offset); request.write_u32(&output, &mut offset); request.write_u32(&OVERLAY, &mut offset); request.write_string(&NAMESPACE.to_string(), &mut offset); self.socket.write(&request)?; + self.layer_surface_id = Some(current_id); Ok(()) } diff --git a/src/wayland/shm.rs b/src/wayland/shm.rs index 2e499ed..3309585 100644 --- a/src/wayland/shm.rs +++ b/src/wayland/shm.rs @@ -87,3 +87,6 @@ impl Drop for ShmPool { unsafe { munmap(self.addr, self.size); } } } + +unsafe impl Send for ShmPool {} +unsafe impl Sync for ShmPool {} diff --git a/src/wayland/surface.rs b/src/wayland/surface.rs index 224cf28..e305281 100644 --- a/src/wayland/surface.rs +++ b/src/wayland/surface.rs @@ -1,4 +1,4 @@ -use std::{error::Error, io::Write}; +use std::{error::Error, io::Write, sync::atomic::Ordering}; use crate::wayland::{vec_utils::WlMessage, wl_client::WlClient}; @@ -31,12 +31,12 @@ impl WlClient { request.write_u16(&OPCODE, &mut offset); request.write_u16(&MSG_SIZE, &mut offset); - self.current_id += 1; - request.write_u32(&self.current_id, &mut offset); + let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1; + request.write_u32(¤t_id, &mut offset); self.socket.write(&request)?; - self.surface_id = Some(self.current_id); + self.surface_id = Some(current_id); Ok(()) } diff --git a/src/wayland/wl_client.rs b/src/wayland/wl_client.rs index 54c685b..9179de3 100644 --- a/src/wayland/wl_client.rs +++ b/src/wayland/wl_client.rs @@ -1,4 +1,4 @@ -use std::{env::var, error::Error, fmt::Debug, io::Read, os::unix::net::UnixStream, u32}; +use std::{env::var, error::Error, fmt::Debug, io::Read, os::unix::net::UnixStream, sync::{atomic::{AtomicU32, Ordering}, Arc, Mutex}, thread, u32}; use crate::wayland::shm; @@ -10,10 +10,10 @@ struct WlHeader { pub struct WlClient { pub socket: UnixStream, - pub current_id: u32, - pub registry_id: Option, + pub current_id: AtomicU32, + pub registry_id: AtomicU32, pub shm_id: Option, - pub shm_pool: Option, + pub shm_pool: Arc>>, pub buffer_id: Option, pub compositor_id: Option, pub surface_id: Option, @@ -30,12 +30,12 @@ impl WlClient { var("WAYLAND_DISPLAY")? ))?; - let res = WlClient { + let mut wl_client = WlClient { socket: sock, - current_id: 1, - registry_id: None, + current_id: AtomicU32::from(1), + registry_id: AtomicU32::from(0), shm_id: None, - shm_pool: None, + shm_pool: Arc::new(Mutex::new(None)), buffer_id: None, compositor_id: None, surface_id: None, @@ -44,7 +44,21 @@ impl WlClient { layer_surface_id: None, }; - Ok(res) + let shm_pool = wl_client.shm_pool.clone(); + thread::spawn(move || { + }).join(); + + wl_client.wl_display_get_registry()?; + + loop { + wl_client.read_event()?; + + if false { + break + } + } + + Ok(wl_client) } pub fn read_event(&mut self) -> Result<(), Box> { @@ -62,7 +76,7 @@ impl WlClient { let mut event = vec![0u8; header.size as usize - 8]; self.socket.read_exact(&mut event)?; - if header.object == self.registry_id.unwrap() && header.opcode == 0 { // wl_registry::global + if header.object == self.registry_id.load(Ordering::Relaxed) && header.opcode == 0 { // wl_registry::global self.wl_registry_global(&event)?; } else if header.object == 1 && header.opcode == 0 { // wl_display::error @@ -82,7 +96,6 @@ impl WlClient { } else if Some(header.object) == self.surface_id && header.opcode == 3 { // wl_surface::preferred_buffer_transform println!("Preferred buffer transform: {}", i32::from_ne_bytes(event[0..4].try_into().unwrap())); - dbg!(self); } else { println!( @@ -96,30 +109,3 @@ impl WlClient { Ok(()) } } - -impl Debug for WlClient { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, -"WlClient {{ - current_id: {}, - registry_id: {}, - shm_id: {}, - buffer_id: {}, - compositor_id: {}, - surface_id: {}, - xdg_wm_base_id: {}, - layer_shell_id: {}, - layer_surface_id: {}, -}}", - self.current_id, - self.registry_id.unwrap_or(0), - self.shm_id.unwrap_or(0), - self.buffer_id.unwrap_or(0), - self.compositor_id.unwrap_or(0), - self.surface_id.unwrap_or(0), - self.xdg_wm_base_id.unwrap_or(0), - self.layer_shell_id.unwrap_or(0), - self.layer_surface_id.unwrap_or(0), - ) - } -} diff --git a/src/wayland/wl_registry.rs b/src/wayland/wl_registry.rs index 33feabc..f343537 100644 --- a/src/wayland/wl_registry.rs +++ b/src/wayland/wl_registry.rs @@ -1,5 +1,5 @@ use crate::wayland::{surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient}; -use std::{io::Write, error::Error}; +use std::{error::Error, io::Write, sync::atomic::{AtomicU32, Ordering}}; impl WlClient { fn init_toplevel(&mut self) -> Result<(), Box> { @@ -41,12 +41,11 @@ impl WlClient { request.write_u16(&OPCODE, &mut offset); request.write_u16(&MSG_SIZE, &mut offset); - self.current_id += 1; - request.write_u32(&self.current_id, &mut offset); - self.registry_id = Some(self.current_id); + let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1; + request.write_u32(¤t_id, &mut offset); - let written = self.socket.write(&request)?; - assert!(written == MSG_SIZE.into()); + self.socket.write(&request)?; + self.registry_id = AtomicU32::from(current_id); Ok(()) } @@ -68,50 +67,50 @@ impl WlClient { // TODO: Collapse these into one line (probably using a macro) if interface == "wl_shm" { - self.current_id += 1; + let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1; self.wl_registry_bind( &name, &interface, &version, - &self.current_id.clone() + ¤t_id )?; - self.shm_id = Some(self.current_id); + self.shm_id = Some(current_id); self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)}); } if interface == "wl_compositor" { - self.current_id += 1; + let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1; self.wl_registry_bind( &name, &interface, &version, - &self.current_id.clone() + ¤t_id )?; - self.compositor_id = Some(self.current_id); + self.compositor_id = Some(current_id); self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)}); } if interface == "xdg_wm_base" { - self.current_id += 1; + let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1; self.wl_registry_bind( &name, &interface, &version, - &self.current_id.clone() + ¤t_id )?; - self.xdg_wm_base_id = Some(self.current_id); + self.xdg_wm_base_id = Some(current_id); self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)}); } if interface == "zwlr_layer_shell_v1" { - self.current_id += 1; + let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1; self.wl_registry_bind( &name, &interface, &version, - &self.current_id.clone() + ¤t_id )?; - self.layer_shell_id = Some(self.current_id); + self.layer_shell_id = Some(current_id); self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)}); } @@ -124,11 +123,11 @@ impl WlClient { interface: &String, version: &u32, id: &u32 - ) -> Result<(), String> { - let object: u32 = match self.registry_id { - Some(id) => id, - None => return Err(String::from("wl_registry_bind failed: wl_state.registry_id not set!")) - }; + ) -> Result<(), Box> { + let object: u32 = self.registry_id.load(Ordering::Relaxed); + if object == 0 { + return Err(UnsetErr("registry_id".to_string()).into()); + } const OPCODE: u16 = 0; let req_size: u16 = 24 + ((interface.len() as u16+3) & (u16::MAX-3)); @@ -144,14 +143,7 @@ impl WlClient { request.write_u32 (&version, &mut offset); request.write_u32 (&id, &mut offset); - match self.socket.write(&request) { - Ok(bytes) => { - assert!(bytes == req_size as usize) - } - Err(err) => { - return Err(err.to_string()); - } - }; + self.socket.write(&request)?; Ok(()) } diff --git a/src/wayland/wl_shm.rs b/src/wayland/wl_shm.rs index ddd5a1f..1c6182d 100644 --- a/src/wayland/wl_shm.rs +++ b/src/wayland/wl_shm.rs @@ -1,4 +1,4 @@ -use std::{error::Error, io::Write, os::unix::net::SocketAncillary, u8}; +use std::{error::Error, io::Write, os::unix::net::SocketAncillary, sync::atomic::Ordering, u8}; use crate::wayland::{shm, surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient}; const STRIDE: usize = 4; @@ -10,19 +10,20 @@ 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, 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(300, 300, 200, 0xff0000ff); - self.shm_pool.as_mut().unwrap().rounded_rectangle(450, 400, 60, 40, 16, 0xffffff00); + let mut shm_pool = self.shm_pool.lock().unwrap(); + let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1; + *shm_pool = Some(shm::ShmPool::new(width, height, current_id)?); + shm_pool.as_mut().unwrap().write(&vec![0xffff0000; width * height], 0); + shm_pool.as_mut().unwrap().rectangle(50, 50, 50, 50, 0xff00ff00); + shm_pool.as_mut().unwrap().circle(300, 300, 200, 0xff0000ff); + shm_pool.as_mut().unwrap().rounded_rectangle(450, 400, 60, 40, 16, 0xffffff00); let object = self.shm_id.ok_or(UnsetErr("shm_id".to_string()))?; const OPCODE: u16 = 0; const REQ_SIZE: u16 = 16; - let id = self.shm_pool.as_ref().unwrap().id; - let fds = [self.shm_pool.as_ref().unwrap().fd]; - let shm_size = self.shm_pool.as_ref().unwrap().size; + let id = shm_pool.as_ref().unwrap().id; + let fds = [shm_pool.as_ref().unwrap().fd]; + let shm_size = shm_pool.as_ref().unwrap().size; let mut request = vec![0u8; REQ_SIZE as usize]; let mut offset: usize = 0; @@ -57,13 +58,13 @@ impl WlClient { width: u32, height: u32 ) -> Result<(), Box> { - let object: u32 = self.shm_pool.as_ref().unwrap().id; + let object: u32 = self.shm_pool.lock().unwrap().as_ref().unwrap().id; const REQ_SIZE: u16 = 32; const OPCODE: u16 = 0; let stride: u32 = width * 4; - self.current_id += 1; - let id = self.current_id; + let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1; + let id = current_id; let format = 0; let mut offset: usize = 0; @@ -82,7 +83,7 @@ impl WlClient { self.socket.write(&request)?; - self.buffer_id = Some(self.current_id); + self.buffer_id = Some(current_id); Ok(()) }