From 64fe7ec94161539960a10203549c8ae5e900f162 Mon Sep 17 00:00:00 2001 From: chlorospingus Date: Wed, 21 May 2025 15:50:52 -0700 Subject: [PATCH] Properly double buffering --- src/graphics/circle.rs | 34 +++++++++++------ src/graphics/drawable.rs | 9 +++-- src/graphics/rectangle.rs | 37 ++++++++++++------- src/wayland/layer_shell.rs | 14 ++++--- src/wayland/shm.rs | 35 ++++++++---------- src/wayland/surface.rs | 58 +++++++++++++++++++++++++---- src/wayland/wl_client.rs | 76 +++++++++++++++++++------------------- src/wayland/wl_registry.rs | 27 +++++++++++--- src/wayland/wl_shm.rs | 38 +++++++++---------- 9 files changed, 203 insertions(+), 125 deletions(-) diff --git a/src/graphics/circle.rs b/src/graphics/circle.rs index 1affd27..398e5cf 100644 --- a/src/graphics/circle.rs +++ b/src/graphics/circle.rs @@ -1,4 +1,4 @@ -use crate::wayland::shm::ShmPool; +use crate::wayland::{shm::ShmPool, wl_shm::wl_buffer}; use super::drawable::{Drawable, color_blend}; // x and y are center of circle @@ -16,24 +16,34 @@ impl Circle { } impl Drawable for Circle { - fn draw(&self, shm_pool: &mut ShmPool) { + fn update(&mut self) { + self.x += 1; + } + + fn draw(&self, buffer: &wl_buffer, shm_pool: &mut ShmPool) { for l_row in 1..self.radius { let inner_diff = (((self.radius-1).pow(2) - l_row.pow(2)) as f64).sqrt(); let outer_diff = ((self.radius.pow(2) - l_row.pow(2)) as f64).sqrt(); let row: Vec = vec![self.color; 2*(inner_diff.floor() as usize)]; - shm_pool.write(&row, (self.y-l_row)*shm_pool.width + self.x - inner_diff.floor() as usize); - shm_pool.write(&row, (self.y+l_row-1)*shm_pool.width + self.x - inner_diff.floor() as usize); + shm_pool.write(&row, (self.y-l_row)*buffer.width + self.x - inner_diff.floor() as usize + buffer.offset); + shm_pool.write(&row, (self.y+l_row-1)*buffer.width + self.x - inner_diff.floor() as usize + buffer.offset); for l_col in (inner_diff.floor() as usize+1)..(outer_diff.ceil() as usize) { let distance = ((l_row.pow(2) + l_col.pow(2)) as f64).sqrt(); - let offset = (self.y-l_row)*shm_pool.width + self.x - l_col; - shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize); - let offset = (self.y-l_row)*shm_pool.width + self.x + l_col-1; - shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize); - let offset = (self.y+l_row-1)*shm_pool.width + self.x - l_col; - shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize); - let offset = (self.y+l_row-1)*shm_pool.width + self.x + l_col-1; - shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize); + let offset = (self.y-l_row)*buffer.width + self.x - l_col + buffer.offset; + shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset).unwrap(), distance.fract()), offset); + let offset = (self.y-l_row)*buffer.width + self.x + l_col-1 + buffer.offset; + shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset).unwrap(), distance.fract()), offset); + let offset = (self.y+l_row-1)*buffer.width + self.x - l_col + buffer.offset; + shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset).unwrap(), distance.fract()), offset); + let offset = (self.y+l_row-1)*buffer.width + self.x + l_col-1 + buffer.offset; + shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset).unwrap(), distance.fract()), offset); } } } } + +impl Into> for Circle { + fn into(self) -> Box { + Box::new(self) + } +} diff --git a/src/graphics/drawable.rs b/src/graphics/drawable.rs index 7d495f8..3f7039e 100644 --- a/src/graphics/drawable.rs +++ b/src/graphics/drawable.rs @@ -1,10 +1,12 @@ -use crate::wayland::shm::ShmPool; +use crate::wayland::{shm::ShmPool, wl_shm::wl_buffer}; pub fn color_blend(col1: u32, col2: u32, diff: f64) -> u32 { // TODO: Account for alpha channel + let a1 = (col1 & 0xff000000) >> 24; let r1 = (col1 & 0x00ff0000) >> 16; let g1 = (col1 & 0x0000ff00) >> 8; let b1 = col1 & 0x000000ff; + let a2 = (col2 & 0xff000000) >> 24; let r2 = (col2 & 0x00ff0000) >> 16; let g2 = (col2 & 0x0000ff00) >> 8; let b2 = col2 & 0x000000ff; @@ -26,6 +28,7 @@ pub fn color_blend(col1: u32, col2: u32, diff: f64) -> u32 { return 0xff000000 + (r3 << 16) + (g3 << 8) + b3; } -pub trait Drawable { - fn draw(&self, shm_pool: &mut ShmPool); +pub trait Drawable : Send { + fn update(&mut self); + fn draw(&self, buffer: &wl_buffer, shm_pool: &mut ShmPool); } diff --git a/src/graphics/rectangle.rs b/src/graphics/rectangle.rs index ca20fc2..b8994cb 100644 --- a/src/graphics/rectangle.rs +++ b/src/graphics/rectangle.rs @@ -1,7 +1,6 @@ -use crate::wayland::shm::ShmPool; +use crate::wayland::{shm::ShmPool, wl_shm::wl_buffer}; use super::drawable::{Drawable, color_blend}; - // x and y and topleft corner of rect pub struct Rectangle { x: usize, @@ -19,27 +18,37 @@ impl Rectangle { } impl Drawable for Rectangle { - fn draw(&self, shm_pool: &mut ShmPool) { + fn update(&mut self) { + // self.x += 1; + } + + fn draw(&self, buffer: &wl_buffer, shm_pool: &mut ShmPool) { for g_row in self.y+self.radius..self.y+self.height-self.radius+1 { - shm_pool.write(&vec![self.color; self.width], g_row*shm_pool.width+self.x); + shm_pool.write(&vec![self.color; self.width], g_row*buffer.width as usize+self.x + buffer.offset); } for l_row in 1..self.radius { let inner_diff = (((self.radius-1).pow(2) - l_row.pow(2)) as f64).sqrt(); let outer_diff = ((self.radius.pow(2) - l_row.pow(2)) as f64).sqrt(); - shm_pool.write(&vec![self.color; self.width - (2*(self.radius - inner_diff.floor() as usize-1))], (self.y+self.radius-l_row)*shm_pool.width + self.x + self.radius - inner_diff.floor() as usize-1); - shm_pool.write(&vec![self.color; self.width - (2*(self.radius - inner_diff.floor() as usize-1))], (self.y+self.height-self.radius+l_row)*shm_pool.width + self.x + self.radius - inner_diff.floor() as usize-1); + shm_pool.write(&vec![self.color; self.width - (2*(self.radius - inner_diff.floor() as usize-1))], (self.y+self.radius-l_row)*buffer.width as usize + self.x + self.radius - inner_diff.floor() as usize-1 + buffer.offset); + shm_pool.write(&vec![self.color; self.width - (2*(self.radius - inner_diff.floor() as usize-1))], (self.y+self.height-self.radius+l_row)*buffer.width as usize + self.x + self.radius - inner_diff.floor() as usize-1 + buffer.offset); for l_col in inner_diff.floor() as usize+1..outer_diff.ceil() as usize { + // TODO: handle error from read_pixel let distance = ((l_row.pow(2) + l_col.pow(2)) as f64).sqrt(); - let offset = (self.y+self.radius-l_row)*shm_pool.width + self.x + self.radius - l_col - 1; - shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize); - let offset = (self.y+self.radius-l_row)*shm_pool.width + self.x + self.width - self.radius + l_col; - shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize); - let offset = (self.y+self.height-self.radius+l_row)*shm_pool.width + self.x + self.radius - l_col - 1; - shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize); - let offset = (self.y+self.height-self.radius+l_row)*shm_pool.width + self.x + self.width - self.radius + l_col; - shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize); + let offset = (self.y+self.radius-l_row)*buffer.width as usize + self.x + self.radius - l_col - 1 + buffer.offset; + shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset).unwrap(), distance.fract()), offset); + let offset = (self.y+self.radius-l_row)*buffer.width as usize + self.x + self.width - self.radius + l_col + buffer.offset; + shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset).unwrap(), distance.fract()), offset); + let offset = (self.y+self.height-self.radius+l_row)*buffer.width as usize + self.x + self.radius - l_col - 1 + buffer.offset; + shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset).unwrap(), distance.fract()), offset); + let offset = (self.y+self.height-self.radius+l_row)*buffer.width as usize + self.x + self.width - self.radius + l_col + buffer.offset; + shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset).unwrap(), distance.fract()), offset); } } } } +impl Into> for Rectangle { + fn into(self) -> Box { + Box::new(self) + } +} diff --git a/src/wayland/layer_shell.rs b/src/wayland/layer_shell.rs index 646cd68..b8bb202 100644 --- a/src/wayland/layer_shell.rs +++ b/src/wayland/layer_shell.rs @@ -1,4 +1,4 @@ -use std::{error::Error, io::Write, sync::atomic::Ordering}; +use std::{error::Error, io::Write, sync::atomic::Ordering, thread, time::Duration}; use crate::wayland::{surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient}; const NAMESPACE: &str = "chlorostart"; @@ -42,12 +42,18 @@ impl WlClient { Ok(()) } - pub fn layer_surface_configure(&self, event: &Vec) -> Result<(), Box> { + pub fn layer_surface_configure(&self, event: &Vec) -> Result<(), Box> { let mut offset: usize = 0; let serial = event.read_u32(&mut offset); let width = event.read_u32(&mut offset); let height = event.read_u32(&mut offset); + println!( + "Configure layer surface:\n\twidth: {}\n\theight: {}", + width, + height + ); + // TODO: Resize based on configure // Ack configure @@ -68,9 +74,7 @@ impl WlClient { request.write_u32(&serial, &mut offset); self.socket.lock().unwrap().write(&request)?; - - self.wl_surface_attach()?; - self.wl_surface_commit()?; + self.wl_surface_frame()?; Ok(()) } diff --git a/src/wayland/shm.rs b/src/wayland/shm.rs index b335e15..91ab670 100644 --- a/src/wayland/shm.rs +++ b/src/wayland/shm.rs @@ -5,13 +5,10 @@ pub struct ShmPool { pub fd: i32, pub addr: *mut c_void, pub size: usize, - pub width: usize, } impl ShmPool { - pub fn new(width: usize, height: usize) -> std::io::Result { - let size = width * height * 4; - + pub fn new(size: usize) -> std::io::Result { 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 { @@ -39,17 +36,16 @@ impl ShmPool { fd, addr, size, - width, }) } pub fn from_fd(fd: i32, size: usize) -> std::io::Result { let addr = unsafe { mmap(std::ptr::null_mut(), size, PROT_READ, MAP_PRIVATE, fd, 0) }; if addr == MAP_FAILED { - eprint!("mmap in ShmPool::from_fd() failed: "); + eprint!("mmap in ShmPool::from_fd() failed with fd {}", fd); return Err(std::io::Error::last_os_error()); } - Ok(ShmPool {fd, addr, size, width: 0}) + Ok(ShmPool {fd, addr, size}) } pub fn read_string(&self, offset: usize) -> std::io::Result { @@ -74,30 +70,31 @@ impl ShmPool { } pub fn write(&mut self, data: &Vec, offset: usize) { - if offset > self.size { + if offset + data.len() >= self.size { return; } unsafe { std::ptr::copy_nonoverlapping( data.as_ptr() as *const u32, // src: data as *const u32 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 - } + data.len() ); } } - 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 write_pixel(&mut self, data: u32, offset: usize) { + // TODO: Return error if out of bounds + if offset + 3 > self.size { + return; + } + unsafe {*(self.addr.offset(offset as isize*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)}; + pub fn read_pixel(&self, offset: usize) -> Option { + if offset + 3 > self.size { + return None; + } + return Some(unsafe {*(self.addr.offset(4*offset as isize) as *const u32)}); } } diff --git a/src/wayland/surface.rs b/src/wayland/surface.rs index d8cad55..bc4b64d 100644 --- a/src/wayland/surface.rs +++ b/src/wayland/surface.rs @@ -1,6 +1,6 @@ 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, wl_shm::wl_buffer}; use std::fmt; @@ -40,17 +40,16 @@ impl WlClient { Ok(()) } - pub fn wl_surface_attach(&self) -> Result<(), Box> { + pub fn wl_surface_attach(&self, buffer: &wl_buffer) -> Result<(), Box> { + + let id = buffer.id; + let object = self.surface_id.load(Ordering::Relaxed); if object == 0 { return Err(UnsetErr("surface_id".to_string()).into()); } const OPCODE: u16 = 1; const MSG_SIZE: u16 = 20; - let buffer = self.buffer_id.load(Ordering::Relaxed); - if buffer == 0 { - return Err(UnsetErr("buffer_id".to_string()).into()); - } const X: u32 = 0; const Y: u32 = 0; @@ -60,11 +59,11 @@ impl WlClient { request.write_u32(&object, &mut offset); request.write_u16(&OPCODE, &mut offset); request.write_u16(&MSG_SIZE, &mut offset); - request.write_u32(&buffer, &mut offset); + request.write_u32(&id, &mut offset); request.write_u32(&X, &mut offset); request.write_u32(&Y, &mut offset); - self.socket.lock().unwrap().write(&request)?; + self.socket.lock()?.write(&request)?; Ok(()) } @@ -89,6 +88,49 @@ impl WlClient { Ok(()) } + pub fn wl_surface_frame(&self) -> Result<(), Box> { + let object = self.surface_id.load(Ordering::Relaxed); + if object == 0 { + return Err(UnsetErr("surface_id".to_string()).into()); + } + const OPCODE: u16 = 3; + const MSG_SIZE: u16 = 12; + let id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1; + + let mut request = vec![0u8; MSG_SIZE as usize]; + let mut offset: usize = 0; + + request.write_u32(&object, &mut offset); + request.write_u16(&OPCODE, &mut offset); + request.write_u16(&MSG_SIZE, &mut offset); + request.write_u32(&id, &mut offset); + self.socket.lock()?.write(&request)?; + self.frame_hint_id.store(id, Ordering::Relaxed); + + let buf_lock = if self.active_buffer.fetch_update( + Ordering::Relaxed, + Ordering::Relaxed, + |b| { Some(!b) } + ).unwrap() { + &self.buffer1 + } else { + &self.buffer2 + }.lock()?; + let buffer = buf_lock.as_ref().ok_or(UnsetErr("buffer".to_string()))?; + + self.wl_surface_attach(buffer)?; + let mut drawables = self.drawables.lock()?; + let mut shm_pool = self.shm_pool.lock()?; + shm_pool.write(&vec![0x00000000; 800 * 800 * 2], 0); + for drawable in &mut *drawables { + drawable.update(); + drawable.draw(buffer, &mut *shm_pool); + } + self.wl_surface_commit()?; + + Ok(()) + } + pub fn xdg_wm_base_pong(&self, event: &Vec) -> Result<(), Box> { let object = self.xdg_wm_base_id.load(Ordering::Relaxed); if object == 0 { diff --git a/src/wayland/wl_client.rs b/src/wayland/wl_client.rs index 10419b6..e73fb88 100644 --- a/src/wayland/wl_client.rs +++ b/src/wayland/wl_client.rs @@ -1,11 +1,6 @@ use std::{collections::HashMap, env::var, error::Error, fmt::Debug, io::{IoSliceMut, Write}, os::unix::net::{AncillaryData, SocketAncillary, UnixStream}, sync::{atomic::{AtomicBool, AtomicU32, Ordering}, mpsc, Arc, Mutex, RwLock}, thread::{self}, time::Duration, u32}; -use crate::wayland::{shm, vec_utils::WlMessage}; - -#[derive(PartialEq)] -pub enum ThreadMessage { -} -use ThreadMessage::*; +use crate::{graphics::{circle::Circle, drawable::Drawable, rectangle::Rectangle}, wayland::{shm, surface::UnsetErr, vec_utils::WlMessage, wl_shm::wl_buffer}}; struct WlHeader { object: u32, @@ -15,23 +10,26 @@ struct WlHeader { pub struct WlClient { pub socket: Mutex, - pub sender: mpsc::Sender, pub running: AtomicBool, pub current_id: AtomicU32, pub registry_id: AtomicU32, pub shm_id: AtomicU32, pub shmpool_id: AtomicU32, pub shm_pool: Mutex, - pub buffer_id: AtomicU32, pub compositor_id: AtomicU32, pub surface_id: AtomicU32, + pub active_buffer: AtomicBool, + pub buffer1: Mutex>, + pub buffer2: Mutex>, + pub frame_hint_id: AtomicU32, pub xdg_wm_base_id: AtomicU32, pub layer_shell_id: AtomicU32, pub layer_surface_id: AtomicU32, pub seat_id: AtomicU32, pub keyboard_id: AtomicU32, pub keymap_fd: Mutex>, - pub keymap: RwLock>>> + pub keymap: RwLock>>>, + pub drawables: Mutex>>, } impl WlClient { @@ -43,18 +41,18 @@ impl WlClient { ))?; sock.set_nonblocking(true)?; - let (sender, receiver) = mpsc::channel::(); - let mut arc_wl_client = Arc::new(WlClient { socket: Mutex::new(sock), - sender, running: AtomicBool::from(false), current_id: AtomicU32::from(1), registry_id: AtomicU32::from(0), shm_id: AtomicU32::from(0), shmpool_id: AtomicU32::from(0), - shm_pool: Mutex::new(shm::ShmPool::new(800, 800)?), - buffer_id: AtomicU32::from(0), + shm_pool: Mutex::new(shm::ShmPool::new(800 * 800 * 4 * 2)?), + active_buffer: AtomicBool::from(false), + buffer1: Mutex::new(None), + buffer2: Mutex::new(None), + frame_hint_id: AtomicU32::from(0), compositor_id: AtomicU32::from(0), surface_id: AtomicU32::from(0), xdg_wm_base_id: AtomicU32::from(0), @@ -64,8 +62,13 @@ impl WlClient { keyboard_id: AtomicU32::from(0), keymap: RwLock::new(None), keymap_fd: Mutex::new(None), + drawables: Mutex::new(Vec::new()), }); arc_wl_client.wl_display_get_registry(); + if let Ok(mut drawables) = arc_wl_client.drawables.lock() { + drawables.push(Rectangle::new(50, 50, 300, 300, 16, 0xffff8800).into()); + drawables.push(Circle::new(150, 80, 25, 0xff00ffff).into()); + } arc_wl_client.running.store(true, Ordering::Relaxed); let wl_client = arc_wl_client.clone(); @@ -75,21 +78,12 @@ impl WlClient { } })?; - // let wl_client = arc_wl_client.clone(); - // let recvloop = thread::Builder::new().name("recvloop".to_string()).spawn(move || { - // while wl_client.running.load(Ordering::Relaxed) { - // match receiver.recv().unwrap() { - // } - // } - // })?; - // - // recvloop.join(); readloop.join(); Ok(()) } - pub fn read_event(self: &Arc) -> Result<(), Box> { + pub fn read_event(self: &Arc) -> Result<(), Box> { // TODO: Don't realloc header and event // FIXME: Using fd like this is unreliable because fd could be before or after @@ -126,8 +120,8 @@ impl WlClient { )?; for ancillary_result in ancillary.messages() { if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() { - scm_rights.for_each(|fd| { - println!("found {}", fd); + scm_rights.for_each(|received| { + fd = received; }); } } @@ -139,7 +133,6 @@ impl WlClient { } else if header.object == 1 && header.opcode == 0 { // wl_display::error WlClient::wl_display_error(&event); - dbg!(&self); } else if header.object == self.shm_id.load(Ordering::Relaxed) && header.opcode == 0 { // wl_shm::format WlClient::wl_shm_format(&event); @@ -151,10 +144,10 @@ impl WlClient { self.layer_surface_configure(&event)?; } else if header.object == self.surface_id.load(Ordering::Relaxed) && header.opcode == 2 { // wl_surface::preferred_buffer_scale - println!("Preferred buffer scale: {}", i32::from_ne_bytes(event[0..4].try_into().unwrap())); + // println!("Preferred buffer scale: {}", i32::from_ne_bytes(event[0..4].try_into().unwrap())); } else if header.object == self.surface_id.load(Ordering::Relaxed) && 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())); } else if header.object == self.seat_id.load(Ordering::Relaxed) && header.opcode == 0 { // wl_seat::capabilities self.wl_seat_capabilities(&event)?; @@ -163,7 +156,7 @@ impl WlClient { self.wl_seat_name(&event); } else if header.object == self.keyboard_id.load(Ordering::Relaxed) && header.opcode == 0 { // wl_keyboard::keymap - self.wl_keyboard_keymap(&event, fd); + self.wl_keyboard_keymap(&event, fd)?; } else if header.object == self.keyboard_id.load(Ordering::Relaxed) && header.opcode == 3 { // wl_keyboard::key let wl_client = self.clone(); @@ -171,6 +164,9 @@ impl WlClient { wl_client.wl_keyboard_key(&event); }); } + else if header.object == self.frame_hint_id.load(Ordering::Relaxed) && header.opcode == 0 { // wl_callback::done + self.wl_surface_frame()?; + } else { println!( "Received event:\n\tObject: {}\n\tOpcode: {}\n\tSize: {}", @@ -183,9 +179,8 @@ impl WlClient { Ok(()) } - pub fn destroy_object(&self, id: &AtomicU32, opcode: u16) { - let object = id.load(Ordering::Relaxed); - if object == 0 { + pub fn destroy_object(&self, id: u32, opcode: u16) { + if id == 0 { return; } const REQ_SIZE: u16 = 8; @@ -193,7 +188,7 @@ impl WlClient { let mut request = vec![0; REQ_SIZE as usize]; let mut offset = 0; - request.write_u32(&object, &mut offset); + request.write_u32(&id, &mut offset); request.write_u16(&opcode, &mut offset); request.write_u16(&REQ_SIZE, &mut offset); @@ -201,12 +196,13 @@ impl WlClient { self.shmpool_id.store(0, Ordering::Relaxed); } - pub fn exit(&self) { + pub fn exit(&self) -> Result<(), Box> { println!("Exiting!"); - self.destroy_object(&self.layer_surface_id, 7); - self.destroy_object(&self.buffer_id, 0); + self.destroy_object(self.layer_surface_id.load(Ordering::Relaxed), 7); + self.destroy_object(self.buffer1.lock()?.as_ref().ok_or(UnsetErr("buffer1".to_string()))?.id, 0); self.keymap_fd.lock().unwrap().take(); self.running.store(false, Ordering::Relaxed); + Ok(()) } } @@ -217,7 +213,8 @@ impl Debug for WlClient { registry_id: {}, shm_id: {}, shmpool_id: {}, - buffer_id: {}, + buffer1: {:?}, + buffer2: {:?}, compositor_id: {}, surface_id: {}, xdg_wm_base_id: {}, @@ -230,7 +227,8 @@ impl Debug for WlClient { self.registry_id.load(Ordering::Relaxed), self.shm_id.load(Ordering::Relaxed), self.shmpool_id.load(Ordering::Relaxed), - self.buffer_id.load(Ordering::Relaxed), + self.buffer1.lock().unwrap(), + self.buffer2.lock().unwrap(), self.compositor_id.load(Ordering::Relaxed), self.surface_id.load(Ordering::Relaxed), self.xdg_wm_base_id.load(Ordering::Relaxed), diff --git a/src/wayland/wl_registry.rs b/src/wayland/wl_registry.rs index 98ef7e9..7253cb3 100644 --- a/src/wayland/wl_registry.rs +++ b/src/wayland/wl_registry.rs @@ -1,8 +1,8 @@ -use crate::wayland::{surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient}; -use std::{error::Error, io::Write, sync::atomic::{AtomicU32, Ordering}}; +use crate::wayland::{surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient, wl_shm::wl_buffer}; +use std::{error::Error, io::Write, sync::{atomic::{AtomicU32, Ordering}, Arc}}; impl WlClient { - fn init_toplevel(&self) -> Result<(), Box> { + fn init_toplevel(&self) -> Result<(), Box> { if self.shm_id.load(Ordering::Relaxed) == 0 { return Err(Box::new(UnsetErr("shm_id".to_string()))); } @@ -26,8 +26,25 @@ impl WlClient { self.layer_surface_set_keyboard_interactivity()?; self.wl_surface_commit()?; - self.wl_shm_create_pool(800, 800)?; - self.wl_shm_pool_create_buffer(0, 800, 800)?; + self.wl_shm_create_pool()?; + + let current_id = self.current_id.fetch_add(2, Ordering::Relaxed); + let mut buffer1 = self.buffer1.lock().unwrap(); + let mut buffer2 = self.buffer2.lock().unwrap(); + *buffer1 = Some(wl_buffer { + id: current_id + 1, + offset: 0, + width: 800, + height: 800 + }); + *buffer2 = Some(wl_buffer { + id: current_id + 2, + offset: 800 * 800, // pixel offset + width: 800, + height: 800 + }); + self.wl_shm_pool_create_buffer(buffer1.as_ref().unwrap())?; + self.wl_shm_pool_create_buffer(buffer2.as_ref().unwrap())?; Ok(()) } diff --git a/src/wayland/wl_shm.rs b/src/wayland/wl_shm.rs index 78a6a93..0c1d305 100644 --- a/src/wayland/wl_shm.rs +++ b/src/wayland/wl_shm.rs @@ -1,27 +1,28 @@ +use std::sync::atomic::AtomicU32; use std::{error::Error, io::Write, os::unix::net::SocketAncillary, sync::atomic::Ordering, u8}; -use crate::graphics::drawable::Drawable; -use crate::wayland::{shm, surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient}; -use crate::graphics::{rectangle::Rectangle, circle::Circle}; +use crate::wayland::{surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient}; const STRIDE: usize = 4; +#[derive(Debug)] +pub struct wl_buffer { + pub id: u32, + pub offset: usize, + pub width: usize, + pub height: usize, +} + impl WlClient { pub fn wl_shm_format(event: &Vec) { // let mut offset = 0; // println!("Received pixel format: {:x}", event.read_u32(&mut offset)); } - pub fn wl_shm_create_pool(&self, width: usize, height: usize) -> Result<(), Box> { - let mut shm_pool = self.shm_pool.lock().unwrap(); + pub fn wl_shm_create_pool(&self) -> Result<(), Box> { + let shm_pool = self.shm_pool.lock().unwrap(); let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1; self.shmpool_id.store(current_id, Ordering::Relaxed); - // shm_pool.write(&vec![0xffff0000; width * height], 0); - let rect = Rectangle::new(100, 100, 200, 50, 20, 0xffffff); - rect.draw(&mut shm_pool); - // let circle = Circle::new(250, 150, 20, 0xff00ffff); - // circle.draw(&mut shm_pool); - let object = self.shm_id.load(Ordering::Relaxed); if object == 0 { return Err(UnsetErr("shm_id".to_string()).into()); @@ -61,17 +62,17 @@ impl WlClient { pub fn wl_shm_pool_create_buffer( &self, - shm_offset: u32, - width: u32, - height: u32 + buffer: &wl_buffer ) -> Result<(), Box> { let object: u32 = self.shmpool_id.load(Ordering::Relaxed); const REQ_SIZE: u16 = 32; const OPCODE: u16 = 0; + let byte_offset: u32 = buffer.offset as u32 * 4; + let width: u32 = buffer.width as u32; + let height: u32 = buffer.height as u32; let stride: u32 = width * 4; - let current_id = self.current_id.fetch_add(1, Ordering::Relaxed) + 1; - let id = current_id; + let id = buffer.id; let format = 0; let mut offset: usize = 0; @@ -82,7 +83,7 @@ impl WlClient { request.write_u16(&REQ_SIZE, &mut offset); request.write_u32(&id, &mut offset); - request.write_u32(&shm_offset, &mut offset); + request.write_u32(&byte_offset, &mut offset); request.write_u32(&width, &mut offset); request.write_u32(&height, &mut offset); request.write_u32(&stride, &mut offset); @@ -90,9 +91,6 @@ impl WlClient { self.socket.lock().unwrap().write(&request)?; - self.buffer_id.store(current_id, Ordering::Relaxed); - Ok(()) } - }