diff --git a/compositor/src/backends/direct.rs b/compositor/src/backends/direct.rs index 8de169c..fc12e2c 100644 --- a/compositor/src/backends/direct.rs +++ b/compositor/src/backends/direct.rs @@ -174,6 +174,11 @@ fn open_primary_device( // SAFETY: the new context is not current on another thread and remains renderer-owned. let renderer = unsafe { GlesRenderer::new(egl_context)? }; state.shm_state.update_formats(renderer.shm_formats()); + let dmabuf_formats = renderer.dmabuf_formats(); + let display_handle = state.display_handle.clone(); + state + .dmabuf_state + .create_global::(&display_handle, dmabuf_formats); let (connector, crtc, mode) = select_output(&drm)?; let output = create_output(state, &connector, mode); if let Some(backend) = state.direct_backend.as_mut() { @@ -299,6 +304,7 @@ fn render_device(state: &mut Ferese, node: DrmNode) { } let rendered = (|| -> Result> { + state.process_dmabuf_imports(&mut device.renderer); let (mut buffer, age) = device.surface.next_buffer()?; let elements = animated_window_elements(state, &mut device.renderer, &device.output); let mut framebuffer = device.renderer.bind(&mut buffer)?; diff --git a/compositor/src/handlers/compositor.rs b/compositor/src/handlers/compositor.rs index 4aa38bb..69e4204 100644 --- a/compositor/src/handlers/compositor.rs +++ b/compositor/src/handlers/compositor.rs @@ -1,5 +1,5 @@ use smithay::{ - backend::renderer::utils::on_commit_buffer_handler, + backend::{allocator::dmabuf::Dmabuf, renderer::utils::on_commit_buffer_handler}, reexports::wayland_server::{ Client, protocol::{wl_buffer, wl_surface::WlSurface}, @@ -10,6 +10,7 @@ use smithay::{ CompositorClientState, CompositorHandler, CompositorState, get_parent, is_sync_subsurface, }, + dmabuf::{DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier}, shm::{ShmHandler, ShmState}, }, }; @@ -74,6 +75,22 @@ impl BufferHandler for Ferese { fn buffer_destroyed(&mut self, _buffer: &wl_buffer::WlBuffer) {} } +impl DmabufHandler for Ferese { + fn dmabuf_state(&mut self) -> &mut DmabufState { + &mut self.dmabuf_state + } + + fn dmabuf_imported( + &mut self, + _global: &DmabufGlobal, + dmabuf: Dmabuf, + notifier: ImportNotifier, + ) { + self.queue_dmabuf_import(dmabuf, notifier); + crate::backends::direct::render_all(self); + } +} + impl ShmHandler for Ferese { fn shm_state(&self) -> &ShmState { &self.shm_state diff --git a/compositor/src/handlers/mod.rs b/compositor/src/handlers/mod.rs index 7d2fb2a..766c7f1 100644 --- a/compositor/src/handlers/mod.rs +++ b/compositor/src/handlers/mod.rs @@ -235,6 +235,7 @@ impl XdgForeignHandler for Ferese { smithay::delegate_compositor!(Ferese); smithay::delegate_cursor_shape!(Ferese); smithay::delegate_data_device!(Ferese); +smithay::delegate_dmabuf!(Ferese); smithay::delegate_fractional_scale!(Ferese); smithay::delegate_idle_inhibit!(Ferese); smithay::delegate_idle_notify!(Ferese); diff --git a/compositor/src/state.rs b/compositor/src/state.rs index e8f0a8d..2a909c9 100644 --- a/compositor/src/state.rs +++ b/compositor/src/state.rs @@ -11,7 +11,7 @@ use ferese_core::{WindowPlacement, WorkspaceSet}; use ferese_layout::{Axis, Direction, GapConfig, LayoutResult, Rect, SizeConstraints, WindowId}; use smithay::{ - backend::drm::DrmEventTime, + backend::{allocator::dmabuf::Dmabuf, drm::DrmEventTime, renderer::ImportDma}, desktop::{ LayerSurface, PopupManager, Space, Window, WindowSurfaceType, layer_map_for_output, utils::send_frames_surface_tree, @@ -37,6 +37,7 @@ use smithay::{ wayland::{ compositor::{CompositorClientState, CompositorState, with_states}, cursor_shape::CursorShapeManagerState, + dmabuf::{DmabufState, ImportNotifier}, fractional_scale::FractionalScaleManagerState, idle_inhibit::IdleInhibitManagerState, idle_notify::IdleNotifierState, @@ -78,6 +79,7 @@ pub struct Ferese { pub idle_inhibitors: HashMap, pub active_shortcuts_inhibitor: Option, pub direct_backend: Option, + pending_dmabuf_imports: Vec<(Dmabuf, ImportNotifier)>, next_window_id: u64, last_animation_tick: Instant, pub popups: PopupManager, @@ -86,6 +88,7 @@ pub struct Ferese { pub cursor_shape_state: CursorShapeManagerState, pub data_device_state: DataDeviceState, pub decoration_state: XdgDecorationState, + pub dmabuf_state: DmabufState, pub fractional_scale_state: FractionalScaleManagerState, pub idle_inhibit_state: IdleInhibitManagerState, pub idle_notifier_state: IdleNotifierState, @@ -108,6 +111,25 @@ pub struct Ferese { } impl Ferese { + pub(crate) fn queue_dmabuf_import(&mut self, dmabuf: Dmabuf, notifier: ImportNotifier) { + self.pending_dmabuf_imports.push((dmabuf, notifier)); + } + + pub(crate) fn process_dmabuf_imports(&mut self, renderer: &mut R) + where + R: ImportDma, + { + for (dmabuf, notifier) in self.pending_dmabuf_imports.drain(..) { + if renderer.import_dmabuf(&dmabuf, None).is_ok() { + if let Err(error) = notifier.successful::() { + tracing::debug!(?error, "dma-buf client disappeared before import completed"); + } + } else { + notifier.failed(); + } + } + } + pub fn new( event_loop: &mut EventLoop<'static, Self>, display: Display, @@ -117,6 +139,7 @@ impl Ferese { let cursor_shape_state = CursorShapeManagerState::new::(&display_handle); let xdg_shell_state = XdgShellState::new::(&display_handle); let decoration_state = XdgDecorationState::new::(&display_handle); + let dmabuf_state = DmabufState::new(); let fractional_scale_state = FractionalScaleManagerState::new::(&display_handle); let idle_inhibit_state = IdleInhibitManagerState::new::(&display_handle); let idle_notifier_state = IdleNotifierState::new(&display_handle, event_loop.handle()); @@ -168,6 +191,7 @@ impl Ferese { idle_inhibitors: HashMap::new(), active_shortcuts_inhibitor: None, direct_backend: None, + pending_dmabuf_imports: Vec::new(), next_window_id: 1, last_animation_tick: start_time, popups: PopupManager::default(), @@ -176,6 +200,7 @@ impl Ferese { cursor_shape_state, data_device_state, decoration_state, + dmabuf_state, fractional_scale_state, idle_inhibit_state, idle_notifier_state, diff --git a/compositor/src/winit.rs b/compositor/src/winit.rs index 4efbc2f..e65fd51 100644 --- a/compositor/src/winit.rs +++ b/compositor/src/winit.rs @@ -6,6 +6,7 @@ use std::{ use smithay::{ backend::{ renderer::{ + ImportDma, damage::OutputDamageTracker, element::{ AsRenderElements, Kind as RenderElementKind, @@ -52,7 +53,12 @@ render_elements! { } pub fn init(event_loop: &mut EventLoop, state: &mut Ferese) -> Result<(), Box> { - let (mut backend, event_source) = winit::init()?; + let (mut backend, event_source) = winit::init::()?; + let dmabuf_formats = backend.renderer().dmabuf_formats(); + let display_handle = state.display_handle.clone(); + state + .dmabuf_state + .create_global::(&display_handle, dmabuf_formats); let initial_scale = normalized_scale(backend.scale_factor()); let mode = Mode { size: backend.window_size(), @@ -127,6 +133,7 @@ pub fn init(event_loop: &mut EventLoop, state: &mut Ferese) -> Result<() let rendered = (|| -> Result<(), Box> { { let (renderer, mut framebuffer) = backend.bind()?; + state.process_dmabuf_imports(renderer); let elements = animated_window_elements(state, renderer, &output); damage_tracker.render_output( renderer,