current_id, registry_id, and ShmPool are atomic

This commit is contained in:
2025-05-06 11:57:35 -07:00
parent cbe54334ca
commit 375b44beee
7 changed files with 73 additions and 101 deletions

View File

@@ -8,15 +8,5 @@ mod graphics;
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
let mut wl_client = WlClient::new()?; let mut wl_client = WlClient::new()?;
wl_client.wl_display_get_registry()?;
loop {
wl_client.read_event()?;
if false {
break
}
}
Ok(()) Ok(())
} }

View File

@@ -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}; use crate::wayland::{vec_utils::WlMessage, wl_client::WlClient};
const NAMESPACE: &str = "chlorostart"; const NAMESPACE: &str = "chlorostart";
@@ -19,15 +19,15 @@ impl WlClient {
request.write_u16(&OPCODE, &mut offset); request.write_u16(&OPCODE, &mut offset);
request.write_u16(&msg_size, &mut offset); request.write_u16(&msg_size, &mut offset);
self.current_id += 1; let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1;
request.write_u32(&self.current_id, &mut offset); request.write_u32(&current_id, &mut offset);
self.layer_surface_id = Some(self.current_id);
request.write_u32(&self.surface_id.unwrap(), &mut offset); request.write_u32(&self.surface_id.unwrap(), &mut offset);
request.write_u32(&output, &mut offset); request.write_u32(&output, &mut offset);
request.write_u32(&OVERLAY, &mut offset); request.write_u32(&OVERLAY, &mut offset);
request.write_string(&NAMESPACE.to_string(), &mut offset); request.write_string(&NAMESPACE.to_string(), &mut offset);
self.socket.write(&request)?; self.socket.write(&request)?;
self.layer_surface_id = Some(current_id);
Ok(()) Ok(())
} }

View File

@@ -87,3 +87,6 @@ impl Drop for ShmPool {
unsafe { munmap(self.addr, self.size); } unsafe { munmap(self.addr, self.size); }
} }
} }
unsafe impl Send for ShmPool {}
unsafe impl Sync for ShmPool {}

View File

@@ -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}; use crate::wayland::{vec_utils::WlMessage, wl_client::WlClient};
@@ -31,12 +31,12 @@ impl WlClient {
request.write_u16(&OPCODE, &mut offset); request.write_u16(&OPCODE, &mut offset);
request.write_u16(&MSG_SIZE, &mut offset); request.write_u16(&MSG_SIZE, &mut offset);
self.current_id += 1; let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1;
request.write_u32(&self.current_id, &mut offset); request.write_u32(&current_id, &mut offset);
self.socket.write(&request)?; self.socket.write(&request)?;
self.surface_id = Some(self.current_id); self.surface_id = Some(current_id);
Ok(()) Ok(())
} }

View File

@@ -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; use crate::wayland::shm;
@@ -10,10 +10,10 @@ struct WlHeader {
pub struct WlClient { pub struct WlClient {
pub socket: UnixStream, pub socket: UnixStream,
pub current_id: u32, pub current_id: AtomicU32,
pub registry_id: Option<u32>, pub registry_id: AtomicU32,
pub shm_id: Option<u32>, pub shm_id: Option<u32>,
pub shm_pool: Option<shm::ShmPool>, pub shm_pool: Arc<Mutex<Option<shm::ShmPool>>>,
pub buffer_id: Option<u32>, pub buffer_id: Option<u32>,
pub compositor_id: Option<u32>, pub compositor_id: Option<u32>,
pub surface_id: Option<u32>, pub surface_id: Option<u32>,
@@ -30,12 +30,12 @@ impl WlClient {
var("WAYLAND_DISPLAY")? var("WAYLAND_DISPLAY")?
))?; ))?;
let res = WlClient { let mut wl_client = WlClient {
socket: sock, socket: sock,
current_id: 1, current_id: AtomicU32::from(1),
registry_id: None, registry_id: AtomicU32::from(0),
shm_id: None, shm_id: None,
shm_pool: None, shm_pool: Arc::new(Mutex::new(None)),
buffer_id: None, buffer_id: None,
compositor_id: None, compositor_id: None,
surface_id: None, surface_id: None,
@@ -44,7 +44,21 @@ impl WlClient {
layer_surface_id: None, 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<dyn Error>> { pub fn read_event(&mut self) -> Result<(), Box<dyn Error>> {
@@ -62,7 +76,7 @@ impl WlClient {
let mut event = vec![0u8; header.size as usize - 8]; let mut event = vec![0u8; header.size as usize - 8];
self.socket.read_exact(&mut event)?; 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)?; self.wl_registry_global(&event)?;
} }
else if header.object == 1 && header.opcode == 0 { // wl_display::error 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 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())); println!("Preferred buffer transform: {}", i32::from_ne_bytes(event[0..4].try_into().unwrap()));
dbg!(self);
} }
else { else {
println!( println!(
@@ -96,30 +109,3 @@ impl WlClient {
Ok(()) 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),
)
}
}

View File

@@ -1,5 +1,5 @@
use crate::wayland::{surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient}; 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 { impl WlClient {
fn init_toplevel(&mut self) -> Result<(), Box<dyn Error>> { fn init_toplevel(&mut self) -> Result<(), Box<dyn Error>> {
@@ -41,12 +41,11 @@ impl WlClient {
request.write_u16(&OPCODE, &mut offset); request.write_u16(&OPCODE, &mut offset);
request.write_u16(&MSG_SIZE, &mut offset); request.write_u16(&MSG_SIZE, &mut offset);
self.current_id += 1; let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1;
request.write_u32(&self.current_id, &mut offset); request.write_u32(&current_id, &mut offset);
self.registry_id = Some(self.current_id);
let written = self.socket.write(&request)?; self.socket.write(&request)?;
assert!(written == MSG_SIZE.into()); self.registry_id = AtomicU32::from(current_id);
Ok(()) Ok(())
} }
@@ -68,50 +67,50 @@ impl WlClient {
// TODO: Collapse these into one line (probably using a macro) // TODO: Collapse these into one line (probably using a macro)
if interface == "wl_shm" { if interface == "wl_shm" {
self.current_id += 1; let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1;
self.wl_registry_bind( self.wl_registry_bind(
&name, &name,
&interface, &interface,
&version, &version,
&self.current_id.clone() &current_id
)?; )?;
self.shm_id = Some(self.current_id); self.shm_id = Some(current_id);
self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)}); self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)});
} }
if interface == "wl_compositor" { if interface == "wl_compositor" {
self.current_id += 1; let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1;
self.wl_registry_bind( self.wl_registry_bind(
&name, &name,
&interface, &interface,
&version, &version,
&self.current_id.clone() &current_id
)?; )?;
self.compositor_id = Some(self.current_id); self.compositor_id = Some(current_id);
self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)}); self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)});
} }
if interface == "xdg_wm_base" { 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( self.wl_registry_bind(
&name, &name,
&interface, &interface,
&version, &version,
&self.current_id.clone() &current_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)}); self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)});
} }
if interface == "zwlr_layer_shell_v1" { 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( self.wl_registry_bind(
&name, &name,
&interface, &interface,
&version, &version,
&self.current_id.clone() &current_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)}); self.init_toplevel().unwrap_or_else(|err| {eprintln!("{}", err)});
} }
@@ -124,11 +123,11 @@ impl WlClient {
interface: &String, interface: &String,
version: &u32, version: &u32,
id: &u32 id: &u32
) -> Result<(), String> { ) -> Result<(), Box<dyn Error>> {
let object: u32 = match self.registry_id { let object: u32 = self.registry_id.load(Ordering::Relaxed);
Some(id) => id, if object == 0 {
None => return Err(String::from("wl_registry_bind failed: wl_state.registry_id not set!")) return Err(UnsetErr("registry_id".to_string()).into());
}; }
const OPCODE: u16 = 0; const OPCODE: u16 = 0;
let req_size: u16 = 24 + ((interface.len() as u16+3) & (u16::MAX-3)); 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 (&version, &mut offset);
request.write_u32 (&id, &mut offset); request.write_u32 (&id, &mut offset);
match self.socket.write(&request) { self.socket.write(&request)?;
Ok(bytes) => {
assert!(bytes == req_size as usize)
}
Err(err) => {
return Err(err.to_string());
}
};
Ok(()) Ok(())
} }

