aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/mod.rs4
-rw-r--r--src/backend/tty.rs48
-rw-r--r--src/handlers/mod.rs5
-rw-r--r--src/input.rs8
-rw-r--r--src/niri.rs27
5 files changed, 65 insertions, 27 deletions
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::<State>(&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<Mutex<HashMap<String, Output>>> {
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<GlesRenderer>],
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();