feat: support renderer-validated dma-buf imports

This commit is contained in:
Samuel Onoja committed 2026-09-25 01:26:16 +01:00
1 parent d32f20dbbf
commit 05f801aee6
5 files changed
+59 -3

No files matched your search

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