diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-12-20 08:49:18 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-12-22 15:19:46 +0300 |
| commit | fbb0054232fb859636ea7e32bdc45c71e185f0c6 (patch) | |
| tree | 0a36a33a9b38c91423854c17eb96ace9bd10f14a /src/backend/headless.rs | |
| parent | 2d3c36edae2cbce10ec57995c5a4418fb2424bd2 (diff) | |
| download | niri-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.rs | 139 |
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() + } +} |
