diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2023-09-03 14:22:04 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2023-09-03 14:22:04 +0400 |
| commit | cc1c9d93254df120fc1041e121cb3b5edd00ffc9 (patch) | |
| tree | b39afcd0df6d74ec10bf511aed23b16ce105fe11 | |
| parent | 03a9fd8af3bbd8a0e6dbc33516dce83cce564166 (diff) | |
| download | niri-cc1c9d93254df120fc1041e121cb3b5edd00ffc9.tar.gz niri-cc1c9d93254df120fc1041e121cb3b5edd00ffc9.tar.bz2 niri-cc1c9d93254df120fc1041e121cb3b5edd00ffc9.zip | |
Add initial dmabuf feedback implementation
| -rw-r--r-- | src/backend/tty.rs | 24 | ||||
| -rw-r--r-- | src/handlers/compositor.rs | 40 | ||||
| -rw-r--r-- | src/handlers/mod.rs | 28 |
3 files changed, 86 insertions, 6 deletions
diff --git a/src/backend/tty.rs b/src/backend/tty.rs index eec796f1..2db762fc 100644 --- a/src/backend/tty.rs +++ b/src/backend/tty.rs @@ -12,7 +12,7 @@ use smithay::backend::drm::{DrmDevice, DrmDeviceFd, DrmEvent, DrmEventTime}; use smithay::backend::egl::{EGLContext, EGLDisplay}; use smithay::backend::libinput::{LibinputInputBackend, LibinputSessionInterface}; use smithay::backend::renderer::gles::{GlesRenderer, GlesTexture}; -use smithay::backend::renderer::{Bind, DebugFlags, ImportEgl}; +use smithay::backend::renderer::{Bind, DebugFlags, ImportDma, ImportEgl}; use smithay::backend::session::libseat::LibSeatSession; use smithay::backend::session::{Event as SessionEvent, Session}; use smithay::backend::udev::{self, UdevBackend, UdevEvent}; @@ -27,10 +27,11 @@ use smithay::reexports::nix::fcntl::OFlag; use smithay::reexports::nix::libc::dev_t; use smithay::reexports::wayland_protocols::wp::presentation_time::server::wp_presentation_feedback; use smithay::utils::DeviceFd; +use smithay::wayland::dmabuf::{DmabufFeedbackBuilder, DmabufGlobal, DmabufState}; use smithay_drm_extras::drm_scanner::{DrmScanEvent, DrmScanner}; use smithay_drm_extras::edid::EdidInfo; -use crate::niri::OutputRenderElements; +use crate::niri::{OutputRenderElements, State}; use crate::{LoopData, Niri}; const BACKGROUND_COLOR: [f32; 4] = [0.1, 0.1, 0.1, 1.]; @@ -59,6 +60,8 @@ struct OutputDevice { formats: HashSet<DrmFormat>, drm_scanner: DrmScanner, surfaces: HashMap<crtc::Handle, GbmDrmCompositor>, + dmabuf_state: DmabufState, + dmabuf_global: DmabufGlobal, } #[derive(Debug, Clone, Copy)] @@ -331,6 +334,13 @@ impl Tty { let formats = Bind::<Dmabuf>::supported_formats(&gles).unwrap_or_default(); + let mut dmabuf_state = DmabufState::new(); + let default_feedback = DmabufFeedbackBuilder::new(device_id, gles.dmabuf_formats()) + .build() + .unwrap(); + let dmabuf_global = dmabuf_state + .create_global_with_default_feedback::<State>(&niri.display_handle, &default_feedback); + self.output_device = Some(OutputDevice { id: device_id, token, @@ -340,6 +350,8 @@ impl Tty { formats, drm_scanner: DrmScanner::new(), surfaces: HashMap::new(), + dmabuf_state, + dmabuf_global, }); self.device_changed(device_id, niri); @@ -394,7 +406,11 @@ impl Tty { } let mut device = self.output_device.take().unwrap(); + device + .dmabuf_state + .destroy_global::<State>(&niri.display_handle, device.dmabuf_global); device.gles.unbind_wl_display(); + niri.event_loop.remove(device.token); } @@ -582,6 +598,10 @@ impl Tty { } } } + + pub fn dmabuf_state(&mut self) -> &mut DmabufState { + &mut self.output_device.as_mut().unwrap().dmabuf_state + } } fn refresh_interval(mode: DrmMode) -> Duration { diff --git a/src/handlers/compositor.rs b/src/handlers/compositor.rs index 035daafc..5f7bf71d 100644 --- a/src/handlers/compositor.rs +++ b/src/handlers/compositor.rs @@ -2,13 +2,16 @@ use std::collections::hash_map::Entry; use smithay::backend::renderer::utils::{on_commit_buffer_handler, with_renderer_surface_state}; use smithay::desktop::find_popup_root_surface; +use smithay::reexports::calloop::Interest; use smithay::reexports::wayland_server::protocol::wl_buffer; use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; -use smithay::reexports::wayland_server::Client; +use smithay::reexports::wayland_server::{Client, Resource}; use smithay::wayland::buffer::BufferHandler; use smithay::wayland::compositor::{ - get_parent, is_sync_subsurface, CompositorClientState, CompositorHandler, CompositorState, + add_blocker, add_pre_commit_hook, get_parent, is_sync_subsurface, with_states, + BufferAssignment, CompositorClientState, CompositorHandler, CompositorState, SurfaceAttributes, }; +use smithay::wayland::dmabuf::get_dmabuf; use smithay::wayland::shm::{ShmHandler, ShmState}; use smithay::{delegate_compositor, delegate_shm}; @@ -24,6 +27,39 @@ impl CompositorHandler for State { &client.get_data::<ClientState>().unwrap().compositor_state } + fn new_surface(&mut self, surface: &WlSurface) { + add_pre_commit_hook::<Self, _>(surface, move |state, _dh, surface| { + let maybe_dmabuf = with_states(surface, |surface_data| { + surface_data + .cached_state + .pending::<SurfaceAttributes>() + .buffer + .as_ref() + .and_then(|assignment| match assignment { + BufferAssignment::NewBuffer(buffer) => get_dmabuf(buffer).ok(), + _ => None, + }) + }); + if let Some(dmabuf) = maybe_dmabuf { + if let Ok((blocker, source)) = dmabuf.generate_blocker(Interest::READ) { + let client = surface.client().unwrap(); + let res = state + .niri + .event_loop + .insert_source(source, move |_, _, data| { + data.state + .client_compositor_state(&client) + .blocker_cleared(&mut data.state, &data.display.handle()); + Ok(()) + }); + if res.is_ok() { + add_blocker(surface, blocker); + } + } + } + }) + } + fn commit(&mut self, surface: &WlSurface) { let _span = tracy_client::span!("CompositorHandler::commit"); diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 7e643d5d..0e330322 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -2,6 +2,8 @@ mod compositor; mod layer_shell; mod xdg_shell; +use smithay::backend::allocator::dmabuf::Dmabuf; +use smithay::backend::renderer::ImportDma; use smithay::input::pointer::CursorImageStatus; use smithay::input::{Seat, SeatHandler, SeatState}; use smithay::reexports::wayland_server::protocol::wl_data_source::WlDataSource; @@ -11,9 +13,10 @@ use smithay::wayland::data_device::{ set_data_device_focus, ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler, }; +use smithay::wayland::dmabuf::{DmabufGlobal, DmabufHandler, DmabufState, ImportError}; use smithay::{ - delegate_data_device, delegate_output, delegate_pointer_gestures, delegate_presentation, - delegate_seat, delegate_tablet_manager, + delegate_data_device, delegate_dmabuf, delegate_output, delegate_pointer_gestures, + delegate_presentation, delegate_seat, delegate_tablet_manager, }; use crate::niri::State; @@ -75,3 +78,24 @@ delegate_data_device!(State); delegate_output!(State); delegate_presentation!(State); + +impl DmabufHandler for State { + fn dmabuf_state(&mut self) -> &mut DmabufState { + self.backend.tty().dmabuf_state() + } + + fn dmabuf_imported( + &mut self, + _global: &DmabufGlobal, + dmabuf: Dmabuf, + ) -> Result<(), ImportError> { + match self.backend.renderer().import_dmabuf(&dmabuf, None) { + Ok(_texture) => Ok(()), + Err(err) => { + warn!("error importing dmabuf: {err:?}"); + Err(ImportError::Failed) + } + } + } +} +delegate_dmabuf!(State); |
