wayland.shm: migrate to wayland_rs-0.20

This commit is contained in:
Victor Berger 2018-04-13 12:36:57 +02:00
parent 570cee0987
commit b9cac1a373
3 changed files with 106 additions and 87 deletions

View File

@ -49,7 +49,7 @@ extern crate error_chain;
extern crate lazy_static; extern crate lazy_static;
//pub mod backend; //pub mod backend;
//pub mod wayland; pub mod wayland;
pub mod utils; pub mod utils;
fn slog_or_stdlog<L>(logger: L) -> ::slog::Logger fn slog_or_stdlog<L>(logger: L) -> ::slog::Logger

View File

@ -18,8 +18,8 @@
//! not previously destroyed all the globals using it, otherwise you'll //! not previously destroyed all the globals using it, otherwise you'll
//! quickly encounter a panic. //! quickly encounter a panic.
pub mod compositor; //pub mod compositor;
pub mod output; //pub mod output;
pub mod seat; //pub mod seat;
pub mod shm; pub mod shm;
pub mod shell; //pub mod shell;

View File

@ -23,12 +23,13 @@
//! use wayland_server::protocol::wl_shm::Format; //! use wayland_server::protocol::wl_shm::Format;
//! //!
//! # fn main() { //! # fn main() {
//! # let (display, mut event_loop) = wayland_server::create_display(); //! # let (mut display, mut event_loop) = wayland_server::Display::new();
//! // Insert the ShmGlobal into your event loop //! // Insert the ShmGlobal into your event loop
//! // Here, we specify that Yuyv and C8 format are supported //! // Here, we specify that Yuyv and C8 format are supported
//! // additionnaly to the standart Argb8888 and Xrgb8888. //! // additionnaly to the standart Argb8888 and Xrgb8888.
//! let shm_global = init_shm_global( //! let shm_global = init_shm_global(
//! &mut event_loop, //! &mut display,
//! event_loop.token(),
//! vec![Format::Yuyv, Format::C8], //! vec![Format::Yuyv, Format::C8],
//! None // we don't provide a logger here //! None // we don't provide a logger here
//! ); //! );
@ -42,7 +43,8 @@
//! # extern crate wayland_server; //! # extern crate wayland_server;
//! # extern crate smithay; //! # extern crate smithay;
//! # use wayland_server::protocol::wl_buffer::WlBuffer; //! # use wayland_server::protocol::wl_buffer::WlBuffer;
//! # fn wrap(buffer: &WlBuffer) { //! # use wayland_server::Resource;
//! # fn wrap(buffer: &Resource<WlBuffer>) {
//! use smithay::wayland::shm::{with_buffer_contents, BufferData}; //! use smithay::wayland::shm::{with_buffer_contents, BufferData};
//! //!
//! with_buffer_contents(&buffer, //! with_buffer_contents(&buffer,
@ -64,7 +66,8 @@
use self::pool::{Pool, ResizeError}; use self::pool::{Pool, ResizeError};
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use wayland_server::{resource_is_registered, Client, EventLoopHandle, Global, Resource}; use wayland_server::{Display, Global, LoopToken, NewResource, Resource};
use wayland_server::commons::Implementation;
use wayland_server::protocol::{wl_buffer, wl_shm, wl_shm_pool}; use wayland_server::protocol::{wl_buffer, wl_shm, wl_shm_pool};
mod pool; mod pool;
@ -77,6 +80,7 @@ mod pool;
pub struct ShmGlobalData { pub struct ShmGlobalData {
formats: Rc<Vec<wl_shm::Format>>, formats: Rc<Vec<wl_shm::Format>>,
log: ::slog::Logger, log: ::slog::Logger,
token: LoopToken,
} }
/// Create a new SHM global advertizing given supported formats. /// Create a new SHM global advertizing given supported formats.
@ -85,12 +89,15 @@ pub struct ShmGlobalData {
/// as they are required by the protocol. Formats given as argument /// as they are required by the protocol. Formats given as argument
/// as additionnaly advertized. /// as additionnaly advertized.
/// ///
/// The global is directly registered into the eventloop, and this function /// The global is directly created on the provided `Display`, and this function
/// returns the global handle, in case you whish to remove this global in /// returns the global handle, in case you whish to remove this global in
/// the future. /// the future.
pub fn init_shm_global<L>( pub fn init_shm_global<L>(
evlh: &mut EventLoopHandle, mut formats: Vec<wl_shm::Format>, logger: L display: &mut Display,
) -> Global<wl_shm::WlShm, ShmGlobalData> token: LoopToken,
mut formats: Vec<wl_shm::Format>,
logger: L,
) -> Global<wl_shm::WlShm>
where where
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
{ {
@ -102,9 +109,16 @@ where
let data = ShmGlobalData { let data = ShmGlobalData {
formats: Rc::new(formats), formats: Rc::new(formats),
log: log.new(o!("smithay_module" => "shm_handler")), log: log.new(o!("smithay_module" => "shm_handler")),
token: token.clone(),
}; };
evlh.register_global::<wl_shm::WlShm, _>(1, shm_global_bind, data) display.create_global::<wl_shm::WlShm, _>(&token, 1, move |_version, shm_new: NewResource<_>| {
let shm = shm_new.implement_nonsend(data.clone(), None::<fn(_, _)>, &data.token);
// send the formats
for f in &data.formats[..] {
shm.send(wl_shm::Event::Format { format: *f });
}
})
} }
/// Error that can occur when accessing an SHM buffer /// Error that can occur when accessing an SHM buffer
@ -131,11 +145,11 @@ pub enum BufferAccessError {
/// ///
/// If the buffer is not managed by the provided `ShmGlobal`, the closure is not called /// If the buffer is not managed by the provided `ShmGlobal`, the closure is not called
/// and this method will return `Err(())` (this will be the case for an EGL buffer for example). /// and this method will return `Err(())` (this will be the case for an EGL buffer for example).
pub fn with_buffer_contents<F>(buffer: &wl_buffer::WlBuffer, f: F) -> Result<(), BufferAccessError> pub fn with_buffer_contents<F>(buffer: &Resource<wl_buffer::WlBuffer>, f: F) -> Result<(), BufferAccessError>
where where
F: FnOnce(&[u8], BufferData), F: FnOnce(&[u8], BufferData),
{ {
if !resource_is_registered(buffer, &buffer_implementation()) { if !buffer.is_implemented_with::<ShmGlobalData>() {
return Err(BufferAccessError::NotManaged); return Err(BufferAccessError::NotManaged);
} }
let data = unsafe { &*(buffer.get_user_data() as *mut InternalBufferData) }; let data = unsafe { &*(buffer.get_user_data() as *mut InternalBufferData) };
@ -151,52 +165,43 @@ where
Ok(()) Ok(())
} }
fn shm_global_bind(evlh: &mut EventLoopHandle, data: &mut ShmGlobalData, _: &Client, global: wl_shm::WlShm) { impl Implementation<Resource<wl_shm::WlShm>, wl_shm::Request> for ShmGlobalData {
// register an handler for this shm fn receive(&mut self, request: wl_shm::Request, shm: Resource<wl_shm::WlShm>) {
evlh.register(&global, shm_implementation(), data.clone(), None); use self::wl_shm::{Error, Request};
// and then the custom formats
for f in &data.formats[..] {
global.format(*f);
}
}
fn shm_implementation() -> wl_shm::Implementation<ShmGlobalData> { match request {
wl_shm::Implementation { Request::CreatePool { id: pool, fd, size } => {
create_pool: |evlh, data, _, shm, pool, fd, size| { if size <= 0 {
if size <= 0 {
shm.post_error(
wl_shm::Error::InvalidFd as u32,
"Invalid size for a new wl_shm_pool.".into(),
);
return;
}
let mmap_pool = match Pool::new(fd, size as usize, data.log.clone()) {
Ok(p) => p,
Err(()) => {
shm.post_error( shm.post_error(
wl_shm::Error::InvalidFd as u32, Error::InvalidFd as u32,
format!("Failed mmap of fd {}.", fd), "Invalid size for a new wl_shm_pool.".into(),
); );
return; return;
} }
}; let mmap_pool = match Pool::new(fd, size as usize, self.log.clone()) {
let arc_pool = Box::new(Arc::new(mmap_pool)); Ok(p) => p,
evlh.register( Err(()) => {
&pool, shm.post_error(
shm_pool_implementation(), wl_shm::Error::InvalidFd as u32,
data.clone(), format!("Failed mmap of fd {}.", fd),
Some(destroy_shm_pool), );
); return;
pool.set_user_data(Box::into_raw(arc_pool) as *mut ()); }
}, };
let arc_pool = Box::new(Arc::new(mmap_pool));
let pool = pool.implement_nonsend(
self.clone(),
Some(|pool: Resource<_>, _| {
drop(unsafe { Box::from_raw(pool.get_user_data() as *mut Arc<Pool>) })
}),
&self.token,
);
pool.set_user_data(Box::into_raw(arc_pool) as *mut ());
}
}
} }
} }
fn destroy_shm_pool(pool: &wl_shm_pool::WlShmPool) {
let arc_pool = unsafe { Box::from_raw(pool.get_user_data() as *mut Arc<Pool>) };
drop(arc_pool)
}
/// Details of the contents of a buffer relative to its pool /// Details of the contents of a buffer relative to its pool
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct BufferData { pub struct BufferData {
@ -217,30 +222,48 @@ struct InternalBufferData {
data: BufferData, data: BufferData,
} }
fn shm_pool_implementation() -> wl_shm_pool::Implementation<ShmGlobalData> { impl Implementation<Resource<wl_shm_pool::WlShmPool>, wl_shm_pool::Request> for ShmGlobalData {
wl_shm_pool::Implementation { fn receive(&mut self, request: wl_shm_pool::Request, pool: Resource<wl_shm_pool::WlShmPool>) {
create_buffer: |evlh, data, _, pool, buffer, offset, width, height, stride, format| { use self::wl_shm_pool::Request;
if !data.formats.contains(&format) {
buffer.post_error(wl_shm::Error::InvalidFormat as u32, String::new()); let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) };
return;
match request {
Request::CreateBuffer {
id: buffer,
offset,
width,
height,
stride,
format,
} => {
if !self.formats.contains(&format) {
pool.post_error(
wl_shm::Error::InvalidFormat as u32,
format!("SHM format {:?} is not supported.", format),
);
return;
}
let data = Box::into_raw(Box::new(InternalBufferData {
pool: arc_pool.clone(),
data: BufferData {
offset: offset,
width: width,
height: height,
stride: stride,
format: format,
},
}));
let buffer = buffer.implement_nonsend(
self.clone(),
Some(|buffer: Resource<_>, _| {
drop(unsafe { Box::from_raw(buffer.get_user_data() as *mut InternalBufferData) })
}),
&self.token,
);
buffer.set_user_data(data as *mut ());
} }
let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) }; Request::Resize { size } => match arc_pool.resize(size) {
let data = Box::into_raw(Box::new(InternalBufferData {
pool: arc_pool.clone(),
data: BufferData {
offset: offset,
width: width,
height: height,
stride: stride,
format: format,
},
}));
evlh.register(&buffer, buffer_implementation(), (), Some(destroy_buffer));
buffer.set_user_data(data as *mut ());
},
resize: |_, _, _, pool, size| {
let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) };
match arc_pool.resize(size) {
Ok(()) => {} Ok(()) => {}
Err(ResizeError::InvalidSize) => { Err(ResizeError::InvalidSize) => {
pool.post_error( pool.post_error(
@ -251,19 +274,15 @@ fn shm_pool_implementation() -> wl_shm_pool::Implementation<ShmGlobalData> {
Err(ResizeError::MremapFailed) => { Err(ResizeError::MremapFailed) => {
pool.post_error(wl_shm::Error::InvalidFd as u32, "mremap failed.".into()); pool.post_error(wl_shm::Error::InvalidFd as u32, "mremap failed.".into());
} }
} },
}, Request::Destroy => {}
destroy: |_, _, _, _| {}, }
} }
} }
fn destroy_buffer(buffer: &wl_buffer::WlBuffer) { impl Implementation<Resource<wl_buffer::WlBuffer>, wl_buffer::Request> for ShmGlobalData {
let buffer_data = unsafe { Box::from_raw(buffer.get_user_data() as *mut InternalBufferData) }; fn receive(&mut self, request: wl_buffer::Request, _pool: Resource<wl_buffer::WlBuffer>) {
drop(buffer_data) // this will break if new requests are added to buffer =)
} let wl_buffer::Request::Destroy = request;
fn buffer_implementation() -> wl_buffer::Implementation<()> {
wl_buffer::Implementation {
destroy: |_, _, _, _| {},
} }
} }