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::{
|
crate::{
|
||||||
backend::{
|
backend::{
|
||||||
BackendColorSpace, BackendConnectorState, BackendTransferFunction, Connector,
|
BackendColorSpace, BackendConnectorState, BackendTransferFunction, Connector,
|
||||||
ConnectorKernelId, Mode,
|
ConnectorId, ConnectorKernelId, Mode,
|
||||||
},
|
},
|
||||||
backends::metal::MetalError,
|
backends::metal::MetalError,
|
||||||
|
state::State,
|
||||||
utils::{errorfmt::ErrorFmt, hash_map_ext::HashMapExt},
|
utils::{errorfmt::ErrorFmt, hash_map_ext::HashMapExt},
|
||||||
video::drm::DrmError,
|
video::drm::DrmError,
|
||||||
},
|
},
|
||||||
|
|
@ -149,50 +150,74 @@ pub trait BackendAppliedConnectorTransaction {
|
||||||
fn rollback(self: Box<Self>) -> Result<(), BackendConnectorTransactionError>;
|
fn rollback(self: Box<Self>) -> Result<(), BackendConnectorTransactionError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
struct Common {
|
||||||
|
state: Rc<State>,
|
||||||
|
states: AHashMap<ConnectorId, BackendConnectorState>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ConnectorTransaction {
|
pub struct ConnectorTransaction {
|
||||||
|
common: Common,
|
||||||
parts:
|
parts:
|
||||||
AHashMap<Box<dyn BackendConnectorTransactionTypeDyn>, Box<dyn BackendConnectorTransaction>>,
|
AHashMap<Box<dyn BackendConnectorTransactionTypeDyn>, Box<dyn BackendConnectorTransaction>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct PreparedConnectorTransaction {
|
pub struct PreparedConnectorTransaction {
|
||||||
|
common: Common,
|
||||||
parts: Vec<Box<dyn BackendPreparedConnectorTransaction>>,
|
parts: Vec<Box<dyn BackendPreparedConnectorTransaction>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct AppliedConnectorTransaction {
|
pub struct AppliedConnectorTransaction {
|
||||||
|
common: Common,
|
||||||
parts: Vec<Box<dyn BackendAppliedConnectorTransaction>>,
|
parts: Vec<Box<dyn BackendAppliedConnectorTransaction>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConnectorTransaction {
|
impl ConnectorTransaction {
|
||||||
|
pub fn new(state: &Rc<State>) -> Self {
|
||||||
|
Self {
|
||||||
|
common: Common {
|
||||||
|
state: state.clone(),
|
||||||
|
states: Default::default(),
|
||||||
|
},
|
||||||
|
parts: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add(
|
pub fn add(
|
||||||
&mut self,
|
&mut self,
|
||||||
connector: &Rc<dyn Connector>,
|
connector: &Rc<dyn Connector>,
|
||||||
change: BackendConnectorState,
|
mut state: BackendConnectorState,
|
||||||
) -> Result<(), BackendConnectorTransactionError> {
|
) -> Result<(), BackendConnectorTransactionError> {
|
||||||
|
state.serial = self.common.state.backend_connector_state_serials.next();
|
||||||
let ty = connector.transaction_type();
|
let ty = connector.transaction_type();
|
||||||
let tran = match self.parts.entry(ty) {
|
let tran = match self.parts.entry(ty) {
|
||||||
Entry::Occupied(v) => v.into_mut(),
|
Entry::Occupied(v) => v.into_mut(),
|
||||||
Entry::Vacant(v) => v.insert(connector.create_transaction()?),
|
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(
|
pub fn prepare(
|
||||||
&mut self,
|
mut self,
|
||||||
) -> Result<PreparedConnectorTransaction, BackendConnectorTransactionError> {
|
) -> Result<PreparedConnectorTransaction, BackendConnectorTransactionError> {
|
||||||
let mut new = vec![];
|
let mut new = vec![];
|
||||||
for tran in self.parts.drain_values() {
|
for tran in self.parts.drain_values() {
|
||||||
new.push(tran.prepare()?);
|
new.push(tran.prepare()?);
|
||||||
}
|
}
|
||||||
Ok(PreparedConnectorTransaction { parts: new })
|
Ok(PreparedConnectorTransaction {
|
||||||
|
common: self.common,
|
||||||
|
parts: new,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PreparedConnectorTransaction {
|
impl PreparedConnectorTransaction {
|
||||||
pub fn apply(self) -> Result<AppliedConnectorTransaction, BackendConnectorTransactionError> {
|
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 {
|
for tran in self.parts {
|
||||||
applied.parts.push(tran.apply()?);
|
applied.parts.push(tran.apply()?);
|
||||||
}
|
}
|
||||||
|
|
@ -205,6 +230,11 @@ impl AppliedConnectorTransaction {
|
||||||
for tran in self.parts.drain(..) {
|
for tran in self.parts.drain(..) {
|
||||||
tran.commit();
|
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()?;
|
let mut tran = self.connector.create_transaction()?;
|
||||||
tran.add(&self.connector, s)?;
|
tran.add(&self.connector, s)?;
|
||||||
tran.prepare()?.apply()?.commit();
|
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())
|
if let Some(output) = state.outputs.get(&self.connector.id())
|
||||||
&& let Some(node) = &output.node
|
&& let Some(node) = &output.node
|
||||||
{
|
{
|
||||||
node.update_state(s);
|
node.update_state(old, s);
|
||||||
} else {
|
|
||||||
self.state.set(s);
|
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -105,10 +105,7 @@ impl ConnectorHandler {
|
||||||
async fn handle_connected(&self, info: MonitorInfo) {
|
async fn handle_connected(&self, info: MonitorInfo) {
|
||||||
log::info!("Connector {} connected", self.data.connector.kernel_id());
|
log::info!("Connector {} connected", self.data.connector.kernel_id());
|
||||||
self.data.connected.set(true);
|
self.data.connected.set(true);
|
||||||
let old_state = self.data.state.get();
|
self.data.set_state(&self.state, info.state);
|
||||||
if old_state.serial < info.state.serial {
|
|
||||||
self.data.state.set(info.state);
|
|
||||||
}
|
|
||||||
let name = self.state.globals.name();
|
let name = self.state.globals.name();
|
||||||
if info.non_desktop {
|
if info.non_desktop {
|
||||||
self.handle_non_desktop_connected(info).await;
|
self.handle_non_desktop_connected(info).await;
|
||||||
|
|
@ -290,7 +287,7 @@ impl ConnectorHandler {
|
||||||
on.global.formats.set(formats);
|
on.global.formats.set(formats);
|
||||||
}
|
}
|
||||||
ConnectorEvent::State(state) => {
|
ConnectorEvent::State(state) => {
|
||||||
on.update_state(state);
|
self.data.set_state(&self.state, state);
|
||||||
}
|
}
|
||||||
ev => unreachable!("received unexpected event {:?}", ev),
|
ev => unreachable!("received unexpected event {:?}", ev),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ impl Idle {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_set_idle(&self, idle: bool) -> Result<(), BackendConnectorTransactionError> {
|
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() {
|
for connector in self.state.connectors.lock().values() {
|
||||||
let mut state = connector.state.get();
|
let mut state = connector.state.get();
|
||||||
state.active = !idle;
|
state.active = !idle;
|
||||||
|
|
|
||||||
|
|
@ -849,12 +849,7 @@ impl OutputNode {
|
||||||
self.state.tree_changed();
|
self.state.tree_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_state(self: &Rc<Self>, state: BackendConnectorState) {
|
pub fn update_state(self: &Rc<Self>, old: BackendConnectorState, state: BackendConnectorState) {
|
||||||
let old = self.global.connector.state.get();
|
|
||||||
if old.serial >= state.serial {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.global.connector.state.set(state);
|
|
||||||
self.update_btf_and_bcs(state.transfer_function, state.color_space);
|
self.update_btf_and_bcs(state.transfer_function, state.color_space);
|
||||||
if old.vrr != state.vrr {
|
if old.vrr != state.vrr {
|
||||||
self.schedule.set_vrr_enabled(state.vrr);
|
self.schedule.set_vrr_enabled(state.vrr);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue