wayland/dmabuf: Send initial surface feedback

This commit is contained in:
Victoria Brekenfeld 2025-12-23 16:38:26 +01:00 committed by Victoria Brekenfeld
parent dc5a9fac66
commit 7b8fca9ece
2 changed files with 65 additions and 4 deletions

View file

@ -118,7 +118,7 @@ pub struct Surface {
known_nodes: HashSet<DrmNode>,
active: Arc<AtomicBool>,
pub(super) feedback: HashMap<DrmNode, SurfaceDmabufFeedback>,
pub feedback: HashMap<DrmNode, SurfaceDmabufFeedback>,
pub(super) primary_plane_formats: FormatSet,
overlay_plane_formats: Option<FormatSet>,

View file

@ -1,10 +1,18 @@
// SPDX-License-Identifier: GPL-3.0-only
use crate::state::State;
use crate::{
state::{BackendData, State},
wayland::handlers::compositor::frame_time_filter_fn,
};
use smithay::{
backend::allocator::dmabuf::Dmabuf,
backend::{allocator::dmabuf::Dmabuf, renderer::element::Kind},
delegate_dmabuf,
wayland::dmabuf::{DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier},
desktop::WindowSurfaceType,
reexports::wayland_server::protocol::wl_surface::WlSurface,
wayland::{
compositor::with_states,
dmabuf::{DmabufFeedback, DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier},
},
};
impl DmabufHandler for State {
@ -29,6 +37,59 @@ impl DmabufHandler for State {
}
}
}
fn new_surface_feedback(
&mut self,
surface: &WlSurface,
global: &DmabufGlobal,
) -> Option<DmabufFeedback> {
let BackendData::Kms(kms) = &self.backend else {
return None;
};
let shell = self.common.shell.read();
let (handle, output) = shell.workspace_for_surface(surface)?;
let is_fullscreen = shell
.workspaces
.space_for_handle(&handle)?
.fullscreen
.as_ref()
.is_some_and(|f| f.surface.has_surface(surface, WindowSurfaceType::all()));
let node = kms
.drm_devices
.values()
.find(|device| {
device
.socket
.as_ref()
.map(|s| &s.dmabuf_global == global)
.unwrap_or(false)
})?
.inner
.render_node;
let kms_surface = kms
.drm_devices
.values()
.find_map(|device| device.inner.surfaces.values().find(|s| s.output == output))?;
let feedback = kms_surface.feedback.get(&node)?.clone();
Some(with_states(surface, |data| {
if is_fullscreen {
feedback
.primary_scanout_feedback
.unwrap_or(feedback.render_feedback)
} else {
if frame_time_filter_fn(data) == Kind::ScanoutCandidate {
feedback
.overlay_scanout_feedback
.unwrap_or(feedback.render_feedback)
} else {
feedback.render_feedback
}
}
}))
}
}
delegate_dmabuf!(State);