diff --git a/src/backend/kms/device.rs b/src/backend/kms/device.rs index 42b8fb78..41329f94 100644 --- a/src/backend/kms/device.rs +++ b/src/backend/kms/device.rs @@ -253,7 +253,7 @@ impl State { self.backend.kms().drm_devices.insert(drm_node, device); } - self.backend.kms().refresh_used_devices(); + self.backend.kms().refresh_used_devices()?; self.common .output_configuration_state @@ -345,7 +345,7 @@ impl State { } } - self.backend.kms().refresh_used_devices(); + self.backend.kms().refresh_used_devices()?; self.common .output_configuration_state diff --git a/src/backend/kms/mod.rs b/src/backend/kms/mod.rs index 51bead35..b4f4eb76 100644 --- a/src/backend/kms/mod.rs +++ b/src/backend/kms/mod.rs @@ -1,14 +1,10 @@ // SPDX-License-Identifier: GPL-3.0-only -use crate::{ - config::OutputState, shell::Shell, state::BackendData, utils::prelude::*, - wayland::handlers::output, -}; +use crate::{config::OutputState, shell::Shell, state::BackendData, utils::prelude::*}; use anyhow::{Context, Result}; use calloop::LoopSignal; use render::gles::GbmGlowBackend; -use smallvec::SmallVec; use smithay::{ backend::{ allocator::{ @@ -87,10 +83,9 @@ pub fn init_backend( .context("Failed to initialize udev connection")?; // handle session events - let handle = event_loop.handle(); let loop_signal = event_loop.get_signal(); let dispatcher = udev_dispatcher.clone(); - let session_event_source = event_loop + event_loop .handle() .insert_source(notifier, move |event, &mut (), state| match event { SessionEvent::ActivateSession => { @@ -226,7 +221,8 @@ fn init_udev( } }); - let udev_event_source = evlh.register_dispatcher(dispatcher.clone()).unwrap(); + evlh.register_dispatcher(dispatcher.clone()) + .context("Failed to register udev event source")?; Ok(dispatcher) } @@ -622,8 +618,9 @@ impl KmsState { )?); } std::mem::drop(output_config); - surface.set_mode(*mode); - // TODO: .context("Failed to apply new mode")?; + surface + .set_mode(*mode) + .context("Failed to apply new mode")?; } } } diff --git a/src/backend/kms/surface/mod.rs b/src/backend/kms/surface/mod.rs index a2d005c3..cc96b59a 100644 --- a/src/backend/kms/surface/mod.rs +++ b/src/backend/kms/surface/mod.rs @@ -17,6 +17,7 @@ use crate::{ }; use anyhow::{Context, Result}; +use calloop::channel::Channel; use smithay::{ backend::{ allocator::{ @@ -80,7 +81,6 @@ use std::{ mpsc::{Receiver, SyncSender}, Arc, Condvar, Mutex, RwLock, }, - thread::JoinHandle, time::Duration, }; @@ -110,7 +110,6 @@ pub struct Surface { loop_handle: LoopHandle<'static, State>, thread_command: Sender, - thread_handle: JoinHandle<()>, thread_token: RegistrationToken, } @@ -234,8 +233,7 @@ pub enum ThreadCommand { UpdateMirroring(Option), VBlank(Option), ScheduleRender, - // TODO: Error handling - SetMode(Mode), + SetMode(Mode, SyncSender>), End, } @@ -262,220 +260,29 @@ impl Surface { let (tx, rx) = channel::(); let (tx2, rx2) = channel::(); let active = Arc::new(AtomicBool::new(false)); - let active_clone = active.clone(); + let active_clone = active.clone(); let frame_callback_seq_clone = frame_callback_seq.clone(); let output_clone = output.clone(); - let thread_handle = std::thread::spawn(move || { - profiling::register_thread!(format!("Surface Thread {}", output.name())); - let mut event_loop = EventLoop::try_new().unwrap(); - - let api = GpuManager::new(GbmGlowBackend::::default()) - .expect("Failed to initialize rendering"); - /* - let software_api = GpuManager::new(GbmPixmanBackend::::with_allocator_flags( - gbm_flags, - )) - .context("Failed to initialize software rendering"); - */ - - #[cfg(feature = "debug")] - let egui = { - let state = smithay_egui::EguiState::new( - smithay::utils::Rectangle::from_loc_and_size((0, 0), (400, 800)), - ); - let mut visuals: egui::style::Visuals = Default::default(); - visuals.window_shadow.extrusion = 0.0; - state.context().set_visuals(visuals); - state - }; - - let mut state = SurfaceThreadState { - api, - primary_node, - target_node, - active: active_clone, - compositor: None, - - state: QueueState::Idle, - timings: Timings::new(None, false), - frame_callback_seq: frame_callback_seq_clone, - thread_sender: tx2, - - output: output_clone, - mirroring: None, - mirroring_textures: HashMap::new(), - - shell, - loop_handle: event_loop.handle(), - clock: Clock::new(), - #[cfg(feature = "debug")] - egui, - }; - - let signal = event_loop.get_signal(); - event_loop - .handle() - .insert_source(rx, move |command, _, state| match command { - Event::Msg(ThreadCommand::Suspend) => { - state.active.store(false, Ordering::SeqCst); - let _ = state.compositor.take(); - - match std::mem::replace(&mut state.state, QueueState::Idle) { - QueueState::Idle => {} - QueueState::Queued(token) - | QueueState::WaitingForEstimatedVBlank(token) => { - state.loop_handle.remove(token); - } - QueueState::WaitingForVBlank { .. } => { - state.timings.discard_current_frame() - } - QueueState::WaitingForEstimatedVBlankAndQueued { - estimated_vblank, - queued_render, - } => { - state.loop_handle.remove(estimated_vblank); - state.loop_handle.remove(queued_render); - } - }; - } - Event::Msg(ThreadCommand::Resume { - surface, - gbm, - cursor_size, - vrr, - result, - }) => { - let driver = surface.get_driver().ok(); - let mut planes = surface.planes().clone(); - - // QUIRK: Using an overlay plane on a nvidia card breaks the display controller (wtf...) - if driver.is_some_and(|driver| { - driver - .name() - .to_string_lossy() - .to_lowercase() - .contains("nvidia") - }) { - planes.overlay = vec![]; - } - - let render_formats = state - .api - .single_renderer(&state.target_node) - .unwrap() - .dmabuf_formats() - .collect(); - - state - .timings - .set_refresh_interval(Some(Duration::from_nanos( - drm_helpers::calculate_refresh_rate(surface.pending_mode()) as u64, - ))); - state.timings.set_vrr(vrr); - - match DrmCompositor::new( - &state.output, - surface, - Some(planes), - GbmAllocator::new( - gbm.clone(), - GbmBufferFlags::RENDERING | GbmBufferFlags::SCANOUT, - ), - gbm.clone(), - &[ - Fourcc::Abgr2101010, - Fourcc::Argb2101010, - Fourcc::Abgr8888, - Fourcc::Argb8888, - ], - render_formats, - cursor_size, - Some(gbm), - ) { - Ok(compositor) => { - state.active.store(true, Ordering::SeqCst); - state.compositor = Some(compositor); - let _ = result.send(Ok(())); - } - Err(err) => { - state.active.store(false, Ordering::SeqCst); - let _ = result.send(Err(err.into())); - } - } - } - Event::Msg(ThreadCommand::NodeAdded { node, gbm, egl }) => { - //if let Some(egl) = egl { - let mut renderer = - unsafe { GlowRenderer::new(egl) }.expect("Failed to create renderer"); - init_shaders(renderer.borrow_mut()); - - state.api.as_mut().add_node(node, gbm, renderer); - /* - } else { - state.software_api.as_mut().add_node(node, gbm); - } - */ - - #[cfg(feature = "debug")] - { - let renderer = state.api.single_renderer(node); - state - .egui - .load_svg(renderer, String::from("intel"), INTEL_LOGO) - .unwrap(); - state - .egui - .load_svg(renderer, String::from("amd"), AMD_LOGO) - .unwrap(); - state - .egui - .load_svg(renderer, String::from("nvidia"), NVIDIA_LOGO) - .unwrap(); - } - } - Event::Msg(ThreadCommand::NodeRemoved { node }) => { - state.api.as_mut().remove_node(&node); - //state.software_api.as_mut().remove_node(node); - } - Event::Msg(ThreadCommand::VBlank(metadata)) => { - state.on_vblank(metadata); - } - Event::Msg(ThreadCommand::ScheduleRender) => { - { - // Wait for start up. - let (lock, cvar) = &*startup_done; - // As long as the value inside the `Mutex` is `false`, we wait. - let _guard = cvar - .wait_while(lock.lock().unwrap(), |startup_done| !*startup_done) - .unwrap(); - } - - state.queue_redraw(false); - } - Event::Msg(ThreadCommand::UpdateMirroring(mirroring)) => { - state.mirroring = mirroring; - state.mirroring_textures.clear(); - } - Event::Msg(ThreadCommand::SetMode(mode)) => { - if let Some(compositor) = state.compositor.as_mut() { - compositor.use_mode(mode); - } - } - Event::Closed | Event::Msg(ThreadCommand::End) => { - signal.stop(); - signal.wakeup(); - } - }) - .unwrap(); - - if let Err(err) = event_loop.run(None, &mut state, |_| { - // TODO: if queued, but token invalid, schedule redraw timer again - }) { - error!("Surface thread crashed: {}", err); - } - }); + std::thread::Builder::new() + .name(format!("surface-{}", output.name())) + .spawn(move || { + if let Err(err) = surface_thread( + output_clone, + primary_node, + target_node, + shell, + active_clone, + frame_callback_seq_clone, + tx2, + rx, + startup_done, + ) { + error!("Surface thread crashed: {}", err); + } + }) + .context("Failed to spawn surface thread")?; let output_clone = output.clone(); let thread_token = evlh @@ -540,46 +347,54 @@ impl Surface { plane_formats: HashSet::new(), loop_handle: evlh.clone(), thread_command: tx, - thread_handle, thread_token, }) } - pub fn add_node(&mut self, node: DrmNode, gbm: GbmAllocator, egl: EGLContext) { - self.known_nodes.insert(node); - self.thread_command - .send(ThreadCommand::NodeAdded { node, gbm, egl }); - } - - pub fn remove_node(&mut self, node: DrmNode) { - self.known_nodes.remove(&node); - self.thread_command - .send(ThreadCommand::NodeRemoved { node }); - } - pub fn known_nodes(&self) -> &HashSet { &self.known_nodes } + pub fn is_active(&self) -> bool { + self.active.load(Ordering::SeqCst) + } + + pub fn add_node(&mut self, node: DrmNode, gbm: GbmAllocator, egl: EGLContext) { + self.known_nodes.insert(node); + let _ = self + .thread_command + .send(ThreadCommand::NodeAdded { node, gbm, egl }); + } + + pub fn remove_node(&mut self, node: DrmNode) { + self.known_nodes.remove(&node); + let _ = self + .thread_command + .send(ThreadCommand::NodeRemoved { node }); + } + pub fn on_vblank(&self, metadata: Option) { - self.thread_command.send(ThreadCommand::VBlank(metadata)); + let _ = self.thread_command.send(ThreadCommand::VBlank(metadata)); } pub fn schedule_render(&self) { - self.thread_command.send(ThreadCommand::ScheduleRender); + let _ = self.thread_command.send(ThreadCommand::ScheduleRender); } pub fn set_mirroring(&mut self, output: Option) { - self.thread_command + let _ = self + .thread_command .send(ThreadCommand::UpdateMirroring(output)); } - pub fn set_mode(&mut self, mode: Mode) { - self.thread_command.send(ThreadCommand::SetMode(mode)); + pub fn set_mode(&mut self, mode: Mode) -> Result<()> { + let (tx, rx) = std::sync::mpsc::sync_channel(1); + let _ = self.thread_command.send(ThreadCommand::SetMode(mode, tx)); + rx.recv().context("Surface thread died")? } pub fn suspend(&mut self) { - self.thread_command.send(ThreadCommand::Suspend); + let _ = self.thread_command.send(ThreadCommand::Suspend); } pub fn resume( @@ -615,10 +430,6 @@ impl Surface { rx.recv().context("Surface thread died")? } - - pub fn is_active(&self) -> bool { - self.active.load(Ordering::SeqCst) - } } impl Drop for Surface { @@ -628,7 +439,246 @@ impl Drop for Surface { } } +fn surface_thread( + output: Output, + primary_node: DrmNode, + target_node: DrmNode, + shell: Arc>, + active: Arc, + frame_callback_seq: Arc, + thread_sender: Sender, + thread_receiver: Channel, + startup_done: Arc<(Mutex, Condvar)>, +) -> Result<()> { + profiling::register_thread!(format!("Surface Thread {}", output.name())); + + let mut event_loop = EventLoop::try_new().unwrap(); + + let api = GpuManager::new(GbmGlowBackend::::default()) + .context("Failed to initialize rendering api")?; + /* + let software_api = GpuManager::new(GbmPixmanBackend::::with_allocator_flags( + gbm_flags, + )) + .context("Failed to initialize software rendering"); + */ + + #[cfg(feature = "debug")] + let egui = { + let state = smithay_egui::EguiState::new(smithay::utils::Rectangle::from_loc_and_size( + (0, 0), + (400, 800), + )); + let mut visuals: egui::style::Visuals = Default::default(); + visuals.window_shadow.extrusion = 0.0; + state.context().set_visuals(visuals); + state + }; + + let mut state = SurfaceThreadState { + api, + primary_node, + target_node, + active, + compositor: None, + + state: QueueState::Idle, + timings: Timings::new(None, false), + frame_callback_seq, + thread_sender, + + output, + mirroring: None, + mirroring_textures: HashMap::new(), + + shell, + loop_handle: event_loop.handle(), + clock: Clock::new(), + #[cfg(feature = "debug")] + egui, + }; + + let signal = event_loop.get_signal(); + event_loop + .handle() + .insert_source(thread_receiver, move |command, _, state| match command { + Event::Msg(ThreadCommand::Suspend) => state.suspend(), + Event::Msg(ThreadCommand::Resume { + surface, + gbm, + cursor_size, + vrr, + result, + }) => { + let _ = result.send(state.resume(surface, gbm, cursor_size, vrr)); + } + Event::Msg(ThreadCommand::NodeAdded { node, gbm, egl }) => { + if let Err(err) = state.node_added(node, gbm, egl) { + warn!(?err, ?node, "Failed to add node to surface-thread"); + } + } + Event::Msg(ThreadCommand::NodeRemoved { node }) => { + state.node_removed(node); + } + Event::Msg(ThreadCommand::VBlank(metadata)) => { + state.on_vblank(metadata); + } + Event::Msg(ThreadCommand::ScheduleRender) => { + { + // Wait for start up. + let (lock, cvar) = &*startup_done; + // As long as the value inside the `Mutex` is `false`, we wait. + let _guard = cvar + .wait_while(lock.lock().unwrap(), |startup_done| !*startup_done) + .unwrap(); + } + + state.queue_redraw(false); + } + Event::Msg(ThreadCommand::UpdateMirroring(mirroring_output)) => { + state.update_mirroring(mirroring_output); + } + Event::Msg(ThreadCommand::SetMode(mode, result)) => { + if let Some(compositor) = state.compositor.as_mut() { + let _ = result.send(compositor.use_mode(mode).map_err(Into::into)); + } + } + Event::Closed | Event::Msg(ThreadCommand::End) => { + signal.stop(); + signal.wakeup(); + } + }) + .map_err(|insert_error| insert_error.error) + .context("Failed to listen for events")?; + + event_loop.run(None, &mut state, |_| {}).map_err(Into::into) +} + impl SurfaceThreadState { + fn suspend(&mut self) { + self.active.store(false, Ordering::SeqCst); + let _ = self.compositor.take(); + + match std::mem::replace(&mut self.state, QueueState::Idle) { + QueueState::Idle => {} + QueueState::Queued(token) | QueueState::WaitingForEstimatedVBlank(token) => { + self.loop_handle.remove(token); + } + QueueState::WaitingForVBlank { .. } => self.timings.discard_current_frame(), + QueueState::WaitingForEstimatedVBlankAndQueued { + estimated_vblank, + queued_render, + } => { + self.loop_handle.remove(estimated_vblank); + self.loop_handle.remove(queued_render); + } + }; + } + + fn resume( + &mut self, + surface: DrmSurface, + gbm: GbmDevice, + cursor_size: Size, + vrr: bool, + ) -> Result<()> { + let driver = surface.get_driver().ok(); + let mut planes = surface.planes().clone(); + + // QUIRK: Using an overlay plane on a nvidia card breaks the display controller (wtf...) + if driver.is_some_and(|driver| { + driver + .name() + .to_string_lossy() + .to_lowercase() + .contains("nvidia") + }) { + planes.overlay = vec![]; + } + + let render_formats = self + .api + .single_renderer(&self.target_node) + .unwrap() + .dmabuf_formats() + .collect(); + + self.timings.set_refresh_interval(Some(Duration::from_nanos( + drm_helpers::calculate_refresh_rate(surface.pending_mode()) as u64, + ))); + self.timings.set_vrr(vrr); + + match DrmCompositor::new( + &self.output, + surface, + Some(planes), + GbmAllocator::new( + gbm.clone(), + GbmBufferFlags::RENDERING | GbmBufferFlags::SCANOUT, + ), + gbm.clone(), + &[ + Fourcc::Abgr2101010, + Fourcc::Argb2101010, + Fourcc::Abgr8888, + Fourcc::Argb8888, + ], + render_formats, + cursor_size, + Some(gbm), + ) { + Ok(compositor) => { + self.active.store(true, Ordering::SeqCst); + self.compositor = Some(compositor); + Ok(()) + } + Err(err) => { + self.active.store(false, Ordering::SeqCst); + Err(err.into()) + } + } + } + + fn node_added( + &mut self, + node: DrmNode, + gbm: GbmAllocator, + egl: EGLContext, + ) -> Result<()> { + //if let Some(egl) = egl { + let mut renderer = + unsafe { GlowRenderer::new(egl) }.context("Failed to create renderer")?; + init_shaders(renderer.borrow_mut()).context("Failed to initialize shaders")?; + + self.api.as_mut().add_node(node, gbm, renderer); + /* + } else { + self.software_api.as_mut().add_node(node, gbm); + } + */ + + #[cfg(feature = "debug")] + { + let renderer = self.api.single_renderer(node); + self.egui + .load_svg(renderer, String::from("intel"), INTEL_LOGO) + .unwrap(); + self.egui + .load_svg(renderer, String::from("amd"), AMD_LOGO) + .unwrap(); + self.egui + .load_svg(renderer, String::from("nvidia"), NVIDIA_LOGO) + .unwrap(); + } + + Ok(()) + } + + fn node_removed(&mut self, node: DrmNode) { + self.api.as_mut().remove_node(&node); + //self.software_api.as_mut().remove_node(node); + } + fn on_vblank(&mut self, metadata: Option) { let Some(compositor) = self.compositor.as_mut() else { return; @@ -1254,14 +1304,20 @@ impl SurfaceThreadState { self.state = QueueState::WaitingForEstimatedVBlank(token); } + fn update_mirroring(&mut self, mirroring_output: Option) { + self.mirroring = mirroring_output; + self.mirroring_textures.clear(); + } + fn send_frame_callbacks(&mut self) { if self.mirroring.is_none() { - self.thread_sender.send(SurfaceCommand::SendFrames); + let _ = self.thread_sender.send(SurfaceCommand::SendFrames); } } fn send_dmabuf_feedback(&mut self, states: RenderElementStates) { - self.thread_sender + let _ = self + .thread_sender .send(SurfaceCommand::RenderStates(states)); } } diff --git a/src/main.rs b/src/main.rs index b11a9d85..3b33c5cf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -146,9 +146,7 @@ fn main() -> Result<()> { let shell = state.common.shell.read().unwrap(); if shell.animations_going() { for output in shell.outputs().cloned().collect::>().into_iter() { - state - .backend - .schedule_render(&state.common.event_loop_handle, &output); + state.backend.schedule_render(&output); } } } diff --git a/src/shell/element/stack.rs b/src/shell/element/stack.rs index 8a61873d..a9945afb 100644 --- a/src/shell/element/stack.rs +++ b/src/shell/element/stack.rs @@ -56,7 +56,6 @@ use smithay::{ }; use std::{ borrow::Cow, - cell::RefCell, fmt, hash::Hash, sync::{ diff --git a/src/shell/mod.rs b/src/shell/mod.rs index ddfbb717..af479dea 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -649,7 +649,7 @@ impl Workspaces { return; } - if let Some(set) = self.sets.remove(output) { + if let Some(set) = self.sets.shift_remove(output) { { let map = layer_map_for_output(output); for surface in map.layers() { diff --git a/src/state.rs b/src/state.rs index 5337c3e0..f258dc01 100644 --- a/src/state.rs +++ b/src/state.rs @@ -98,11 +98,11 @@ use time::UtcOffset; use std::{ cell::RefCell, - collections::{HashSet, VecDeque}, + collections::HashSet, ffi::OsString, process::Child, sync::{Arc, Condvar, Mutex, Once, RwLock}, - time::{Duration, Instant}, + time::Duration, }; #[derive(RustEmbed)] @@ -326,13 +326,13 @@ impl BackendData { layer_map_for_output(&output).arrange(); - self.schedule_render(loop_handle, &output); + self.schedule_render(&output); } Ok(()) } - pub fn schedule_render(&mut self, loop_handle: &LoopHandle<'_, State>, output: &Output) { + pub fn schedule_render(&mut self, 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. diff --git a/src/wayland/handlers/buffer.rs b/src/wayland/handlers/buffer.rs index fd7d6255..b638d1fb 100644 --- a/src/wayland/handlers/buffer.rs +++ b/src/wayland/handlers/buffer.rs @@ -5,6 +5,7 @@ use smithay::{ reexports::wayland_server::{protocol::wl_buffer::WlBuffer, Resource}, wayland::buffer::BufferHandler, }; +use tracing::warn; impl BufferHandler for State { fn buffer_destroyed(&mut self, buffer: &WlBuffer) { @@ -12,7 +13,9 @@ impl BufferHandler for State { for device in kms_state.drm_devices.values_mut() { if device.active_buffers.remove(&buffer.downgrade()) { if !device.in_use(kms_state.primary_node.as_ref()) { - kms_state.refresh_used_devices(); + if let Err(err) = kms_state.refresh_used_devices() { + warn!(?err, "Failed to init devices."); + }; break; } } diff --git a/src/wayland/handlers/compositor.rs b/src/wayland/handlers/compositor.rs index b3c5f09c..b596b194 100644 --- a/src/wayland/handlers/compositor.rs +++ b/src/wayland/handlers/compositor.rs @@ -148,8 +148,7 @@ impl CompositorHandler for State { // schedule a new render if let Some(output) = shell.visible_output_for_surface(surface) { - self.backend - .schedule_render(&self.common.event_loop_handle, &output); + self.backend.schedule_render(&output); } if mapped { diff --git a/src/wayland/handlers/dmabuf.rs b/src/wayland/handlers/dmabuf.rs index b823dedd..b0e81098 100644 --- a/src/wayland/handlers/dmabuf.rs +++ b/src/wayland/handlers/dmabuf.rs @@ -7,6 +7,7 @@ use smithay::{ reexports::wayland_server::Resource, wayland::dmabuf::{DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier}, }; +use tracing::warn; impl DmabufHandler for State { fn dmabuf_state(&mut self) -> &mut DmabufState { @@ -41,7 +42,9 @@ impl DmabufHandler for State { { device.active_buffers.insert(buffer.downgrade()); } - kms_state.refresh_used_devices(); + if let Err(err) = kms_state.refresh_used_devices() { + warn!(?err, "Failed to init devices."); + }; } } Ok(None) => { diff --git a/src/wayland/handlers/drm.rs b/src/wayland/handlers/drm.rs index bb810d8a..27fa5418 100644 --- a/src/wayland/handlers/drm.rs +++ b/src/wayland/handlers/drm.rs @@ -9,6 +9,7 @@ use smithay::{ reexports::wayland_server::{protocol::wl_buffer::WlBuffer, Resource}, wayland::dmabuf::DmabufGlobal, }; +use tracing::warn; impl DrmHandler> for State { fn dmabuf_imported( @@ -33,7 +34,9 @@ impl DrmHandler> for State { device.active_buffers.insert(buffer.downgrade()); } - kms_state.refresh_used_devices(); + if let Err(err) = kms_state.refresh_used_devices() { + warn!(?err, "Failed to init devices."); + }; } } } diff --git a/src/wayland/handlers/layer_shell.rs b/src/wayland/handlers/layer_shell.rs index 573057ef..876cbdb3 100644 --- a/src/wayland/handlers/layer_shell.rs +++ b/src/wayland/handlers/layer_shell.rs @@ -71,8 +71,7 @@ impl WlrLayerShellHandler for State { shell.workspaces.recalculate(); - self.backend - .schedule_render(&self.common.event_loop_handle, &output); + self.backend.schedule_render(&output); } } } diff --git a/src/wayland/handlers/screencopy/mod.rs b/src/wayland/handlers/screencopy/mod.rs index 5d70fbce..6e7bc2a1 100644 --- a/src/wayland/handlers/screencopy/mod.rs +++ b/src/wayland/handlers/screencopy/mod.rs @@ -260,8 +260,7 @@ impl ScreencopyHandler for State { }; output.add_frame(session, frame); - self.backend - .schedule_render(&self.common.event_loop_handle, &output); + self.backend.schedule_render(&output); } ImageSourceData::Workspace(handle) => { render_workspace_to_buffer(self, session, frame, handle) diff --git a/src/wayland/handlers/session_lock.rs b/src/wayland/handlers/session_lock.rs index 988df031..10d6f93f 100644 --- a/src/wayland/handlers/session_lock.rs +++ b/src/wayland/handlers/session_lock.rs @@ -40,8 +40,7 @@ impl SessionLockHandler for State { }); for output in shell.outputs() { - self.backend - .schedule_render(&self.common.event_loop_handle, &output); + self.backend.schedule_render(&output); } } @@ -50,8 +49,7 @@ impl SessionLockHandler for State { shell.session_lock = None; for output in shell.outputs() { - self.backend - .schedule_render(&self.common.event_loop_handle, &output); + self.backend.schedule_render(&output); } } diff --git a/src/wayland/handlers/xdg_shell/mod.rs b/src/wayland/handlers/xdg_shell/mod.rs index 71c30cf2..4f782e38 100644 --- a/src/wayland/handlers/xdg_shell/mod.rs +++ b/src/wayland/handlers/xdg_shell/mod.rs @@ -399,8 +399,7 @@ impl XdgShellHandler for State { } if let Some(output) = output.as_ref() { - self.backend - .schedule_render(&self.common.event_loop_handle, &output); + self.backend.schedule_render(&output); } } diff --git a/src/xwayland.rs b/src/xwayland.rs index 846c3c61..34024d58 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -351,8 +351,7 @@ impl XwmHandler for State { } for output in outputs.into_iter() { - self.backend - .schedule_render(&self.common.event_loop_handle, &output); + self.backend.schedule_render(&output); } }