1
0
Fork 0
forked from wry/wry

output-transactions: unify state application after transactions

This commit is contained in:
Julian Orth 2025-07-13 14:51:25 +02:00
parent a52986f3f4
commit 3c1475041f
5 changed files with 54 additions and 25 deletions

View file

@ -2,9 +2,10 @@ use {
crate::{
backend::{
BackendColorSpace, BackendConnectorState, BackendTransferFunction, Connector,
ConnectorKernelId, Mode,
ConnectorId, ConnectorKernelId, Mode,
},
backends::metal::MetalError,
state::State,
utils::{errorfmt::ErrorFmt, hash_map_ext::HashMapExt},
video::drm::DrmError,
},
@ -149,50 +150,74 @@ pub trait BackendAppliedConnectorTransaction {
fn rollback(self: Box<Self>) -> Result<(), BackendConnectorTransactionError>;
}
#[derive(Default)]
struct Common {
state: Rc<State>,
states: AHashMap<ConnectorId, BackendConnectorState>,
}
pub struct ConnectorTransaction {
common: Common,
parts:
AHashMap<Box<dyn BackendConnectorTransactionTypeDyn>, Box<dyn BackendConnectorTransaction>>,
}
#[derive(Default)]
pub struct PreparedConnectorTransaction {
common: Common,
parts: Vec<Box<dyn BackendPreparedConnectorTransaction>>,
}
#[derive(Default)]
pub struct AppliedConnectorTransaction {
common: Common,
parts: Vec<Box<dyn BackendAppliedConnectorTransaction>>,
}
impl ConnectorTransaction {
pub fn new(state: &Rc<State>) -> Self {
Self {
common: Common {
state: state.clone(),
states: Default::default(),
},
parts: Default::default(),
}
}
pub fn add(
&mut self,
connector: &Rc<dyn Connector>,
change: BackendConnectorState,
mut state: BackendConnectorState,
) -> Result<(), BackendConnectorTransactionError> {
state.serial = self.common.state.backend_connector_state_serials.next();
let ty = connector.transaction_type();
let tran = match self.parts.entry(ty) {
Entry::Occupied(v) => v.into_mut(),
Entry::Vacant(v) => v.insert(connector.create_transaction()?),
};
tran.add(connector, change)
tran.add(connector, state)?;
self.common.states.insert(connector.id(), state);
Ok(())
}
pub fn prepare(
&mut self,
mut self,
) -> Result<PreparedConnectorTransaction, BackendConnectorTransactionError> {
let mut new = vec![];
for tran in self.parts.drain_values() {
new.push(tran.prepare()?);
}
Ok(PreparedConnectorTransaction { parts: new })
Ok(PreparedConnectorTransaction {
common: self.common,
parts: new,
})
}
}
impl PreparedConnectorTransaction {
pub fn apply(self) -> Result<AppliedConnectorTransaction, BackendConnectorTransactionError> {
let mut applied = AppliedConnectorTransaction::default();
let mut applied = AppliedConnectorTransaction {
common: self.common,
parts: vec![],
};
for tran in self.parts {
applied.parts.push(tran.apply()?);
}
@ -205,6 +230,11 @@ impl AppliedConnectorTransaction {
for tran in self.parts.drain(..) {
tran.commit();
}
for (connector_id, state) in self.common.states.drain() {
if let Some(c) = self.common.state.connectors.get(&connector_id) {
c.set_state(&self.common.state, state);
}
}
}
}

View file

@ -422,14 +422,21 @@ impl ConnectorData {
let mut tran = self.connector.create_transaction()?;
tran.add(&self.connector, s)?;
tran.prepare()?.apply()?.commit();
self.set_state(state, s);
Ok(())
}
pub fn set_state(&self, state: &State, s: BackendConnectorState) {
let old = self.state.get();
if old.serial >= s.serial {
return;
}
self.state.set(s);
if let Some(output) = state.outputs.get(&self.connector.id())
&& let Some(node) = &output.node
{
node.update_state(s);
} else {
self.state.set(s);
node.update_state(old, s);
}
Ok(())
}
}

View file

@ -105,10 +105,7 @@ impl ConnectorHandler {
async fn handle_connected(&self, info: MonitorInfo) {
log::info!("Connector {} connected", self.data.connector.kernel_id());
self.data.connected.set(true);
let old_state = self.data.state.get();
if old_state.serial < info.state.serial {
self.data.state.set(info.state);
}
self.data.set_state(&self.state, info.state);
let name = self.state.globals.name();
if info.non_desktop {
self.handle_non_desktop_connected(info).await;
@ -290,7 +287,7 @@ impl ConnectorHandler {
on.global.formats.set(formats);
}
ConnectorEvent::State(state) => {
on.update_state(state);
self.data.set_state(&self.state, state);
}
ev => unreachable!("received unexpected event {:?}", ev),
}

View file

@ -136,7 +136,7 @@ impl Idle {
}
fn try_set_idle(&self, idle: bool) -> Result<(), BackendConnectorTransactionError> {
let mut tran = ConnectorTransaction::default();
let mut tran = ConnectorTransaction::new(&self.state);
for connector in self.state.connectors.lock().values() {
let mut state = connector.state.get();
state.active = !idle;

View file

@ -849,12 +849,7 @@ impl OutputNode {
self.state.tree_changed();
}
pub fn update_state(self: &Rc<Self>, state: BackendConnectorState) {
let old = self.global.connector.state.get();
if old.serial >= state.serial {
return;
}
self.global.connector.state.set(state);
pub fn update_state(self: &Rc<Self>, old: BackendConnectorState, state: BackendConnectorState) {
self.update_btf_and_bcs(state.transfer_function, state.color_space);
if old.vrr != state.vrr {
self.schedule.set_vrr_enabled(state.vrr);