aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2023-09-03 15:15:55 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2023-09-03 15:15:55 +0400
commit95cbe2a636e89b4ccd24baa8420e02a519658efd (patch)
tree983d1b93844d378c6678cd89e99421331a15f8e4 /src
parentcc1c9d93254df120fc1041e121cb3b5edd00ffc9 (diff)
downloadniri-95cbe2a636e89b4ccd24baa8420e02a519658efd.tar.gz
niri-95cbe2a636e89b4ccd24baa8420e02a519658efd.tar.bz2
niri-95cbe2a636e89b4ccd24baa8420e02a519658efd.zip
Send scanout feedbacks to surfaces
Diffstat (limited to 'src')
-rw-r--r--src/backend/mod.rs3
-rw-r--r--src/backend/tty.rs40
-rw-r--r--src/backend/winit.rs5
-rw-r--r--src/handlers/mod.rs2
-rw-r--r--src/layout.rs38
-rw-r--r--src/niri.rs43
6 files changed, 116 insertions, 15 deletions
diff --git a/src/backend/mod.rs b/src/backend/mod.rs
index d70ee2aa..8a59e6f3 100644
--- a/src/backend/mod.rs
+++ b/src/backend/mod.rs
@@ -1,5 +1,6 @@
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::output::Output;
+use smithay::wayland::dmabuf::DmabufFeedback;
use crate::input::CompositorMod;
use crate::niri::OutputRenderElements;
@@ -43,7 +44,7 @@ impl Backend {
niri: &mut Niri,
output: &Output,
elements: &[OutputRenderElements<GlesRenderer>],
- ) {
+ ) -> Option<&DmabufFeedback> {
match self {
Backend::Tty(tty) => tty.render(niri, output, elements),
Backend::Winit(winit) => winit.render(niri, output, elements),
diff --git a/src/backend/tty.rs b/src/backend/tty.rs
index 2db762fc..e5555984 100644
--- a/src/backend/tty.rs
+++ b/src/backend/tty.rs
@@ -25,9 +25,10 @@ use smithay::reexports::drm::control::{
use smithay::reexports::input::Libinput;
use smithay::reexports::nix::fcntl::OFlag;
use smithay::reexports::nix::libc::dev_t;
+use smithay::reexports::wayland_protocols::wp::linux_dmabuf::zv1::server::zwp_linux_dmabuf_feedback_v1::TrancheFlags;
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::wayland::dmabuf::{DmabufFeedbackBuilder, DmabufGlobal, DmabufState, DmabufFeedback};
use smithay_drm_extras::drm_scanner::{DrmScanEvent, DrmScanner};
use smithay_drm_extras::edid::EdidInfo;
@@ -59,7 +60,7 @@ struct OutputDevice {
gles: GlesRenderer,
formats: HashSet<DrmFormat>,
drm_scanner: DrmScanner,
- surfaces: HashMap<crtc::Handle, GbmDrmCompositor>,
+ surfaces: HashMap<crtc::Handle, (GbmDrmCompositor, DmabufFeedback)>,
dmabuf_state: DmabufState,
dmabuf_global: DmabufGlobal,
}
@@ -274,7 +275,7 @@ impl Tty {
trace!("vblank {metadata:?}");
let device = tty.output_device.as_mut().unwrap();
- let drm_compositor = device.surfaces.get_mut(&crtc).unwrap();
+ let drm_compositor = &mut device.surfaces.get_mut(&crtc).unwrap().0;
let presentation_time = match metadata.as_mut().unwrap().time {
DrmEventTime::Monotonic(time) => time,
@@ -479,6 +480,20 @@ impl Tty {
crtc,
});
+ let planes = surface.planes().unwrap();
+ let scanout_formats = surface
+ .supported_formats(planes.primary.handle)
+ .unwrap()
+ .into_iter()
+ .chain(
+ planes
+ .overlay
+ .into_iter()
+ .flat_map(|p| surface.supported_formats(p.handle).unwrap()),
+ )
+ .collect::<HashSet<_>>();
+ let scanout_formats = scanout_formats.intersection(&device.formats).copied();
+
// Create the compositor.
let compositor = DrmCompositor::new(
OutputModeSource::Auto(output.clone()),
@@ -492,7 +507,12 @@ impl Tty {
Some(device.gbm.clone()),
)?;
- let res = device.surfaces.insert(crtc, compositor);
+ let dmabuf_feedback = DmabufFeedbackBuilder::new(device.id, device.formats.clone())
+ .add_preference_tranche(device.id, Some(TrancheFlags::Scanout), scanout_formats)
+ .build()
+ .unwrap();
+
+ let res = device.surfaces.insert(crtc, (compositor, dmabuf_feedback));
assert!(res.is_none(), "crtc must not have already existed");
niri.add_output(output.clone(), Some(refresh_interval(*mode)));
@@ -541,12 +561,12 @@ impl Tty {
niri: &mut Niri,
output: &Output,
elements: &[OutputRenderElements<GlesRenderer>],
- ) {
+ ) -> Option<&DmabufFeedback> {
let _span = tracy_client::span!("Tty::render");
let device = self.output_device.as_mut().unwrap();
let tty_state: &TtyOutputState = output.user_data().get().unwrap();
- let drm_compositor = device.surfaces.get_mut(&tty_state.crtc).unwrap();
+ let (drm_compositor, dmabuf_feedback) = device.surfaces.get_mut(&tty_state.crtc).unwrap();
match drm_compositor.render_frame::<_, _, GlesTexture>(
&mut device.gles,
@@ -564,7 +584,9 @@ impl Tty {
niri.output_state
.get_mut(output)
.unwrap()
- .waiting_for_vblank = true
+ .waiting_for_vblank = true;
+
+ return Some(dmabuf_feedback);
}
Err(err) => {
error!("error queueing frame: {err}");
@@ -577,6 +599,8 @@ impl Tty {
error!("error rendering frame: {err}");
}
}
+
+ None
}
pub fn change_vt(&mut self, vt: i32) {
@@ -593,7 +617,7 @@ impl Tty {
pub fn toggle_debug_tint(&mut self) {
if let Some(device) = self.output_device.as_mut() {
- for (_, compositor) in &mut device.surfaces {
+ for (_, (compositor, _)) in &mut device.surfaces {
compositor.set_debug_flags(compositor.debug_flags() ^ DebugFlags::TINT);
}
}
diff --git a/src/backend/winit.rs b/src/backend/winit.rs
index 767bf7f4..dc2e8bc6 100644
--- a/src/backend/winit.rs
+++ b/src/backend/winit.rs
@@ -11,6 +11,7 @@ use smithay::reexports::wayland_protocols::wp::presentation_time::server::wp_pre
use smithay::reexports::winit::dpi::LogicalSize;
use smithay::reexports::winit::window::WindowBuilder;
use smithay::utils::Transform;
+use smithay::wayland::dmabuf::DmabufFeedback;
use crate::niri::OutputRenderElements;
use crate::utils::get_monotonic_time;
@@ -129,7 +130,7 @@ impl Winit {
niri: &mut Niri,
output: &Output,
elements: &[OutputRenderElements<GlesRenderer>],
- ) {
+ ) -> Option<&DmabufFeedback> {
let _span = tracy_client::span!("Winit::render");
self.backend.bind().unwrap();
@@ -152,6 +153,8 @@ impl Winit {
self.backend.window().request_redraw();
}
+
+ None
}
pub fn toggle_debug_tint(&mut self) {
diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs
index 0e330322..95fc3fa9 100644
--- a/src/handlers/mod.rs
+++ b/src/handlers/mod.rs
@@ -92,7 +92,7 @@ impl DmabufHandler for State {
match self.backend.renderer().import_dmabuf(&dmabuf, None) {
Ok(_texture) => Ok(()),
Err(err) => {
- warn!("error importing dmabuf: {err:?}");
+ debug!("error importing dmabuf: {err:?}");
Err(ImportError::Failed)
}
}
diff --git a/src/layout.rs b/src/layout.rs
index 24a51b42..06608466 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -46,6 +46,7 @@ use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
use smithay::utils::{Logical, Point, Rectangle, Scale, Size};
use smithay::wayland::compositor::{with_states, SurfaceData};
+use smithay::wayland::dmabuf::DmabufFeedback;
use smithay::wayland::shell::xdg::SurfaceCachedState;
use crate::animation::Animation;
@@ -79,6 +80,14 @@ pub trait LayoutElement: SpaceElement + PartialEq + Clone {
) where
T: Into<Duration>,
F: FnMut(&WlSurface, &SurfaceData) -> Option<Output> + Copy;
+ fn send_dmabuf_feedback<'a, P, F>(
+ &self,
+ output: &Output,
+ primary_scan_out_output: P,
+ select_dmabuf_feedback: F,
+ ) where
+ P: FnMut(&WlSurface, &SurfaceData) -> Option<Output> + Copy,
+ F: Fn(&WlSurface, &SurfaceData) -> &'a DmabufFeedback + Copy;
}
#[derive(Debug)]
@@ -220,6 +229,18 @@ impl LayoutElement for Window {
{
self.send_frame(output, time, throttle, primary_scan_out_output);
}
+
+ fn send_dmabuf_feedback<'a, P, F>(
+ &self,
+ output: &Output,
+ primary_scan_out_output: P,
+ select_dmabuf_feedback: F,
+ ) where
+ P: FnMut(&WlSurface, &SurfaceData) -> Option<Output> + Copy,
+ F: Fn(&WlSurface, &SurfaceData) -> &'a DmabufFeedback + Copy,
+ {
+ self.send_dmabuf_feedback(output, primary_scan_out_output, select_dmabuf_feedback);
+ }
}
impl ColumnWidth {
@@ -464,6 +485,16 @@ impl<W: LayoutElement> MonitorSet<W> {
}
}
+ pub fn send_dmabuf_feedback(&self, output: &Output, feedback: &DmabufFeedback) {
+ if let MonitorSet::Normal { monitors, .. } = self {
+ for mon in monitors {
+ if &mon.output == output {
+ mon.workspaces[mon.active_workspace_idx].send_dmabuf_feedback(feedback);
+ }
+ }
+ }
+ }
+
pub fn find_window_and_output(&mut self, wl_surface: &WlSurface) -> Option<(W, Output)> {
if let MonitorSet::Normal { monitors, .. } = self {
for mon in monitors {
@@ -1506,6 +1537,13 @@ impl<W: LayoutElement> Workspace<W> {
}
}
+ fn send_dmabuf_feedback(&self, feedback: &DmabufFeedback) {
+ let output = self.output.as_ref().unwrap();
+ for win in self.windows() {
+ win.send_dmabuf_feedback(output, |_, _| Some(output.clone()), |_, _| feedback);
+ }
+ }
+
fn view_pos(&self) -> i32 {
self.column_x(self.active_column_idx) + self.view_offset - PADDING
}
diff --git a/src/niri.rs b/src/niri.rs
index 364acf1d..12dad95b 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -19,8 +19,9 @@ use smithay::backend::renderer::element::{
use smithay::backend::renderer::gles::{GlesRenderer, GlesTexture};
use smithay::backend::renderer::{Bind, ExportMem, Frame, ImportAll, Offscreen, Renderer};
use smithay::desktop::utils::{
- send_frames_surface_tree, surface_presentation_feedback_flags_from_states,
- take_presentation_feedback_surface_tree, OutputPresentationFeedback,
+ send_dmabuf_feedback_surface_tree, send_frames_surface_tree,
+ surface_presentation_feedback_flags_from_states, take_presentation_feedback_surface_tree,
+ OutputPresentationFeedback,
};
use smithay::desktop::{
layer_map_for_output, LayerSurface, PopupManager, Space, Window, WindowSurfaceType,
@@ -43,6 +44,7 @@ use smithay::utils::{
};
use smithay::wayland::compositor::{with_states, CompositorClientState, CompositorState};
use smithay::wayland::data_device::DataDeviceState;
+use smithay::wayland::dmabuf::DmabufFeedback;
use smithay::wayland::output::OutputManagerState;
use smithay::wayland::pointer_gestures::PointerGesturesState;
use smithay::wayland::presentation::PresentationState;
@@ -378,7 +380,7 @@ impl Niri {
pub fn remove_output(&mut self, output: &Output) {
let mut state = self.output_state.remove(output).unwrap();
- self.display_handle.remove_global::<Niri>(state.global);
+ self.display_handle.remove_global::<State>(state.global);
if let Some(idle) = state.queued_redraw.take() {
idle.cancel();
@@ -698,12 +700,45 @@ impl Niri {
let elements = self.render(backend.renderer(), output);
// Hand it over to the backend.
- backend.render(self, output, &elements);
+ let dmabuf_feedback = backend.render(self, output, &elements);
+
+ // Send the dmabuf feedbacks.
+ if let Some(feedback) = dmabuf_feedback {
+ self.send_dmabuf_feedbacks(output, feedback);
+ }
// Send the frame callbacks.
self.send_frame_callbacks(output);
}
+ fn send_dmabuf_feedbacks(&self, output: &Output, feedback: &DmabufFeedback) {
+ let _span = tracy_client::span!("Niri::send_dmabuf_feedbacks");
+
+ self.monitor_set.send_dmabuf_feedback(output, feedback);
+
+ for surface in layer_map_for_output(output).layers() {
+ surface.send_dmabuf_feedback(output, |_, _| Some(output.clone()), |_, _| feedback);
+ }
+
+ if let Some(surface) = &self.dnd_icon {
+ send_dmabuf_feedback_surface_tree(
+ surface,
+ output,
+ |_, _| Some(output.clone()),
+ |_, _| feedback,
+ );
+ }
+
+ if let CursorImageStatus::Surface(surface) = &self.cursor_image {
+ send_dmabuf_feedback_surface_tree(
+ surface,
+ output,
+ |_, _| Some(output.clone()),
+ |_, _| feedback,
+ );
+ }
+ }
+
fn send_frame_callbacks(&self, output: &Output) {
let _span = tracy_client::span!("Niri::send_frame_callbacks");