aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/mod.rs9
-rw-r--r--src/backend/tty.rs77
-rw-r--r--src/backend/winit.rs29
3 files changed, 106 insertions, 9 deletions
diff --git a/src/backend/mod.rs b/src/backend/mod.rs
index a273f769..595b8513 100644
--- a/src/backend/mod.rs
+++ b/src/backend/mod.rs
@@ -1,4 +1,6 @@
+use std::cell::RefCell;
use std::collections::HashMap;
+use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::time::Duration;
@@ -110,6 +112,13 @@ impl Backend {
}
}
+ pub fn ipc_outputs(&self) -> Rc<RefCell<HashMap<String, niri_ipc::Output>>> {
+ match self {
+ Backend::Tty(tty) => tty.ipc_outputs(),
+ Backend::Winit(winit) => winit.ipc_outputs(),
+ }
+ }
+
#[cfg_attr(not(feature = "dbus"), allow(unused))]
pub fn enabled_outputs(&self) -> Arc<Mutex<HashMap<String, Output>>> {
match self {
diff --git a/src/backend/tty.rs b/src/backend/tty.rs
index 0dacf9b7..f86851cb 100644
--- a/src/backend/tty.rs
+++ b/src/backend/tty.rs
@@ -74,6 +74,7 @@ pub struct Tty {
// The allocator for the primary GPU. It is only `Some()` if we have a device corresponding to
// the primary GPU.
primary_allocator: Option<DmabufAllocator<GbmAllocator<DrmDeviceFd>>>,
+ ipc_outputs: Rc<RefCell<HashMap<String, niri_ipc::Output>>>,
enabled_outputs: Arc<Mutex<HashMap<String, Output>>>,
}
@@ -221,6 +222,7 @@ impl Tty {
devices: HashMap::new(),
dmabuf_global: None,
primary_allocator: None,
+ ipc_outputs: Rc::new(RefCell::new(HashMap::new())),
enabled_outputs: Arc::new(Mutex::new(HashMap::new())),
}
}
@@ -367,6 +369,8 @@ impl Tty {
warn!("error adding device: {err:?}");
}
}
+
+ self.refresh_ipc_outputs();
}
}
}
@@ -512,6 +516,8 @@ impl Tty {
_ => (),
}
}
+
+ self.refresh_ipc_outputs();
}
fn device_removed(&mut self, device_id: dev_t, niri: &mut Niri) {
@@ -576,6 +582,8 @@ impl Tty {
self.gpu_manager.as_mut().remove_node(&device.render_node);
niri.event_loop.remove(device.token);
+
+ self.refresh_ipc_outputs();
}
fn connector_connected(
@@ -608,16 +616,7 @@ impl Tty {
let device = self.devices.get_mut(&node).context("missing device")?;
- // FIXME: print modes here until we have a better way to list all modes.
for m in connector.modes() {
- let wl_mode = Mode::from(*m);
- debug!(
- "mode: {}x{}@{:.3}",
- m.size().0,
- m.size().1,
- wl_mode.refresh as f64 / 1000.,
- );
-
trace!("{m:?}");
}
@@ -1157,6 +1156,64 @@ impl Tty {
}
}
+ fn refresh_ipc_outputs(&self) {
+ let _span = tracy_client::span!("Tty::refresh_ipc_outputs");
+
+ let mut ipc_outputs = HashMap::new();
+
+ for device in self.devices.values() {
+ for (connector, crtc) in device.drm_scanner.crtcs() {
+ let connector_name = format!(
+ "{}-{}",
+ connector.interface().as_str(),
+ connector.interface_id(),
+ );
+
+ let physical_size = connector.size();
+
+ let (make, model) = EdidInfo::for_connector(&device.drm, connector.handle())
+ .map(|info| (info.manufacturer, info.model))
+ .unwrap_or_else(|| ("Unknown".into(), "Unknown".into()));
+
+ let modes = connector
+ .modes()
+ .iter()
+ .map(|m| niri_ipc::Mode {
+ width: m.size().0,
+ height: m.size().1,
+ refresh_rate: Mode::from(*m).refresh as u32,
+ })
+ .collect();
+
+ let mut output = niri_ipc::Output {
+ name: connector_name.clone(),
+ make,
+ model,
+ physical_size,
+ modes,
+ current_mode: None,
+ };
+
+ if let Some(surface) = device.surfaces.get(&crtc) {
+ let current = surface.compositor.pending_mode();
+ if let Some(current) = connector.modes().iter().position(|m| *m == current) {
+ output.current_mode = Some(current);
+ } else {
+ error!("connector mode list missing current mode");
+ }
+ }
+
+ ipc_outputs.insert(connector_name, output);
+ }
+ }
+
+ self.ipc_outputs.replace(ipc_outputs);
+ }
+
+ pub fn ipc_outputs(&self) -> Rc<RefCell<HashMap<String, niri_ipc::Output>>> {
+ self.ipc_outputs.clone()
+ }
+
pub fn enabled_outputs(&self) -> Arc<Mutex<HashMap<String, Output>>> {
self.enabled_outputs.clone()
}
@@ -1305,6 +1362,8 @@ impl Tty {
warn!("error connecting connector: {err:?}");
}
}
+
+ self.refresh_ipc_outputs();
}
}
diff --git a/src/backend/winit.rs b/src/backend/winit.rs
index 9b31d2c5..3c4b9ad3 100644
--- a/src/backend/winit.rs
+++ b/src/backend/winit.rs
@@ -28,6 +28,7 @@ pub struct Winit {
output: Output,
backend: WinitGraphicsBackend<GlesRenderer>,
damage_tracker: OutputDamageTracker,
+ ipc_outputs: Rc<RefCell<HashMap<String, niri_ipc::Output>>>,
enabled_outputs: Arc<Mutex<HashMap<String, Output>>>,
}
@@ -56,6 +57,23 @@ impl Winit {
output.change_current_state(Some(mode), Some(Transform::Flipped180), None, None);
output.set_preferred(mode);
+ let physical_properties = output.physical_properties();
+ let ipc_outputs = Rc::new(RefCell::new(HashMap::from([(
+ "winit".to_owned(),
+ niri_ipc::Output {
+ name: output.name(),
+ make: physical_properties.make,
+ model: physical_properties.model,
+ physical_size: None,
+ modes: vec![niri_ipc::Mode {
+ width: backend.window_size().w.clamp(0, u16::MAX as i32) as u16,
+ height: backend.window_size().h.clamp(0, u16::MAX as i32) as u16,
+ refresh_rate: 60_000,
+ }],
+ current_mode: Some(0),
+ },
+ )])));
+
let enabled_outputs = Arc::new(Mutex::new(HashMap::from([(
"winit".to_owned(),
output.clone(),
@@ -76,6 +94,12 @@ impl Winit {
None,
None,
);
+
+ let mut ipc_outputs = winit.ipc_outputs.borrow_mut();
+ let mode = &mut ipc_outputs.get_mut("winit").unwrap().modes[0];
+ mode.width = size.w.clamp(0, u16::MAX as i32) as u16;
+ mode.height = size.h.clamp(0, u16::MAX as i32) as u16;
+
state.niri.output_resized(winit.output.clone());
}
WinitEvent::Input(event) => state.process_input_event(event),
@@ -95,6 +119,7 @@ impl Winit {
output,
backend,
damage_tracker,
+ ipc_outputs,
enabled_outputs,
}
}
@@ -198,6 +223,10 @@ impl Winit {
}
}
+ pub fn ipc_outputs(&self) -> Rc<RefCell<HashMap<String, niri_ipc::Output>>> {
+ self.ipc_outputs.clone()
+ }
+
pub fn enabled_outputs(&self) -> Arc<Mutex<HashMap<String, Output>>> {
self.enabled_outputs.clone()
}