1
0
Fork 0
forked from wry/wry

output: pre-compute OutputId hash

This commit is contained in:
Julian Orth 2026-04-05 14:15:38 +02:00 committed by kossLAN
parent 9bd7e14b08
commit 6e9adc487e
No known key found for this signature in database
8 changed files with 88 additions and 40 deletions

View file

@ -1311,12 +1311,7 @@ fn create_connector_display_data(
} }
} }
} }
let output_id = Rc::new(OutputId::new( let output_id = OutputId::new(connector_id.to_string(), manufacturer, name, serial_number);
connector_id.to_string(),
manufacturer,
name,
serial_number,
));
let first_mode = info let first_mode = info
.modes .modes
.first() .first()

View file

@ -591,12 +591,12 @@ impl XBackend {
.push(BackendEvent::NewConnector(output.clone())); .push(BackendEvent::NewConnector(output.clone()));
output.events.push(ConnectorEvent::Connected(MonitorInfo { output.events.push(ConnectorEvent::Connected(MonitorInfo {
modes: Some(vec![]), modes: Some(vec![]),
output_id: Rc::new(OutputId::new( output_id: OutputId::new(
String::new(), "",
"X.Org Foundation".to_string(), "X.Org Foundation",
format!("X-Window-{}", output.window), format!("X-Window-{}", output.window),
output.window.to_string(), output.window.to_string(),
)), ),
width_mm: output.width.get(), width_mm: output.width.get(),
height_mm: output.height.get(), height_mm: output.height.get(),
non_desktop: false, non_desktop: false,

View file

@ -686,12 +686,7 @@ fn init_fd_limit() {
} }
fn create_dummy_output(state: &Rc<State>) { fn create_dummy_output(state: &Rc<State>) {
let output_id = Rc::new(OutputId { let output_id = OutputId::new("jay-dummy-connector", "jay", "jay-dummy-output", "");
connector: Some("jay-dummy-connector".to_string()),
manufacturer: "jay".to_string(),
model: "jay-dummy-output".to_string(),
serial_number: "".to_string(),
});
let persistent_state = Rc::new(PersistentOutputState::default()); let persistent_state = Rc::new(PersistentOutputState::default());
let id = state.connector_ids.next(); let id = state.connector_ids.next();
let connector = Rc::new(DummyOutput { id }) as Rc<dyn Connector>; let connector = Rc::new(DummyOutput { id }) as Rc<dyn Connector>;

View file

@ -33,6 +33,7 @@ use {
std::{ std::{
cell::{Cell, RefCell}, cell::{Cell, RefCell},
collections::hash_map::Entry, collections::hash_map::Entry,
hash::{Hash, Hasher},
rc::Rc, rc::Rc,
}, },
thiserror::Error, thiserror::Error,
@ -164,27 +165,67 @@ impl Default for PersistentOutputState {
} }
} }
#[derive(Eq, PartialEq, Hash, Debug)] #[derive(Eq, Debug)]
pub struct OutputId { pub struct OutputId {
pub connector: Option<String>, pub _connector: Option<String>,
pub manufacturer: String, pub manufacturer: String,
pub model: String, pub model: String,
pub serial_number: String, pub serial_number: String,
pub hash: OutputIdHash,
}
hash_type!(OutputIdHash);
impl PartialEq for OutputId {
fn eq(&self, other: &Self) -> bool {
self.hash == other.hash
}
}
impl Hash for OutputId {
fn hash<H: Hasher>(&self, state: &mut H) {
self.hash.hash(state);
}
} }
impl OutputId { impl OutputId {
pub fn new( pub fn new(
connector: impl Into<String>,
manufacturer: impl Into<String>,
model: impl Into<String>,
serial_number: impl Into<String>,
) -> Rc<Self> {
let connector = connector.into();
let manufacturer = manufacturer.into();
let model = model.into();
let serial_number = serial_number.into();
Self::new_(connector, manufacturer, model, serial_number)
}
fn new_(
connector: String, connector: String,
manufacturer: String, manufacturer: String,
model: String, model: String,
serial_number: String, serial_number: String,
) -> Self { ) -> Rc<Self> {
Self { let connector = serial_number.is_empty().then_some(connector);
connector: serial_number.is_empty().then_some(connector), let mut hasher = blake3::Hasher::new();
hasher.update(&[connector.is_some() as u8]);
let mut hash = |s: &str| {
hasher.update(&(s.len() as u64).to_le_bytes());
hasher.update(s.as_bytes());
};
connector.as_deref().map(&mut hash);
hash(&manufacturer);
hash(&model);
hash(&serial_number);
Rc::new(Self {
_connector: connector,
manufacturer, manufacturer,
model, model,
serial_number, serial_number,
} hash: OutputIdHash(*hasher.finalize().as_bytes()),
})
} }
} }

View file

@ -154,12 +154,7 @@ impl TestBackend {
}); });
let default_monitor_info = MonitorInfo { let default_monitor_info = MonitorInfo {
modes: Some(vec![mode]), modes: Some(vec![mode]),
output_id: Rc::new(OutputId { output_id: OutputId::new("", "jay", "TestConnector", default_connector.id.to_string()),
connector: None,
manufacturer: "jay".to_string(),
model: "TestConnector".to_string(),
serial_number: default_connector.id.to_string(),
}),
width_mm: 80, width_mm: 80,
height_mm: 60, height_mm: 60,
non_desktop: false, non_desktop: false,

View file

@ -54,12 +54,7 @@ async fn test(run: Rc<TestRun>) -> TestResult {
}); });
let new_monitor_info = MonitorInfo { let new_monitor_info = MonitorInfo {
modes: Some(vec![]), modes: Some(vec![]),
output_id: Rc::new(OutputId { output_id: OutputId::new("", "jay", "jay second connector", ""),
connector: None,
manufacturer: "jay".to_string(),
model: "jay second connector".to_string(),
serial_number: "".to_string(),
}),
width_mm: 0, width_mm: 0,
height_mm: 0, height_mm: 0,
non_desktop: false, non_desktop: false,

View file

@ -933,3 +933,35 @@ macro_rules! opaque {
} }
}; };
} }
macro_rules! hash_type {
($name:ident) => {
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct $name(pub [u8; 32]);
impl $name {
#[allow(clippy::allow_attributes, dead_code)]
pub fn hash(t: impl AsRef<[u8]>) -> Self {
Self(*blake3::hash(t.as_ref()).as_bytes())
}
}
impl serde::Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.0.serialize(serializer)
}
}
impl<'de> serde::Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
<[u8; 32]>::deserialize(deserializer).map(Self)
}
}
};
}

View file

@ -258,12 +258,7 @@ impl VirtualOutputs {
state: state.clone(), state: state.clone(),
id, id,
kernel_id, kernel_id,
output_id: Rc::new(OutputId::new( output_id: OutputId::new(kernel_id.to_string(), "Jay", "VirtualOutput", name),
kernel_id.to_string(),
"Jay".to_string(),
"VirtualOutput".to_string(),
name.to_string(),
)),
name: format!("VO-{}", name), name: format!("VO-{}", name),
frontend_state: Default::default(), frontend_state: Default::default(),
needs_format_update: Default::default(), needs_format_update: Default::default(),