2022-07-04 15:26:26 +02:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
|
|
2025-12-23 16:38:26 +01:00
|
|
|
use crate::{
|
|
|
|
|
state::{BackendData, State},
|
|
|
|
|
wayland::handlers::compositor::frame_time_filter_fn,
|
|
|
|
|
};
|
2022-07-04 15:26:26 +02:00
|
|
|
use smithay::{
|
2025-12-23 16:38:26 +01:00
|
|
|
backend::{allocator::dmabuf::Dmabuf, renderer::element::Kind},
|
2022-07-04 16:00:29 +02:00
|
|
|
delegate_dmabuf,
|
2025-12-23 16:38:26 +01:00
|
|
|
desktop::WindowSurfaceType,
|
|
|
|
|
reexports::wayland_server::protocol::wl_surface::WlSurface,
|
|
|
|
|
wayland::{
|
|
|
|
|
compositor::with_states,
|
|
|
|
|
dmabuf::{DmabufFeedback, DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier},
|
|
|
|
|
},
|
2022-07-04 15:26:26 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
impl DmabufHandler for State {
|
|
|
|
|
fn dmabuf_state(&mut self) -> &mut DmabufState {
|
|
|
|
|
&mut self.common.dmabuf_state
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-04 16:00:29 +02:00
|
|
|
fn dmabuf_imported(
|
|
|
|
|
&mut self,
|
|
|
|
|
global: &DmabufGlobal,
|
|
|
|
|
dmabuf: Dmabuf,
|
2023-11-22 13:27:12 -08:00
|
|
|
import_notifier: ImportNotifier,
|
|
|
|
|
) {
|
2025-12-19 18:49:22 +01:00
|
|
|
let client = import_notifier.client();
|
|
|
|
|
match self.backend.dmabuf_imported(client.clone(), global, dmabuf) {
|
2024-01-17 11:34:19 +00:00
|
|
|
Err(err) => {
|
|
|
|
|
tracing::debug!(?err, "dmabuf import failed");
|
|
|
|
|
import_notifier.failed()
|
|
|
|
|
}
|
2025-12-19 18:49:22 +01:00
|
|
|
Ok(_) => {
|
2024-01-17 11:34:19 +00:00
|
|
|
let _ = import_notifier.successful::<State>();
|
|
|
|
|
}
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
2025-12-23 16:38:26 +01:00
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}))
|
|
|
|
|
}
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delegate_dmabuf!(State);
|