use { crate::{ client::{Client, ClientError}, clientmem::{ClientMem, ClientMemError}, format::{formats, map_wayland_format_id}, ifs::wl_buffer::{WlBuffer, WlBufferError}, leaks::Tracker, object::{Object, Version}, utils::clonecell::CloneCell, wire::{WlShmPoolId, wl_shm_pool::*}, }, std::{cell::Cell, rc::Rc}, thiserror::Error, uapi::OwnedFd, }; pub struct WlShmPool { id: WlShmPoolId, client: Rc, fd: Rc, requested_len: Cell, mem: CloneCell>, pub tracker: Tracker, version: Version, } impl WlShmPool { pub fn new( id: WlShmPoolId, client: &Rc, fd: Rc, len: usize, version: Version, ) -> Result { Ok(Self { id, client: client.clone(), requested_len: Cell::new(len), mem: CloneCell::new(Rc::new(ClientMem::new( &fd, len, false, Some(client), Some(&client.state.cpu_worker), false, )?)), fd, tracker: Default::default(), version, }) } } impl WlShmPoolRequestHandler for WlShmPool { type Error = WlShmPoolError; fn create_buffer(&self, req: CreateBuffer, _slf: &Rc) -> Result<(), Self::Error> { let drm_format = map_wayland_format_id(req.format); let format = formats() .get(&drm_format) .ok_or(WlShmPoolError::InvalidFormat(req.format))?; if req.height < 0 || req.width < 0 || req.stride < 0 || req.offset < 0 { return Err(WlShmPoolError::NegativeParameters); } let buffer = WlBuffer::new_shm( req.id, &self.client, req.offset as usize, req.width, req.height, req.stride, format, &self.mem.get(), None, )?; track!(self.client, buffer); self.client.add_client_obj(&buffer)?; Ok(()) } fn destroy(&self, _req: Destroy, _slf: &Rc) -> Result<(), Self::Error> { self.client.remove_obj(self)?; Ok(()) } fn resize(&self, req: Resize, _slf: &Rc) -> Result<(), Self::Error> { if req.size < 0 { return Err(WlShmPoolError::NegativeSize); } let len = req.size as usize; if len < self.requested_len.get() { return Err(WlShmPoolError::CannotShrink); } self.requested_len.set(len); self.mem.set(Rc::new(ClientMem::new( &self.fd, len, false, Some(&self.client), Some(&self.client.state.cpu_worker), false, )?)); Ok(()) } } object_base! { self = WlShmPool; version = self.version; } impl Object for WlShmPool {} simple_add_obj!(WlShmPool); #[derive(Debug, Error)] pub enum WlShmPoolError { #[error(transparent)] ClientError(Box), #[error(transparent)] ClientMemError(Box), #[error("Tried to shrink the pool")] CannotShrink, #[error("Requested size is negative")] NegativeSize, #[error("Format {0} is not supported")] InvalidFormat(u32), #[error("All parameters in a create_buffer request must be non-negative")] NegativeParameters, #[error(transparent)] WlBufferError(Box), } efrom!(WlShmPoolError, ClientError); efrom!(WlShmPoolError, ClientMemError); efrom!(WlShmPoolError, WlBufferError);