View File

@@ -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}; use crate::wayland::{shm, surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient};
const STRIDE: usize = 4; const STRIDE: usize = 4;
@@ -10,19 +10,20 @@ impl WlClient {
} }
pub fn wl_shm_create_pool(&mut self, width: usize, height: usize) -> Result<(), Box<dyn Error>> { pub fn wl_shm_create_pool(&mut self, width: usize, height: usize) -> Result<(), Box<dyn Error>> {
self.current_id += 1; let mut shm_pool = self.shm_pool.lock().unwrap();
self.shm_pool = Some(shm::ShmPool::new(width, height, self.current_id)?); let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1;
self.shm_pool.as_mut().unwrap().write(&vec![0xffff0000; width * height], 0); *shm_pool = Some(shm::ShmPool::new(width, height, current_id)?);
self.shm_pool.as_mut().unwrap().rectangle(50, 50, 50, 50, 0xff00ff00); shm_pool.as_mut().unwrap().write(&vec![0xffff0000; width * height], 0);
self.shm_pool.as_mut().unwrap().circle(300, 300, 200, 0xff0000ff); shm_pool.as_mut().unwrap().rectangle(50, 50, 50, 50, 0xff00ff00);
self.shm_pool.as_mut().unwrap().rounded_rectangle(450, 400, 60, 40, 16, 0xffffff00); 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()))?; let object = self.shm_id.ok_or(UnsetErr("shm_id".to_string()))?;
const OPCODE: u16 = 0; const OPCODE: u16 = 0;
const REQ_SIZE: u16 = 16; const REQ_SIZE: u16 = 16;
let id = self.shm_pool.as_ref().unwrap().id; let id = shm_pool.as_ref().unwrap().id;
let fds = [self.shm_pool.as_ref().unwrap().fd]; let fds = [shm_pool.as_ref().unwrap().fd];
let shm_size = self.shm_pool.as_ref().unwrap().size; let shm_size = shm_pool.as_ref().unwrap().size;
let mut request = vec![0u8; REQ_SIZE as usize]; let mut request = vec![0u8; REQ_SIZE as usize];
let mut offset: usize = 0; let mut offset: usize = 0;
@@ -57,13 +58,13 @@ impl WlClient {
width: u32, width: u32,
height: u32 height: u32
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
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 REQ_SIZE: u16 = 32;
const OPCODE: u16 = 0; const OPCODE: u16 = 0;
let stride: u32 = width * 4; let stride: u32 = width * 4;
self.current_id += 1; let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1;
let id = self.current_id; let id = current_id;
let format = 0; let format = 0;
let mut offset: usize = 0; let mut offset: usize = 0;
@@ -82,7 +83,7 @@ impl WlClient {
self.socket.write(&request)?; self.socket.write(&request)?;
self.buffer_id = Some(self.current_id); self.buffer_id = Some(current_id);
Ok(()) Ok(())
} }