output-transactions: unify state application after transactions
This commit is contained in:
parent
a52986f3f4
commit
3c1475041f
5 changed files with 54 additions and 25 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
15
src/state.rs
15
src/state.rs
|
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue