Files
server/src/wayland/core/shm_pool.rs
2025-09-26 16:32:46 -07:00

86 lines
2.3 KiB
Rust

use super::shm_buffer_backing::ShmBufferBacking;
use crate::wayland::{
Client, WaylandResult,
core::buffer::{Buffer, BufferBacking},
};
use memmap2::{MmapOptions, RemapOptions};
use parking_lot::{Mutex, MutexGuard, RawMutex, lock_api::MappedMutexGuard};
use std::os::fd::{IntoRawFd, OwnedFd};
use waynest::ObjectId;
use waynest_protocols::server::core::wayland::wl_shm::Format;
pub use waynest_protocols::server::core::wayland::wl_shm_pool::*;
#[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct ShmPool {
inner: Mutex<memmap2::MmapMut>,
}
impl ShmPool {
#[tracing::instrument(level = "debug", skip_all)]
pub fn new(fd: OwnedFd, size: i32) -> WaylandResult<Self> {
let map = unsafe {
MmapOptions::new()
.len(size as usize)
.map_mut(fd.into_raw_fd())?
};
Ok(Self {
inner: Mutex::new(map),
})
}
#[tracing::instrument(level = "debug", skip_all)]
pub fn data_lock(&self) -> MappedMutexGuard<'_, RawMutex, [u8]> {
MutexGuard::map(self.inner.lock(), |i| i.as_mut())
}
}
impl WlShmPool for ShmPool {
type Connection = Client;
/// https://wayland.app/protocols/wayland#wl_shm_pool:request:create_buffer
#[tracing::instrument(level = "debug", skip_all)]
async fn create_buffer(
&self,
client: &mut Self::Connection,
sender_id: ObjectId,
id: ObjectId,
offset: i32,
width: i32,
height: i32,
stride: i32,
format: Format,
) -> WaylandResult<()> {
let params = ShmBufferBacking::new(
client.get::<ShmPool>(sender_id).unwrap(),
offset as usize,
stride as usize,
[width as usize, height as usize].into(),
format,
);
Buffer::new(client, id, BufferBacking::Shm(params));
Ok(())
}
/// https://wayland.app/protocols/wayland#wl_shm_pool:request:resize
#[tracing::instrument(level = "debug", skip_all)]
async fn resize(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
size: i32,
) -> WaylandResult<()> {
let mut inner = self.inner.lock();
unsafe { inner.remap(size as usize, RemapOptions::new().may_move(true))? };
Ok(())
}
/// https://wayland.app/protocols/wayland#wl_shm_pool:request:destroy
#[tracing::instrument(level = "debug", skip_all)]
async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> {
Ok(())
}
}