From ac16717f4eb6d339ae0a544ac35b8305ffc8802e Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Tue, 26 Sep 2023 10:06:07 +0400 Subject: Avoid unwraps in more places --- src/backend/mod.rs | 4 ++-- src/backend/tty.rs | 48 +++++++++++++++++++++++++++++++++--------------- src/handlers/mod.rs | 5 ++++- src/input.rs | 8 ++++---- src/niri.rs | 27 ++++++++++++++++++++++----- 5 files changed, 65 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/backend/mod.rs b/src/backend/mod.rs index eca8cc2d..aaad7822 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -38,10 +38,10 @@ impl Backend { } } - pub fn renderer(&mut self) -> &mut GlesRenderer { + pub fn renderer(&mut self) -> Option<&mut GlesRenderer> { match self { Backend::Tty(tty) => tty.renderer(), - Backend::Winit(winit) => winit.renderer(), + Backend::Winit(winit) => Some(winit.renderer()), } } diff --git a/src/backend/tty.rs b/src/backend/tty.rs index 4f5b8df7..5204c44a 100644 --- a/src/backend/tty.rs +++ b/src/backend/tty.rs @@ -327,7 +327,7 @@ impl Tty { let mut dmabuf_state = DmabufState::new(); let default_feedback = DmabufFeedbackBuilder::new(device_id, gles.dmabuf_formats()) .build() - .unwrap(); + .context("error building default dmabuf feedback")?; let dmabuf_global = dmabuf_state .create_global_with_default_feedback::(&niri.display_handle, &default_feedback); @@ -426,11 +426,14 @@ impl Tty { .cloned() .unwrap_or_default(); - let device = self.output_device.as_mut().unwrap(); + let device = self + .output_device + .as_mut() + .context("missing output device")?; let mut mode = connector.modes().get(0); connector.modes().iter().for_each(|m| { - debug!("mode: {m:?}"); + trace!("mode: {m:?}"); if m.mode_type().contains(ModeTypeFlags::PREFERRED) { // Pick the highest refresh rate. @@ -514,7 +517,7 @@ impl Tty { let dmabuf_feedback = DmabufFeedbackBuilder::new(device.id, device.formats.clone()) .add_preference_tranche(device.id, Some(TrancheFlags::Scanout), scanout_formats) .build() - .unwrap(); + .context("error building dmabuf feedback")?; let vblank_frame_name = tracy_client::FrameName::new_leak(format!("vblank on {output_name}")); @@ -554,7 +557,10 @@ impl Tty { crtc: crtc::Handle, ) { debug!("disconnecting connector: {connector:?}"); - let device = self.output_device.as_mut().unwrap(); + let Some(device) = self.output_device.as_mut() else { + error!("missing output device"); + return; + }; let Some(surface) = device.surfaces.remove(&crtc) else { debug!("crtc wasn't enabled"); @@ -568,10 +574,12 @@ impl Tty { let tty_state: &TtyOutputState = output.user_data().get().unwrap(); tty_state.device_id == device.id && tty_state.crtc == crtc }) - .unwrap() - .clone(); - - niri.remove_output(&output); + .cloned(); + if let Some(output) = output { + niri.remove_output(&output); + } else { + error!("missing output for crtc {crtc:?}"); + }; self.connectors.lock().unwrap().remove(&surface.name); } @@ -692,8 +700,8 @@ impl Tty { self.session.seat() } - pub fn renderer(&mut self) -> &mut GlesRenderer { - &mut self.output_device.as_mut().unwrap().gles + pub fn renderer(&mut self) -> Option<&mut GlesRenderer> { + self.output_device.as_mut().map(|d| &mut d.gles) } pub fn render( @@ -705,13 +713,20 @@ impl Tty { ) -> Option<&DmabufFeedback> { let span = tracy_client::span!("Tty::render"); - let device = self.output_device.as_mut().unwrap(); + let Some(device) = self.output_device.as_mut() else { + error!("missing output device"); + return None; + }; + let tty_state: &TtyOutputState = output.user_data().get().unwrap(); - let surface = device.surfaces.get_mut(&tty_state.crtc).unwrap(); - let drm_compositor = &mut surface.compositor; + let Some(surface) = device.surfaces.get_mut(&tty_state.crtc) else { + error!("missing surface"); + return None; + }; span.emit_text(&surface.name); + let drm_compositor = &mut surface.compositor; match drm_compositor.render_frame::<_, _, GlesTexture>( &mut device.gles, elements, @@ -785,7 +800,10 @@ impl Tty { } pub fn dmabuf_state(&mut self) -> &mut DmabufState { - &mut self.output_device.as_mut().unwrap().dmabuf_state + let device = self.output_device.as_mut().expect( + "the dmabuf global must be created and destroyed together with the output device", + ); + &mut device.dmabuf_state } pub fn connectors(&self) -> Arc>> { diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 95fc3fa9..e99cc5ce 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -89,7 +89,10 @@ impl DmabufHandler for State { _global: &DmabufGlobal, dmabuf: Dmabuf, ) -> Result<(), ImportError> { - match self.backend.renderer().import_dmabuf(&dmabuf, None) { + let renderer = self.backend.renderer().expect( + "the dmabuf global must be created and destroyed together with the output device", + ); + match renderer.import_dmabuf(&dmabuf, None) { Ok(_texture) => Ok(()), Err(err) => { debug!("error importing dmabuf: {err:?}"); diff --git a/src/input.rs b/src/input.rs index 888bf785..dc443365 100644 --- a/src/input.rs +++ b/src/input.rs @@ -153,10 +153,10 @@ impl State { Action::Screenshot => { let active = self.niri.monitor_set.active_output().cloned(); if let Some(active) = active { - if let Err(err) = - self.niri.screenshot(self.backend.renderer(), &active) - { - warn!("error taking screenshot: {err:?}"); + if let Some(renderer) = self.backend.renderer() { + if let Err(err) = self.niri.screenshot(renderer, &active) { + warn!("error taking screenshot: {err:?}"); + } } } } diff --git a/src/niri.rs b/src/niri.rs index 6bcca8eb..9aa0e027 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -361,7 +361,14 @@ impl Niri { calloop::channel::Event::Msg(ScreenshotToNiri::TakeScreenshot { include_cursor, }) => { - let renderer = state.backend.renderer(); + let Some(renderer) = state.backend.renderer() else { + let msg = NiriToScreenshot::ScreenshotResult(None); + if let Err(err) = to_screenshot.send_blocking(msg) { + warn!("error sending None to screenshot: {err:?}"); + } + return; + }; + let on_done = { let to_screenshot = to_screenshot.clone(); move |path| { @@ -938,6 +945,10 @@ impl Niri { fn redraw(&mut self, backend: &mut Backend, output: &Output) { let _span = tracy_client::span!("Niri::redraw"); + let Some(renderer) = backend.renderer() else { + return; + }; + let state = self.output_state.get_mut(output).unwrap(); let presentation_time = state.frame_clock.next_presentation_time(); @@ -948,7 +959,7 @@ impl Niri { self.monitor_set.advance_animations(presentation_time); // Render the elements. - let elements = self.render(backend.renderer(), output, true); + let elements = self.render(renderer, output, true); // Hand it over to the backend. let dmabuf_feedback = backend.render(self, output, &elements, presentation_time); @@ -962,7 +973,10 @@ impl Niri { self.send_frame_callbacks(output); // Render and send to PipeWire screencast streams. - self.send_for_screen_cast(backend, output, &elements, presentation_time); + let renderer = backend + .renderer() + .expect("renderer must not have disappeared"); + self.send_for_screen_cast(renderer, output, &elements, presentation_time); } fn send_dmabuf_feedbacks(&self, output: &Output, feedback: &DmabufFeedback) { @@ -1072,7 +1086,7 @@ impl Niri { fn send_for_screen_cast( &mut self, - backend: &mut Backend, + renderer: &mut GlesRenderer, output: &Output, elements: &[OutputRenderElements], presentation_time: Duration, @@ -1116,7 +1130,10 @@ impl Niri { let dmabuf = cast.dmabufs.borrow()[&fd].clone(); // FIXME: Hidden / embedded / metadata cursor - render_to_dmabuf(backend.renderer(), dmabuf, size, scale, elements).unwrap(); + if let Err(err) = render_to_dmabuf(renderer, dmabuf, size, scale, elements) { + error!("error rendering to dmabuf: {err:?}"); + continue; + } let maxsize = data.as_raw().maxsize; let chunk = data.chunk_mut(); -- cgit