shm: update to wayland-server-0.10
This commit is contained in:
parent
b8f40325aa
commit
bb86b1c3ed
|
@ -5,7 +5,7 @@ authors = ["Victor Berger <victor.berger@thalesgroup.com>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wayland-server = "0.9.9"
|
wayland-server = "0.10.1"
|
||||||
nix = "0.7.0"
|
nix = "0.7.0"
|
||||||
xkbcommon = "0.2.1"
|
xkbcommon = "0.2.1"
|
||||||
tempfile = "2.1.5"
|
tempfile = "2.1.5"
|
||||||
|
@ -18,7 +18,7 @@ glium = { version = "0.16.0", optional = true, default-features = false }
|
||||||
input = { version = "0.2.0", optional = true }
|
input = { version = "0.2.0", optional = true }
|
||||||
clippy = { version = "*", optional = true }
|
clippy = { version = "*", optional = true }
|
||||||
rental = "0.4.11"
|
rental = "0.4.11"
|
||||||
wayland-protocols = { version = "0.9.9", features = ["unstable_protocols", "server"] }
|
wayland-protocols = { version = "0.10.1", features = ["unstable_protocols", "server"] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
gl_generator = "0.5"
|
gl_generator = "0.5"
|
||||||
|
|
|
@ -12,7 +12,6 @@ extern crate nix;
|
||||||
extern crate rental;
|
extern crate rental;
|
||||||
extern crate tempfile;
|
extern crate tempfile;
|
||||||
extern crate wayland_protocols;
|
extern crate wayland_protocols;
|
||||||
#[macro_use]
|
|
||||||
extern crate wayland_server;
|
extern crate wayland_server;
|
||||||
extern crate xkbcommon;
|
extern crate xkbcommon;
|
||||||
|
|
||||||
|
@ -33,10 +32,10 @@ extern crate slog;
|
||||||
extern crate slog_stdlog;
|
extern crate slog_stdlog;
|
||||||
|
|
||||||
pub mod backend;
|
pub mod backend;
|
||||||
pub mod compositor;
|
//pub mod compositor;
|
||||||
pub mod shm;
|
pub mod shm;
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
pub mod shell;
|
//pub mod shell;
|
||||||
|
|
||||||
fn slog_or_stdlog<L>(logger: L) -> ::slog::Logger
|
fn slog_or_stdlog<L>(logger: L) -> ::slog::Logger
|
||||||
where
|
where
|
||||||
|
|
223
src/shm/mod.rs
223
src/shm/mod.rs
|
@ -19,39 +19,39 @@
|
||||||
//! extern crate wayland_server;
|
//! extern crate wayland_server;
|
||||||
//! extern crate smithay;
|
//! extern crate smithay;
|
||||||
//!
|
//!
|
||||||
//! use smithay::shm::ShmGlobal;
|
//! use smithay::shm::init_shm_global;
|
||||||
//! use wayland_server::protocol::wl_shm;
|
//! use wayland_server::protocol::wl_shm::Format;
|
||||||
//!
|
//!
|
||||||
//! # fn main() {
|
//! # fn main() {
|
||||||
//! # let (_, mut event_loop) = wayland_server::create_display();
|
//! # let (_, mut event_loop) = wayland_server::create_display();
|
||||||
//!
|
//! // Insert the ShmGlobal into your event loop
|
||||||
//! // Insert the ShmGlobal as a handler to 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 handler_id = event_loop.add_handler_with_init(ShmGlobal::new(
|
//! let shm_global = init_shm_global(
|
||||||
//! vec![wl_shm::Format::Yuyv, wl_shm::Format::C8],
|
//! &mut event_loop,
|
||||||
|
//! vec![Format::Yuyv, Format::C8],
|
||||||
//! None // we don't provide a logger here
|
//! None // we don't provide a logger here
|
||||||
//! ));
|
//! );
|
||||||
//! // Register this handler to advertise a wl_shm global of version 1
|
|
||||||
//! let shm_global = event_loop.register_global::<wl_shm::WlShm,ShmGlobal>(handler_id, 1);
|
|
||||||
//! // Retrieve the shm token for later use to access the buffers
|
|
||||||
//! let shm_token = {
|
|
||||||
//! let state = event_loop.state();
|
|
||||||
//! state.get_handler::<ShmGlobal>(handler_id).get_token()
|
|
||||||
//! };
|
|
||||||
//!
|
|
||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! Then, when you have a `WlBuffer` and need to retrieve its contents, use the token method to
|
//! Then, when you have a `WlBuffer` and need to retrieve its contents, use the token method to
|
||||||
//! do it:
|
//! do it:
|
||||||
//!
|
//!
|
||||||
//! ```ignore
|
//! ```
|
||||||
//! shm_token.with_buffer_contents(&buffer,
|
//! # extern crate wayland_server;
|
||||||
//! |slice: &[u8], buffer_metadata: &BufferData| {
|
//! # extern crate smithay;
|
||||||
|
//! # use wayland_server::protocol::wl_buffer::WlBuffer;
|
||||||
|
//! # fn wrap(buffer: &WlBuffer) {
|
||||||
|
//! use smithay::shm::{with_buffer_contents, BufferData};
|
||||||
|
//!
|
||||||
|
//! with_buffer_contents(&buffer,
|
||||||
|
//! |slice: &[u8], buffer_metadata: BufferData| {
|
||||||
//! // do something to draw it on the screen
|
//! // do something to draw it on the screen
|
||||||
//! }
|
//! }
|
||||||
//! );
|
//! );
|
||||||
|
//! # }
|
||||||
|
//! # fn main() {}
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! **Note**
|
//! **Note**
|
||||||
|
@ -63,67 +63,50 @@
|
||||||
|
|
||||||
|
|
||||||
use self::pool::{Pool, ResizeError};
|
use self::pool::{Pool, ResizeError};
|
||||||
|
use std::rc::Rc;
|
||||||
use std::os::unix::io::RawFd;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use wayland_server::{resource_is_registered, Client, EventLoop, EventLoopHandle, Global, Resource};
|
||||||
use wayland_server::{resource_is_registered, Client, Destroy, EventLoopHandle, GlobalHandler, Init, Resource};
|
|
||||||
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;
|
||||||
|
|
||||||
/// A global for handling SHM pool and buffers
|
#[derive(Clone)]
|
||||||
|
/// Internal data storage of ShmGlobal
|
||||||
///
|
///
|
||||||
/// You must register it to an event loop using `register_with_init`, or it will
|
/// This type is only visible as type parameter of
|
||||||
/// quickly panic.
|
/// the `Global` handle you are provided.
|
||||||
pub struct ShmGlobal {
|
pub struct ShmGlobalData {
|
||||||
formats: Vec<wl_shm::Format>,
|
formats: Rc<Vec<wl_shm::Format>>,
|
||||||
handler_id: Option<usize>,
|
|
||||||
log: ::slog::Logger,
|
log: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShmGlobal {
|
/// Create a new SHM global advertizing given supported formats.
|
||||||
/// Create a new SHM global advertizing given supported formats.
|
///
|
||||||
///
|
/// This global will always advertize `ARGB8888` and `XRGB8888` format
|
||||||
/// This global will always advertize `ARGB8888` and `XRGB8888` format
|
/// 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.
|
///
|
||||||
pub fn new<L>(mut formats: Vec<wl_shm::Format>, logger: L) -> ShmGlobal
|
/// The global is directly registered into the eventloop, and this function
|
||||||
where
|
/// returns the global handle, in case you whish to remove this global in
|
||||||
|
/// the future.
|
||||||
|
pub fn init_shm_global<L>(evl: &mut EventLoop, mut formats: Vec<wl_shm::Format>, logger: L)
|
||||||
|
-> Global<wl_shm::WlShm, ShmGlobalData>
|
||||||
|
where
|
||||||
L: Into<Option<::slog::Logger>>,
|
L: Into<Option<::slog::Logger>>,
|
||||||
{
|
{
|
||||||
let log = ::slog_or_stdlog(logger);
|
let log = ::slog_or_stdlog(logger);
|
||||||
|
|
||||||
// always add the mandatory formats
|
// always add the mandatory formats
|
||||||
formats.push(wl_shm::Format::Argb8888);
|
formats.push(wl_shm::Format::Argb8888);
|
||||||
formats.push(wl_shm::Format::Xrgb8888);
|
formats.push(wl_shm::Format::Xrgb8888);
|
||||||
ShmGlobal {
|
let data = ShmGlobalData {
|
||||||
formats: formats,
|
formats: Rc::new(formats),
|
||||||
handler_id: None,
|
|
||||||
log: log.new(o!("smithay_module" => "shm_handler")),
|
log: log.new(o!("smithay_module" => "shm_handler")),
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
/// Retreive a token from the SHM global.
|
let global = evl.register_global::<wl_shm::WlShm, _>(1, shm_global_bind, data);
|
||||||
///
|
|
||||||
/// This can only be called once the `ShmGlobal` has been added to and event loop
|
|
||||||
/// and has been initialized. If it is not the case, this method will panic.
|
|
||||||
///
|
|
||||||
/// This is needed to retrieve the contents of the shm pools and buffers.
|
|
||||||
pub fn get_token(&self) -> ShmToken {
|
|
||||||
ShmToken {
|
|
||||||
hid: self.handler_id.expect("ShmGlobal was not initialized."),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An SHM global token
|
global
|
||||||
///
|
|
||||||
/// It is needed to access the contents of the buffers & pools managed by the
|
|
||||||
/// associated `ShmGlobal`.
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct ShmToken {
|
|
||||||
hid: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Error that can occur when accessing an SHM buffer
|
/// Error that can occur when accessing an SHM buffer
|
||||||
|
@ -140,22 +123,21 @@ pub enum BufferAccessError {
|
||||||
BadMap,
|
BadMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShmToken {
|
/// Call given closure with the contents of the given buffer
|
||||||
/// Call given closure with the contents of the given buffer
|
///
|
||||||
///
|
/// If the buffer is managed by the provided ShmGlobal, its contents are
|
||||||
/// If the buffer is managed by the associated ShmGlobal, its contents are
|
/// extracted and the closure is extracted with them:
|
||||||
/// extracted and the closure is extracted with them:
|
///
|
||||||
///
|
/// - The first argument is a data slice of the contents of the pool
|
||||||
/// - The first argument is a data slice of the contents of the pool
|
/// - The second argument is the specification of this buffer is this pool
|
||||||
/// - The second argument is the specification of this buffer is this pool
|
///
|
||||||
///
|
/// If the buffer is not managed by the provided ShmGlobal, the closure is not called
|
||||||
/// If the buffer is not managed by the associated 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>(&self, buffer: &wl_buffer::WlBuffer, f: F) -> Result<(), BufferAccessError>
|
where
|
||||||
where
|
|
||||||
F: FnOnce(&[u8], BufferData),
|
F: FnOnce(&[u8], BufferData),
|
||||||
{
|
{
|
||||||
if !resource_is_registered::<_, ShmHandler>(buffer, self.hid) {
|
if !resource_is_registered(buffer, &buffer_implementation()) {
|
||||||
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) };
|
||||||
|
@ -169,48 +151,20 @@ impl ShmToken {
|
||||||
return Err(BufferAccessError::BadMap);
|
return Err(BufferAccessError::BadMap);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Init for ShmGlobal {
|
fn shm_global_bind(evlh: &mut EventLoopHandle, data: &mut ShmGlobalData, _: &Client, global: wl_shm::WlShm) {
|
||||||
fn init(&mut self, evqh: &mut EventLoopHandle, _index: usize) {
|
|
||||||
let id = evqh.add_handler_with_init(ShmHandler {
|
|
||||||
my_id: ::std::usize::MAX,
|
|
||||||
valid_formats: self.formats.clone(),
|
|
||||||
log: self.log.clone(),
|
|
||||||
});
|
|
||||||
self.handler_id = Some(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GlobalHandler<wl_shm::WlShm> for ShmGlobal {
|
|
||||||
fn bind(&mut self, evqh: &mut EventLoopHandle, _: &Client, global: wl_shm::WlShm) {
|
|
||||||
let hid = self.handler_id.expect("ShmGlobal was not initialized.");
|
|
||||||
// register an handler for this shm
|
// register an handler for this shm
|
||||||
evqh.register::<_, ShmHandler>(&global, hid);
|
evlh.register(&global, shm_implementation(), data.clone(), None);
|
||||||
// and then the custom formats
|
// and then the custom formats
|
||||||
for f in &self.formats {
|
for f in &data.formats[..] {
|
||||||
global.format(*f);
|
global.format(*f);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ShmHandler {
|
fn shm_implementation() -> wl_shm::Implementation<ShmGlobalData> {
|
||||||
my_id: usize,
|
wl_shm::Implementation {
|
||||||
valid_formats: Vec<wl_shm::Format>,
|
create_pool: |evlh, data, _, shm, pool, fd, size| {
|
||||||
log: ::slog::Logger,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Init for ShmHandler {
|
|
||||||
fn init(&mut self, _evqh: &mut EventLoopHandle, index: usize) {
|
|
||||||
self.my_id = index;
|
|
||||||
debug!(self.log, "Init finished")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl wl_shm::Handler for ShmHandler {
|
|
||||||
fn create_pool(&mut self, evqh: &mut EventLoopHandle, _client: &Client, shm: &wl_shm::WlShm,
|
|
||||||
pool: wl_shm_pool::WlShmPool, fd: RawFd, size: i32) {
|
|
||||||
if size <= 0 {
|
if size <= 0 {
|
||||||
shm.post_error(
|
shm.post_error(
|
||||||
wl_shm::Error::InvalidFd as u32,
|
wl_shm::Error::InvalidFd as u32,
|
||||||
|
@ -218,7 +172,7 @@ impl wl_shm::Handler for ShmHandler {
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mmap_pool = match Pool::new(fd, size as usize, self.log.clone()) {
|
let mmap_pool = match Pool::new(fd, size as usize, data.log.clone()) {
|
||||||
Ok(p) => p,
|
Ok(p) => p,
|
||||||
Err(()) => {
|
Err(()) => {
|
||||||
shm.post_error(
|
shm.post_error(
|
||||||
|
@ -229,20 +183,22 @@ impl wl_shm::Handler for ShmHandler {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let arc_pool = Box::new(Arc::new(mmap_pool));
|
let arc_pool = Box::new(Arc::new(mmap_pool));
|
||||||
evqh.register_with_destructor::<_, ShmHandler, ShmHandler>(&pool, self.my_id);
|
evlh.register(
|
||||||
|
&pool,
|
||||||
|
shm_pool_implementation(),
|
||||||
|
data.clone(),
|
||||||
|
Some(destroy_shm_pool),
|
||||||
|
);
|
||||||
pool.set_user_data(Box::into_raw(arc_pool) as *mut ());
|
pool.set_user_data(Box::into_raw(arc_pool) as *mut ());
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Destroy<wl_shm_pool::WlShmPool> for ShmHandler {
|
fn destroy_shm_pool(pool: &wl_shm_pool::WlShmPool) {
|
||||||
fn destroy(pool: &wl_shm_pool::WlShmPool) {
|
|
||||||
let arc_pool = unsafe { Box::from_raw(pool.get_user_data() as *mut Arc<Pool>) };
|
let arc_pool = unsafe { Box::from_raw(pool.get_user_data() as *mut Arc<Pool>) };
|
||||||
drop(arc_pool)
|
drop(arc_pool)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_handler!(ShmHandler, wl_shm::Handler, wl_shm::WlShm);
|
|
||||||
|
|
||||||
/// 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 {
|
||||||
|
@ -263,11 +219,10 @@ struct InternalBufferData {
|
||||||
data: BufferData,
|
data: BufferData,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl wl_shm_pool::Handler for ShmHandler {
|
fn shm_pool_implementation() -> wl_shm_pool::Implementation<ShmGlobalData> {
|
||||||
fn create_buffer(&mut self, evqh: &mut EventLoopHandle, _client: &Client,
|
wl_shm_pool::Implementation {
|
||||||
pool: &wl_shm_pool::WlShmPool, buffer: wl_buffer::WlBuffer, offset: i32, width: i32,
|
create_buffer: |evlh, data, _, pool, buffer, offset, width, height, stride, format| {
|
||||||
height: i32, stride: i32, format: wl_shm::Format) {
|
if !data.formats.contains(&format) {
|
||||||
if !self.valid_formats.contains(&format) {
|
|
||||||
buffer.post_error(wl_shm::Error::InvalidFormat as u32, String::new());
|
buffer.post_error(wl_shm::Error::InvalidFormat as u32, String::new());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -282,12 +237,10 @@ impl wl_shm_pool::Handler for ShmHandler {
|
||||||
format: format,
|
format: format,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
evqh.register_with_destructor::<_, ShmHandler, ShmHandler>(&buffer, self.my_id);
|
evlh.register(&buffer, buffer_implementation(), (), Some(destroy_buffer));
|
||||||
buffer.set_user_data(data as *mut ());
|
buffer.set_user_data(data as *mut ());
|
||||||
}
|
},
|
||||||
|
resize: |_, _, _, pool, size| {
|
||||||
fn resize(&mut self, _evqh: &mut EventLoopHandle, _client: &Client, pool: &wl_shm_pool::WlShmPool,
|
|
||||||
size: i32) {
|
|
||||||
let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) };
|
let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) };
|
||||||
match arc_pool.resize(size) {
|
match arc_pool.resize(size) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
|
@ -301,18 +254,18 @@ impl wl_shm_pool::Handler for ShmHandler {
|
||||||
pool.post_error(wl_shm::Error::InvalidFd as u32, "mremap failed.".into());
|
pool.post_error(wl_shm::Error::InvalidFd as u32, "mremap failed.".into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
destroy: |_, _, _, _| {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Destroy<wl_buffer::WlBuffer> for ShmHandler {
|
fn destroy_buffer(buffer: &wl_buffer::WlBuffer) {
|
||||||
fn destroy(buffer: &wl_buffer::WlBuffer) {
|
|
||||||
let buffer_data = unsafe { Box::from_raw(buffer.get_user_data() as *mut InternalBufferData) };
|
let buffer_data = unsafe { Box::from_raw(buffer.get_user_data() as *mut InternalBufferData) };
|
||||||
drop(buffer_data)
|
drop(buffer_data)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_handler!(ShmHandler, wl_shm_pool::Handler, wl_shm_pool::WlShmPool);
|
fn buffer_implementation() -> wl_buffer::Implementation<()> {
|
||||||
|
wl_buffer::Implementation {
|
||||||
impl wl_buffer::Handler for ShmHandler {}
|
destroy: |_, _, _, _| {},
|
||||||
|
}
|
||||||
declare_handler!(ShmHandler, wl_buffer::Handler, wl_buffer::WlBuffer);
|
}
|
||||||
|
|
Loading…
Reference in New Issue