1
0
Fork 0
forked from wry/wry

backend: implement output transactions

This commit is contained in:
Julian Orth 2025-07-10 11:17:34 +02:00
parent f8d03c25a9
commit 7ab99bb840
25 changed files with 2712 additions and 1460 deletions

View file

@ -3,15 +3,19 @@ use {
allocator::BufferObject,
async_engine::{Phase, SpawnedFuture},
backend::{
AXIS_120, AxisSource, Backend, BackendColorSpace, BackendDrmDevice, BackendEvent,
BackendTransferFunction, Connector, ConnectorEvent, ConnectorId, ConnectorKernelId,
DrmDeviceId, DrmEvent, InputDevice, InputDeviceAccelProfile, InputDeviceCapability,
InputDeviceClickMethod, InputDeviceId, InputEvent, KeyState, Mode, MonitorInfo,
ScrollAxis, TransformMatrix,
AXIS_120, AxisSource, Backend, BackendConnectorState, BackendDrmDevice, BackendEvent,
Connector, ConnectorEvent, ConnectorId, ConnectorKernelId, DrmDeviceId, DrmEvent,
InputDevice, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceClickMethod,
InputDeviceId, InputEvent, KeyState, Mode, MonitorInfo, ScrollAxis, TransformMatrix,
transaction::{
BackendAppliedConnectorTransaction, BackendConnectorTransaction,
BackendConnectorTransactionError, BackendConnectorTransactionType,
BackendConnectorTransactionTypeDyn, BackendPreparedConnectorTransaction,
},
},
cmm::cmm_primaries::Primaries,
fixed::Fixed,
format::XRGB8888,
format::{Format, XRGB8888},
gfx_api::{AcquireSync, GfxContext, GfxError, GfxFramebuffer, GfxTexture, ReleaseSync},
ifs::wl_output::OutputId,
state::State,
@ -51,8 +55,10 @@ use {
},
},
},
ahash::AHashMap,
jay_config::video::GfxApi,
std::{
any::Any,
borrow::Cow,
cell::{Cell, RefCell},
collections::VecDeque,
@ -120,6 +126,8 @@ pub enum XBackendError {
XRGB8888,
}
const FORMAT: &Format = XRGB8888;
pub async fn create(state: &Rc<State>) -> Result<Rc<XBackend>, XBackendError> {
let c = match Xcon::connect(state).await {
Ok(c) => c,
@ -376,7 +384,7 @@ impl XBackend {
) -> Result<[XImage; 2], XBackendError> {
let mut images = [None, None];
let formats = self.ctx.formats();
let format = match formats.get(&XRGB8888.drm) {
let format = match formats.get(&FORMAT.drm) {
Some(f) => f,
None => return Err(XBackendError::XRGB8888),
};
@ -385,7 +393,7 @@ impl XBackend {
&self.state.dma_buf_ids,
width,
height,
XRGB8888,
FORMAT,
format.write_modifiers.keys(),
GBM_BO_USE_RENDERING,
)?;
@ -469,6 +477,22 @@ impl XBackend {
cw.wid
};
let images = self.create_images(window_id, WIDTH, HEIGHT).await?;
let state = BackendConnectorState {
serial: self.state.backend_connector_state_serials.next(),
enabled: true,
active: true,
mode: Mode {
width: WIDTH,
height: HEIGHT,
refresh_rate_millihz: 60_000, // TODO
},
non_desktop_override: None,
vrr: false,
tearing: false,
format: FORMAT,
color_space: Default::default(),
transfer_function: Default::default(),
};
let output = Rc::new(XOutput {
id: self.state.connector_ids.next(),
backend: self.clone(),
@ -481,6 +505,7 @@ impl XBackend {
next_image: Default::default(),
cb: CloneCell::new(None),
images,
state: Cell::new(state),
});
{
let class = "jay\0jay\0";
@ -569,21 +594,15 @@ impl XBackend {
format!("X-Window-{}", output.window),
output.window.to_string(),
)),
initial_mode: Mode {
width: output.width.get(),
height: output.height.get(),
refresh_rate_millihz: 60_000, // TODO
},
width_mm: output.width.get(),
height_mm: output.height.get(),
non_desktop: false,
vrr_capable: false,
transfer_functions: vec![],
transfer_function: BackendTransferFunction::Default,
color_spaces: vec![],
color_space: BackendColorSpace::Default,
primaries: Primaries::SRGB,
luminance: None,
state: output.state.get(),
}));
output.changed();
self.present(output).await;
@ -962,11 +981,12 @@ impl XBackend {
old.tex.set(new.tex.get());
old.pixmap.set(new.pixmap.get());
}
output.events.push(ConnectorEvent::ModeChanged(Mode {
width,
height,
refresh_rate_millihz: 60, // TODO
}));
let mut state = output.state.get();
state.serial = self.state.backend_connector_state_serials.next();
state.mode.width = width;
state.mode.height = height;
output.state.set(state);
output.events.push(ConnectorEvent::State(state));
output.changed();
}
Ok(())
@ -1035,6 +1055,7 @@ struct XOutput {
next_image: NumCell<usize>,
images: [XImage; 2],
cb: CloneCell<Option<Rc<dyn Fn()>>>,
state: Cell<BackendConnectorState>,
}
struct XImage {
@ -1083,8 +1104,75 @@ impl Connector for XOutput {
Some(self.backend.drm_device_id)
}
fn set_mode(&self, _mode: Mode) {
log::warn!("X backend doesn't support changing the connector mode");
fn effectively_locked(&self) -> bool {
// todo
true
}
fn transaction_type(&self) -> Box<dyn BackendConnectorTransactionTypeDyn> {
Box::new(XTransactionType)
}
fn create_transaction(
&self,
) -> Result<Box<dyn BackendConnectorTransaction>, BackendConnectorTransactionError> {
Ok(Box::new(XTransaction::default()))
}
}
#[derive(Hash, Eq, PartialEq)]
struct XTransactionType;
impl BackendConnectorTransactionType for XTransactionType {}
#[derive(Default)]
struct XTransaction {
connectors: AHashMap<ConnectorId, Rc<XOutput>>,
}
impl XTransaction {
fn send_state(&self) {
for con in self.connectors.values() {
let mut state = con.state.get();
state.serial = con.backend.state.backend_connector_state_serials.next();
con.events.push(ConnectorEvent::State(state));
}
}
}
impl BackendConnectorTransaction for XTransaction {
fn add(
&mut self,
connector: &Rc<dyn Connector>,
_change: BackendConnectorState,
) -> Result<(), BackendConnectorTransactionError> {
let con = (connector.clone() as Rc<dyn Any>)
.downcast::<XOutput>()
.map_err(|_| {
BackendConnectorTransactionError::UnsupportedConnectorType(connector.kernel_id())
})?;
self.connectors.insert(con.id, con.clone());
Ok(())
}
fn prepare(
self: Box<Self>,
) -> Result<Box<dyn BackendPreparedConnectorTransaction>, BackendConnectorTransactionError>
{
Ok(self)
}
}
impl BackendPreparedConnectorTransaction for XTransaction {
fn apply(
self: Box<Self>,
) -> Result<Box<dyn BackendAppliedConnectorTransaction>, BackendConnectorTransactionError> {
self.send_state();
Ok(self)
}
}
impl BackendAppliedConnectorTransaction for XTransaction {
fn commit(self: Box<Self>) {
// nothing
}
fn rollback(self: Box<Self>) -> Result<(), BackendConnectorTransactionError> {
self.send_state();
Ok(())
}
}