From b07ac107b177e60da7fe48cd272d3acde5ff032f Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Thu, 12 May 2022 14:04:21 +0200 Subject: [PATCH] chore: Update to newest smithay/calloop --- Cargo.lock | 135 ++++++++++++++++++++++++++++----------- src/backend/kms/mod.rs | 139 ++++++++++++++++++++++++----------------- src/backend/winit.rs | 1 + src/backend/x11.rs | 4 +- src/config/mod.rs | 20 ++++-- src/main.rs | 9 ++- src/shell/handler.rs | 4 +- src/state.rs | 13 +++- 8 files changed, 218 insertions(+), 107 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76dce74b..2770d0f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -161,6 +161,19 @@ dependencies = [ "nix 0.22.3", ] +[[package]] +name = "calloop" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84221146483fe8a40de9af92111abd5a71ab8cf0e3c673df2b209f891a82e02e" +dependencies = [ + "log", + "nix 0.24.1", + "slotmap", + "thiserror", + "vec_map", +] + [[package]] name = "cc" version = "1.0.73" @@ -924,25 +937,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" +checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" dependencies = [ "libc", "log", - "miow", - "ntapi", "wasi 0.11.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", + "windows-sys", ] [[package]] @@ -1024,6 +1026,18 @@ dependencies = [ "memoffset", ] +[[package]] +name = "nix" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f17df307904acd05aa8e32e97bb20f2a0df1728bbc2d771ae8f9a90463441e9" +dependencies = [ + "bitflags", + "cfg-if 1.0.0", + "libc", + "memoffset", +] + [[package]] name = "nohash-hasher" version = "0.2.0" @@ -1040,15 +1054,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "ntapi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" -dependencies = [ - "winapi", -] - [[package]] name = "num-traits" version = "0.2.15" @@ -1081,9 +1086,9 @@ dependencies = [ [[package]] name = "num_threads" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aba1801fb138d8e85e11d0fc70baf4fe1cdfffda7c6cd34a854905df588e5ed0" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" dependencies = [ "libc", ] @@ -1099,9 +1104,9 @@ dependencies = [ [[package]] name = "object" -version = "0.28.3" +version = "0.28.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40bec70ba014595f99f7aa110b84331ffe1ee9aece7fe6f387cc7e3ecda4d456" +checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" dependencies = [ "memchr", ] @@ -1176,9 +1181,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" +checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" dependencies = [ "unicode-xid", ] @@ -1329,9 +1334,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f972498cf015f7c0746cac89ebe1d6ef10c293b94175a243a2d9442c163d9944" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ "itoa", "ryu", @@ -1402,6 +1407,15 @@ dependencies = [ "time", ] +[[package]] +name = "slotmap" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" +dependencies = [ + "version_check", +] + [[package]] name = "smallvec" version = "1.8.0" @@ -1411,11 +1425,11 @@ checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "smithay" version = "0.3.0" -source = "git+https://github.com/pop-os/smithay?branch=main#7e8c76d420fb60ca4e0844cc0c401837fd735f00" +source = "git+https://github.com/pop-os/smithay?branch=main#c24ac85b70606c184a973e396fe4acaae1239147" dependencies = [ "appendlist", "bitflags", - "calloop", + "calloop 0.10.0", "cgmath", "downcast-rs", "drm", @@ -1455,7 +1469,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a28f16a97fa0e8ce563b2774d1e732dd5d4025d2772c5dba0a41a0f90a29da3" dependencies = [ "bitflags", - "calloop", + "calloop 0.9.3", "dlib", "lazy_static", "log", @@ -1501,9 +1515,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" +checksum = "04066589568b72ec65f42d65a1a52436e954b168773148893c020269563decf2" dependencies = [ "proc-macro2", "quote", @@ -1635,6 +1649,12 @@ dependencies = [ "serde", ] +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "version_check" version = "0.9.4" @@ -1852,6 +1872,49 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + [[package]] name = "winit" version = "0.26.1" diff --git a/src/backend/kms/mod.rs b/src/backend/kms/mod.rs index 7b349b37..3a478f86 100644 --- a/src/backend/kms/mod.rs +++ b/src/backend/kms/mod.rs @@ -27,8 +27,8 @@ use smithay::{ }, reexports::{ calloop::{ - timer::{Timer, TimerHandle}, - Dispatcher, EventLoop, LoopHandle, RegistrationToken, + timer::{TimeoutAction, Timer}, + Dispatcher, EventLoop, InsertError, LoopHandle, RegistrationToken, }, drm::control::{connector, crtc, Device as ControlDevice, ModeTypeFlags}, input::Libinput, @@ -44,7 +44,7 @@ use std::{ collections::{HashMap, HashSet}, path::PathBuf, rc::Rc, - time::{Duration, Instant, SystemTime}, + time::Duration, }; mod drm_helpers; @@ -82,7 +82,6 @@ pub struct Surface { refresh_rate: u32, vrr: bool, pending: bool, - render_timer: TimerHandle<(DrmNode, crtc::Handle)>, render_timer_token: Option, #[cfg(feature = "debug")] fps: Fps, @@ -109,7 +108,13 @@ pub fn init_backend(event_loop: &mut EventLoop<'static, State>, state: &mut Stat } state.process_input_event(event); for output in state.common.shell.outputs() { - state.backend.kms().schedule_render(output); + if let Err(err) = state + .backend + .kms() + .schedule_render(&state.common.event_loop_handle, output) + { + slog_scope::crit!("Error scheduling event loop for output {}: {:?}", output.name(), err); + } } }) .map_err(|err| err.error) @@ -219,6 +224,7 @@ pub fn init_backend(event_loop: &mut EventLoop<'static, State>, state: &mut Stat state.common.output_conf.outputs(), &mut state.backend, &mut state.common.shell, + &state.common.event_loop_handle, ); state.common.shell.refresh_outputs(); state @@ -236,7 +242,13 @@ pub fn init_backend(event_loop: &mut EventLoop<'static, State>, state: &mut Stat surface.pending = false; } for output in state.common.shell.outputs() { - state.backend.kms().schedule_render(output); + if let Err(err) = state + .backend + .kms() + .schedule_render(&state.common.event_loop_handle, output) + { + slog_scope::crit!("Error scheduling event loop for output {}: {:?}", output.name(), err); + } } }); loop_signal.wakeup(); @@ -382,7 +394,7 @@ impl State { let mut wl_outputs = Vec::new(); let mut w = self.common.shell.global_space().size.w; for (crtc, conn) in outputs { - match device.setup_surface(crtc, conn, &mut self.common.event_loop_handle, (0, w)) { + match device.setup_surface(crtc, conn, (0, w)) { Ok(output) => { w += output .user_data() @@ -403,11 +415,12 @@ impl State { .output_conf .update(&mut *self.common.display.borrow_mut()); for output in wl_outputs { - if let Err(err) = - self.backend - .kms() - .apply_config_for_output(&output, &mut self.common.shell, false) - { + if let Err(err) = self.backend.kms().apply_config_for_output( + &output, + &mut self.common.shell, + false, + &self.common.event_loop_handle, + ) { slog_scope::warn!("Failed to initialize output: {}", err); } } @@ -415,6 +428,7 @@ impl State { self.common.output_conf.outputs(), &mut self.backend, &mut self.common.shell, + &self.common.event_loop_handle, ); self.common.shell.refresh_outputs(); self.common @@ -445,7 +459,7 @@ impl State { } } for (crtc, conn) in changes.added { - match device.setup_surface(crtc, conn, &mut self.common.event_loop_handle, (0, w)) { + match device.setup_surface(crtc, conn, (0, w)) { Ok(output) => { w += output .user_data() @@ -464,11 +478,12 @@ impl State { self.common.output_conf.remove_heads(outputs_removed.iter()); self.common.output_conf.add_heads(outputs_added.iter()); for output in outputs_added { - if let Err(err) = - self.backend - .kms() - .apply_config_for_output(&output, &mut self.common.shell, false) - { + if let Err(err) = self.backend.kms().apply_config_for_output( + &output, + &mut self.common.shell, + false, + &self.common.event_loop_handle, + ) { slog_scope::warn!("Failed to initialize output: {}", err); } } @@ -479,6 +494,7 @@ impl State { self.common.output_conf.outputs(), &mut self.backend, &mut self.common.shell, + &self.common.event_loop_handle, ); self.common.shell.refresh_outputs(); self.common @@ -515,6 +531,7 @@ impl State { self.common.output_conf.outputs(), &mut self.backend, &mut self.common.shell, + &self.common.event_loop_handle, ); self.common.shell.refresh_outputs(); self.common @@ -563,7 +580,6 @@ impl Device { &mut self, crtc: crtc::Handle, conn: connector::Handle, - loop_handle: &mut LoopHandle<'static, State>, position: (i32, i32), ) -> Result { let drm = &mut *self.drm.as_source_mut(); @@ -622,27 +638,6 @@ impl Device { }) }); - let timer = Timer::new()?; - let timer_handle = timer.handle(); - // render timer - let timer_token = loop_handle - .insert_source(timer, |(dev_id, crtc), _, state| { - let backend = state.backend.kms(); - if let Some(device) = backend.devices.get_mut(&dev_id) { - if let Some(surface) = device.surfaces.get_mut(&crtc) { - if let Err(err) = surface.render_output( - &mut backend.api, - &device.render_node, - &mut state.common, - ) { - slog_scope::error!("Error rendering: {}", err); - // TODO re-schedule? - } - } - } - }) - .unwrap(); - let data = Surface { output: output.clone(), surface: None, @@ -651,8 +646,7 @@ impl Device { refresh_rate, last_submit: None, pending: false, - render_timer: timer_handle, - render_timer_token: Some(timer_token), + render_timer_token: None, #[cfg(feature = "debug")] fps: Fps::default(), }; @@ -756,6 +750,7 @@ impl KmsState { output: &Output, shell: &mut Shell, test_only: bool, + loop_handle: &LoopHandle<'_, State>, ) -> Result<(), anyhow::Error> { let recreated = if let Some(device) = self .devices @@ -840,12 +835,18 @@ impl KmsState { shell.refresh_outputs(); if recreated { - self.schedule_render(output); + if let Err(err) = self.schedule_render(loop_handle, output) { + slog_scope::crit!("Error scheduling event loop for output {}: {:?}", output.name(), err); + } } Ok(()) } - pub fn schedule_render(&mut self, output: &Output) { + pub fn schedule_render( + &mut self, + loop_handle: &LoopHandle<'_, State>, + output: &Output, + ) -> Result<(), InsertError> { if let Some((device, crtc, surface)) = self .devices .iter_mut() @@ -853,29 +854,53 @@ impl KmsState { .find(|(_, _, s)| s.output == *output) { if surface.surface.is_none() { - return; + return Ok(()); } if !surface.pending { surface.pending = true; /* - let duration = surface + let instant = surface .last_submit .as_ref() .and_then(|x| match x { - DrmEventTime::Monotonic(instant) => { - instant.checked_duration_since(Instant::now()) - } - DrmEventTime::Realtime(time) => time.duration_since(SystemTime::now()).ok(), + DrmEventTime::Monotonic(instant) => Some(instant), + DrmEventTime::Realtime(_) => None, }) - .unwrap_or(Duration::ZERO); // + Duration::from_secs_f64((1.0 / surface.refresh_rate as f64) - 20.0); + .map(|i| { + *i + Duration::from_secs_f64(1.0 / surface.refresh_rate as f64) + - Duration::from_millis(20) // render budget + }); */ - let data = (*device, *crtc); - //if surface.vrr { - surface.render_timer.add_timeout(Duration::ZERO, data); - //} else { - // surface.render_timer.add_timeout(duration, data); - //} + + let device = *device; + let crtc = *crtc; + surface.render_timer_token = Some(loop_handle.insert_source( + //if surface.vrr || instant.is_none() { + Timer::immediate() + /*} else { + Timer::from_deadline(instant.unwrap()) + }*/, + move |_time, _, state| { + let backend = state.backend.kms(); + if let Some(device) = backend.devices.get_mut(&device) { + if let Some(surface) = device.surfaces.get_mut(&crtc) { + if let Err(err) = surface.render_output( + &mut backend.api, + &device.render_node, + &mut state.common, + ) { + slog_scope::error!("Error rendering: {}", err); + return TimeoutAction::ToDuration(Duration::from_secs_f64( + 1.0 / surface.refresh_rate as f64, + )); + } + } + } + TimeoutAction::Drop + }, + )?); } } + Ok(()) } } diff --git a/src/backend/winit.rs b/src/backend/winit.rs index 6d656b1d..6ff37569 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -210,6 +210,7 @@ pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Res std::iter::once(&output), &mut state.backend, &mut state.common.shell, + &state.common.event_loop_handle, ); state.common.shell.refresh_outputs(); state.common.config.write_outputs(std::iter::once(&output)); diff --git a/src/backend/x11.rs b/src/backend/x11.rs index ca54d124..918a61b7 100644 --- a/src/backend/x11.rs +++ b/src/backend/x11.rs @@ -268,6 +268,7 @@ pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Res std::iter::once(&output), &mut state.backend, &mut state.common.shell, + &state.common.event_loop_handle, ); state.common.shell.refresh_outputs(); state.common.config.write_outputs(std::iter::once(&output)); @@ -414,7 +415,8 @@ impl State { self.process_input_event(event); // TODO actually figure out the output for output in self.common.shell.outputs() { - self.backend.schedule_render(output); + self.backend + .schedule_render(&self.common.event_loop_handle, output); } } } diff --git a/src/config/mod.rs b/src/config/mod.rs index b4a4c4de..ea603e3e 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -2,14 +2,17 @@ use crate::{ shell::{layout::FocusDirection, Shell}, - state::BackendData, + state::{BackendData, State}, }; use serde::{Deserialize, Serialize}; pub use smithay::{ backend::input::KeyState, - reexports::input::{ - AccelProfile, ClickMethod, Device as InputDevice, ScrollMethod, SendEventsMode, - TapButtonMap, + reexports::{ + calloop::LoopHandle, + input::{ + AccelProfile, ClickMethod, Device as InputDevice, ScrollMethod, SendEventsMode, + TapButtonMap, + }, }, utils::{Logical, Physical, Point, Size, Transform}, wayland::{ @@ -270,6 +273,7 @@ impl Config { outputs: impl Iterator>, backend: &mut BackendData, shell: &mut Shell, + loop_handle: &LoopHandle<'_, State>, ) { let outputs = outputs.map(|x| x.borrow().clone()).collect::>(); let mut infos = outputs @@ -300,7 +304,9 @@ impl Config { .get::>() .unwrap() .borrow_mut() = output_config; - if let Err(err) = backend.apply_config_for_output(&output, false, shell) { + if let Err(err) = + backend.apply_config_for_output(&output, false, shell, loop_handle) + { slog_scope::warn!( "Failed to set new config for output {}: {}", output.name(), @@ -322,7 +328,9 @@ impl Config { .get::>() .unwrap() .borrow_mut() = output_config; - if let Err(err) = backend.apply_config_for_output(&output, false, shell) { + if let Err(err) = + backend.apply_config_for_output(&output, false, shell, loop_handle) + { slog_scope::error!( "Failed to reset config for output {}: {}", output.name(), diff --git a/src/main.rs b/src/main.rs index 34586d60..69840bf9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,7 +27,8 @@ fn main() -> Result<()> { slog_scope::info!("Cosmic starting up!"); // init event loop - let mut event_loop = EventLoop::try_new().with_context(|| "Failed to initialize event loop")?; + let mut event_loop = + EventLoop::try_new_high_precision().with_context(|| "Failed to initialize event loop")?; // init wayland let (display, socket) = init_wayland_display(&mut event_loop)?; // init state @@ -56,7 +57,9 @@ fn main() -> Result<()> { // do we need to trigger another render if state.common.dirty_flag.swap(false, Ordering::SeqCst) { for output in state.common.shell.outputs() { - state.backend.schedule_render(output) + state + .backend + .schedule_render(&state.common.event_loop_handle, output) } } @@ -83,7 +86,7 @@ fn init_wayland_display(event_loop: &mut EventLoop) -> Result<(Dis event_loop .handle() .insert_source( - Generic::from_fd(display.get_poll_fd(), Interest::READ, Mode::Level), + Generic::new(display.get_poll_fd(), Interest::READ, Mode::Level), move |_, _, state: &mut state::State| { let display = state.common.display.clone(); let mut display = display.borrow_mut(); diff --git a/src/shell/handler.rs b/src/shell/handler.rs index 9bebb1f3..d460dcce 100644 --- a/src/shell/handler.rs +++ b/src/shell/handler.rs @@ -312,7 +312,9 @@ fn commit(surface: &WlSurface, state: &mut State) { // TODO figure out which output the surface is on. for output in state.common.shell.outputs() { //.cloned().collect::>().into_iter() { - state.backend.schedule_render(output); + state + .backend + .schedule_render(&state.common.event_loop_handle, output); // let space = state.common.spaces.active_space(output); // get output for surface } diff --git a/src/state.rs b/src/state.rs index 02431f11..4434bd69 100644 --- a/src/state.rs +++ b/src/state.rs @@ -118,10 +118,11 @@ impl BackendData { output: &Output, test_only: bool, shell: &mut Shell, + loop_handle: &LoopHandle<'_, State>, ) -> Result<(), anyhow::Error> { let result = match self { BackendData::Kms(ref mut state) => { - state.apply_config_for_output(output, shell, test_only) + state.apply_config_for_output(output, shell, test_only, loop_handle) } BackendData::Winit(ref mut state) => state.apply_config_for_output(output, test_only), BackendData::X11(ref mut state) => state.apply_config_for_output(output, test_only), @@ -155,13 +156,17 @@ impl BackendData { result } - pub fn schedule_render(&mut self, output: &Output) { + pub fn schedule_render(&mut self, loop_handle: &LoopHandle<'_, State>, output: &Output) { match self { BackendData::Winit(_) => {} // We cannot do this on the winit backend. // Winit has a very strict render-loop and skipping frames breaks atleast the wayland winit-backend. // Swapping with damage (which should be empty on these frames) is likely good enough anyway. BackendData::X11(ref mut state) => state.schedule_render(output), - BackendData::Kms(ref mut state) => state.schedule_render(output), + BackendData::Kms(ref mut state) => { + if let Err(err) = state.schedule_render(loop_handle, output) { + slog_scope::crit!("Failed to schedule event, are we shutting down? {:?}", err); + } + } _ => unreachable!("No backend was initialized"), } } @@ -264,6 +269,7 @@ impl State { output, test_only, &mut state.common.shell, + &state.common.event_loop_handle, ) { slog_scope::warn!( "Failed to apply config to {}: {}. Resetting", @@ -284,6 +290,7 @@ impl State { output, false, &mut state.common.shell, + &state.common.event_loop_handle, ) { slog_scope::error!( "Failed to reset output config for {}: {}",