diff --git a/Cargo.toml b/Cargo.toml index 3fe2045b1e0b..ff8ad54104eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -145,3 +145,14 @@ harness = false [profile.release-with-debug] inherits = "release" debug = true + +[patch."crates-io"] +wayland-server = { git = "https://github.com/smithay/wayland-rs" } +wayland-egl = { git = "https://github.com/smithay/wayland-rs" } +wayland-client = { git = "https://github.com/smithay/wayland-rs" } +wayland-cursor = { git = "https://github.com/smithay/wayland-rs" } +wayland-protocols = { git = "https://github.com/smithay/wayland-rs" } +wayland-protocols-wlr = { git = "https://github.com/smithay/wayland-rs" } +wayland-protocols-misc = { git = "https://github.com/smithay/wayland-rs" } +wayland-sys = { git = "https://github.com/smithay/wayland-rs" } +wayland-backend = { git = "https://github.com/smithay/wayland-rs" } diff --git a/src/backend/renderer/utils/wayland.rs b/src/backend/renderer/utils/wayland.rs index 155c01d0af48..c08ed57289de 100644 --- a/src/backend/renderer/utils/wayland.rs +++ b/src/backend/renderer/utils/wayland.rs @@ -24,7 +24,7 @@ use std::{ use super::{CommitCounter, DamageBag, DamageSet, DamageSnapshot, SurfaceView}; use tracing::{error, instrument, warn}; -use wayland_server::protocol::{wl_buffer::WlBuffer, wl_surface::WlSurface}; +use wayland_server::protocol::{wl_buffer::WlBuffer, wl_callback::WlCallback, wl_surface::WlSurface}; /// Type stored in WlSurface states data_map /// @@ -59,6 +59,7 @@ unsafe impl Sync for RendererSurfaceState {} #[derive(Debug)] struct InnerBuffer { buffer: WlBuffer, + release_callback: Option, #[cfg(feature = "backend_drm")] acquire_point: Option, #[cfg(feature = "backend_drm")] @@ -69,6 +70,9 @@ impl Drop for InnerBuffer { #[inline] fn drop(&mut self) { self.buffer.release(); + if let Some(callback) = &self.release_callback { + callback.done(0); + } #[cfg(feature = "backend_drm")] if let Some(release_point) = &self.release_point { if let Err(err) = release_point.signal() { @@ -86,10 +90,11 @@ pub struct Buffer { impl Buffer { /// Create a buffer with implicit sync - pub fn with_implicit(buffer: WlBuffer) -> Self { + pub fn with_implicit(buffer: WlBuffer, release_callback: Option) -> Self { Self { inner: Arc::new(InnerBuffer { buffer, + release_callback, #[cfg(feature = "backend_drm")] acquire_point: None, #[cfg(feature = "backend_drm")] @@ -100,9 +105,15 @@ impl Buffer { /// Create a buffer with explicit acquire and release sync points #[cfg(feature = "backend_drm")] - pub fn with_explicit(buffer: WlBuffer, acquire_point: DrmSyncPoint, release_point: DrmSyncPoint) -> Self { + pub fn with_explicit( + buffer: WlBuffer, + release_callback: Option, + acquire_point: DrmSyncPoint, + release_point: DrmSyncPoint, + ) -> Self { Self { inner: Arc::new(InnerBuffer { + release_callback, buffer, acquire_point: Some(acquire_point), release_point: Some(release_point), @@ -154,6 +165,9 @@ impl RendererSurfaceState { let new_buffer = matches!(attrs.buffer, Some(BufferAssignment::NewBuffer(_))); match attrs.buffer.take() { Some(BufferAssignment::NewBuffer(buffer)) => { + // TODO protocol error if set without buffer + let release_callback = attrs.release_callback.take(); + self.buffer_dimensions = buffer_dimensions(&buffer); if self.buffer_dimensions.is_none() { // This results in us rendering nothing (can happen e.g. for failed egl-buffer-calls), @@ -169,6 +183,7 @@ impl RendererSurfaceState { self.buffer = Some(Buffer { inner: Arc::new(InnerBuffer { buffer, + release_callback, #[cfg(feature = "backend_drm")] acquire_point: syncobj_state.acquire_point.take(), #[cfg(feature = "backend_drm")] diff --git a/src/wayland/compositor/handlers.rs b/src/wayland/compositor/handlers.rs index c7341ba49662..1aa0a107f83b 100644 --- a/src/wayland/compositor/handlers.rs +++ b/src/wayland/compositor/handlers.rs @@ -99,6 +99,7 @@ where }, ); } + wl_compositor::Request::Release => {} _ => unreachable!(), } } @@ -119,6 +120,7 @@ impl Cacheable for SurfaceAttributes { opaque_region: self.opaque_region.clone(), input_region: self.input_region.clone(), frame_callbacks: std::mem::take(&mut self.frame_callbacks), + release_callback: self.release_callback.take(), client_scale: self.client_scale, } } @@ -137,6 +139,9 @@ impl Cacheable for SurfaceAttributes { } } } + if let Some(release_callback) = &self.release_callback { + release_callback.done(0); + } into.buffer_delta = self.buffer_delta; into.buffer_scale = self.buffer_scale; into.buffer_transform = self.buffer_transform; @@ -145,6 +150,7 @@ impl Cacheable for SurfaceAttributes { into.input_region = self.input_region; into.frame_callbacks.extend(self.frame_callbacks); into.client_scale = self.client_scale; + into.release_callback = self.release_callback; } } @@ -334,6 +340,16 @@ where ); }); } + wl_surface::Request::GetRelease { callback } => { + let callback = data_init.init(callback, ()); + PrivateSurfaceData::with_states(surface, |states| { + states + .cached_state + .get::() + .pending() + .release_callback = Some(callback); + }); + } wl_surface::Request::Destroy => { // All is already handled by our destructor } diff --git a/src/wayland/compositor/mod.rs b/src/wayland/compositor/mod.rs index b2d06ac02984..4694e92bc7bb 100644 --- a/src/wayland/compositor/mod.rs +++ b/src/wayland/compositor/mod.rs @@ -247,6 +247,9 @@ pub struct SurfaceAttributes { /// associated with this commit has been displayed on the screen. pub frame_callbacks: Vec, + /// Callback signalled when compositor no longer needs buffer for this surface. + pub release_callback: Option, + pub(crate) client_scale: f64, } @@ -261,6 +264,7 @@ impl Default for SurfaceAttributes { input_region: None, damage: Vec::new(), frame_callbacks: Vec::new(), + release_callback: None, client_scale: 1., } } @@ -699,7 +703,7 @@ impl CompositorState { where D: GlobalDispatch + GlobalDispatch + 'static, { - Self::new_with_version::(display, 6) + Self::new_with_version::(display, 7) } fn new_with_version(display: &DisplayHandle, version: u32) -> Self diff --git a/src/wayland/compositor/tree.rs b/src/wayland/compositor/tree.rs index 798bf356b649..70a039ffe614 100644 --- a/src/wayland/compositor/tree.rs +++ b/src/wayland/compositor/tree.rs @@ -153,6 +153,12 @@ impl PrivateSurfaceData { if let Some(BufferAssignment::NewBuffer(buffer)) = guard.pending().buffer.take() { buffer.release(); }; + if let Some(release_callback) = guard.current().release_callback.take() { + release_callback.done(0); + } + if let Some(release_callback) = guard.pending().release_callback.take() { + release_callback.done(0); + } let hooks = my_data.destruction_hooks.clone(); // don't hold the mutex while the hooks are invoked diff --git a/src/wayland/selection/data_device/mod.rs b/src/wayland/selection/data_device/mod.rs index 976dfac5260c..d5f0d27ef18e 100644 --- a/src/wayland/selection/data_device/mod.rs +++ b/src/wayland/selection/data_device/mod.rs @@ -565,7 +565,7 @@ impl DataDeviceState { D: GlobalDispatch + 'static, D: DataDeviceHandler, { - let manager_global = display.create_global::(3, ()); + let manager_global = display.create_global::(4, ()); Self { manager_global, @@ -822,6 +822,7 @@ mod handlers { } } } + wl_data_device_manager::Request::Release => {} _ => unreachable!(), } }