aboutsummaryrefslogtreecommitdiff
path: root/src/backend/headless.rs
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-12-20 08:49:18 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2024-12-22 15:19:46 +0300
commitfbb0054232fb859636ea7e32bdc45c71e185f0c6 (patch)
tree0a36a33a9b38c91423854c17eb96ace9bd10f14a /src/backend/headless.rs
parent2d3c36edae2cbce10ec57995c5a4418fb2424bd2 (diff)
downloadniri-fbb0054232fb859636ea7e32bdc45c71e185f0c6.tar.gz
niri-fbb0054232fb859636ea7e32bdc45c71e185f0c6.tar.bz2
niri-fbb0054232fb859636ea7e32bdc45c71e185f0c6.zip
Add a Headless backend for tests
Rendering and stuff is unimplemented.
Diffstat (limited to 'src/backend/headless.rs')
-rw-r--r--src/backend/headless.rs139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/backend/headless.rs b/src/backend/headless.rs
new file mode 100644
index 00000000..5b8c7428
--- /dev/null
+++ b/src/backend/headless.rs
@@ -0,0 +1,139 @@
+//! Headless backend for tests.
+//!
+//! This can eventually grow into a more complete backend if needed, but for now it's missing some
+//! crucial parts like rendering.
+
+use std::mem;
+use std::sync::{Arc, Mutex};
+
+use niri_config::OutputName;
+use smithay::backend::allocator::dmabuf::Dmabuf;
+use smithay::backend::renderer::element::RenderElementStates;
+use smithay::backend::renderer::gles::GlesRenderer;
+use smithay::output::{Mode, Output, PhysicalProperties, Subpixel};
+use smithay::reexports::wayland_protocols::wp::presentation_time::server::wp_presentation_feedback;
+use smithay::utils::Size;
+
+use super::{IpcOutputMap, OutputId, RenderResult};
+use crate::niri::{Niri, RedrawState};
+use crate::utils::{get_monotonic_time, logical_output};
+
+pub struct Headless {
+ ipc_outputs: Arc<Mutex<IpcOutputMap>>,
+}
+
+impl Headless {
+ pub fn new() -> Self {
+ Self {
+ ipc_outputs: Default::default(),
+ }
+ }
+
+ pub fn init(&mut self, _niri: &mut Niri) {}
+
+ pub fn add_output(&mut self, niri: &mut Niri, n: u8, size: (u16, u16)) {
+ let connector = format!("headless-{n}");
+ let make = "niri".to_string();
+ let model = "headless".to_string();
+ let serial = n.to_string();
+
+ let output = Output::new(
+ connector.clone(),
+ PhysicalProperties {
+ size: (0, 0).into(),
+ subpixel: Subpixel::Unknown,
+ make: make.clone(),
+ model: model.clone(),
+ },
+ );
+
+ let mode = Mode {
+ size: Size::from((i32::from(size.0), i32::from(size.1))),
+ refresh: 60_000,
+ };
+ output.change_current_state(Some(mode), None, None, None);
+ output.set_preferred(mode);
+
+ output.user_data().insert_if_missing(|| OutputName {
+ connector,
+ make: Some(make),
+ model: Some(model),
+ serial: Some(serial),
+ });
+
+ let physical_properties = output.physical_properties();
+ self.ipc_outputs.lock().unwrap().insert(
+ OutputId::next(),
+ niri_ipc::Output {
+ name: output.name(),
+ make: physical_properties.make,
+ model: physical_properties.model,
+ serial: None,
+ physical_size: None,
+ modes: vec![niri_ipc::Mode {
+ width: size.0,
+ height: size.1,
+ refresh_rate: 60_000,
+ is_preferred: true,
+ }],
+ current_mode: Some(0),
+ vrr_supported: false,
+ vrr_enabled: false,
+ logical: Some(logical_output(&output)),
+ },
+ );
+
+ niri.add_output(output, None, false);
+ }
+
+ pub fn seat_name(&self) -> String {
+ "headless".to_owned()
+ }
+
+ pub fn with_primary_renderer<T>(
+ &mut self,
+ _f: impl FnOnce(&mut GlesRenderer) -> T,
+ ) -> Option<T> {
+ None
+ }
+
+ pub fn render(&mut self, niri: &mut Niri, output: &Output) -> RenderResult {
+ let states = RenderElementStates::default();
+ let mut presentation_feedbacks = niri.take_presentation_feedbacks(output, &states);
+ presentation_feedbacks.presented::<_, smithay::utils::Monotonic>(
+ get_monotonic_time(),
+ std::time::Duration::ZERO,
+ 0,
+ wp_presentation_feedback::Kind::empty(),
+ );
+
+ let output_state = niri.output_state.get_mut(output).unwrap();
+ match mem::replace(&mut output_state.redraw_state, RedrawState::Idle) {
+ RedrawState::Idle => unreachable!(),
+ RedrawState::Queued => (),
+ RedrawState::WaitingForVBlank { .. } => unreachable!(),
+ RedrawState::WaitingForEstimatedVBlank(_) => unreachable!(),
+ RedrawState::WaitingForEstimatedVBlankAndQueued(_) => unreachable!(),
+ }
+
+ output_state.frame_callback_sequence = output_state.frame_callback_sequence.wrapping_add(1);
+
+ // FIXME: request redraw on unfinished animations remain
+
+ RenderResult::Submitted
+ }
+
+ pub fn import_dmabuf(&mut self, _dmabuf: &Dmabuf) -> bool {
+ unimplemented!()
+ }
+
+ pub fn ipc_outputs(&self) -> Arc<Mutex<IpcOutputMap>> {
+ self.ipc_outputs.clone()
+ }
+}
+
+impl Default for Headless {
+ fn default() -> Self {
+ Self::new()
+ }
+}