kms: Dmabuf feedback support

This commit is contained in:
Victoria Brekenfeld 2023-03-31 13:57:37 +02:00
parent 636d38921a
commit bc49507353
8 changed files with 267 additions and 36 deletions

View file

@ -1,7 +1,11 @@
// SPDX-License-Identifier: GPL-3.0-only
use crate::{
backend::{kms::KmsState, winit::WinitState, x11::X11State},
backend::{
kms::{source_node_for_surface, KmsState},
winit::WinitState,
x11::X11State,
},
config::{Config, OutputConfig},
shell::{layout::floating::SeatMoveGrabState, Shell},
utils::prelude::*,
@ -20,15 +24,18 @@ use smithay::{
backend::{
drm::DrmNode,
renderer::{
element::{default_primary_scanout_output_compare, RenderElementStates},
element::{
default_primary_scanout_output_compare, utils::select_dmabuf_feedback,
RenderElementStates,
},
glow::GlowRenderer,
},
},
desktop::utils::{
send_frames_surface_tree, surface_presentation_feedback_flags_from_states,
surface_primary_scanout_output, take_presentation_feedback_surface_tree,
update_surface_primary_scanout_output, with_surfaces_surface_tree,
OutputPresentationFeedback,
send_dmabuf_feedback_surface_tree, send_frames_surface_tree,
surface_presentation_feedback_flags_from_states, surface_primary_scanout_output,
take_presentation_feedback_surface_tree, update_surface_primary_scanout_output,
with_surfaces_surface_tree, OutputPresentationFeedback,
},
input::{pointer::CursorImageStatus, Seat, SeatState},
output::{Mode as OutputMode, Output, Scale},
@ -45,11 +52,12 @@ use smithay::{
wayland::{
compositor::CompositorState,
data_device::DataDeviceState,
dmabuf::DmabufState,
dmabuf::{DmabufFeedback, DmabufState},
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState,
output::OutputManagerState,
presentation::PresentationState,
primary_selection::PrimarySelectionState,
seat::WaylandFocus,
shell::{kde::decoration::KdeDecorationState, xdg::decoration::XdgDecorationState},
shm::ShmState,
viewporter::ViewporterState,
@ -130,6 +138,12 @@ pub enum BackendData {
Unset,
}
#[derive(Debug, Clone)]
pub struct SurfaceDmabufFeedback {
pub render_feedback: DmabufFeedback,
pub scanout_feedback: DmabufFeedback,
}
impl BackendData {
pub fn kms(&mut self) -> &mut KmsState {
match self {
@ -363,7 +377,12 @@ impl Common {
self.last_active_seat.as_ref().expect("No seat?")
}
pub fn send_frames(&self, output: &Output, render_element_states: &RenderElementStates) {
pub fn send_frames(
&self,
output: &Output,
render_element_states: &RenderElementStates,
mut dmabuf_feedback: impl FnMut(DrmNode) -> Option<SurfaceDmabufFeedback>,
) {
let time = self.clock.now();
let throttle = Some(Duration::from_secs(1));
@ -401,6 +420,21 @@ impl Common {
throttle,
surface_primary_scanout_output,
);
let window = grab_state.window();
if let Some(feedback) = window
.wl_surface()
.and_then(|wl_surface| {
source_node_for_surface(&wl_surface, &self.display_handle)
})
.and_then(|source| dmabuf_feedback(source))
{
window.send_dmabuf_feedback(
output,
&feedback,
render_element_states,
surface_primary_scanout_output,
);
}
}
}
}
@ -432,6 +466,20 @@ impl Common {
);
});
window.send_frame(output, time, throttle, surface_primary_scanout_output);
if let Some(feedback) = window
.wl_surface()
.and_then(|wl_surface| {
source_node_for_surface(&wl_surface, &self.display_handle)
})
.and_then(|source| dmabuf_feedback(source))
{
window.send_dmabuf_feedback(
output,
&feedback,
render_element_states,
surface_primary_scanout_output,
);
}
}
});
@ -466,7 +514,24 @@ impl Common {
time,
throttle,
surface_primary_scanout_output,
)
);
if let Some(feedback) = source_node_for_surface(&wl_surface, &self.display_handle)
.and_then(|source| dmabuf_feedback(source))
{
send_dmabuf_feedback_surface_tree(
&wl_surface,
output,
surface_primary_scanout_output,
|surface, _| {
select_dmabuf_feedback(
surface,
render_element_states,
&feedback.render_feedback,
&feedback.scanout_feedback,
)
},
)
}
}
});
@ -482,6 +547,23 @@ impl Common {
);
});
layer_surface.send_frame(output, time, throttle, surface_primary_scanout_output);
if let Some(feedback) =
source_node_for_surface(layer_surface.wl_surface(), &self.display_handle)
.and_then(|source| dmabuf_feedback(source))
{
layer_surface.send_dmabuf_feedback(
output,
surface_primary_scanout_output,
|surface, _| {
select_dmabuf_feedback(
surface,
render_element_states,
&feedback.render_feedback,
&feedback.scanout_feedback,
)
},
);
}
}
}