mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2025-02-01 07:57:59 +01:00
Separate stuff that took in State
I love me some non-overlapping borrows
This commit is contained in:
parent
b99cc8ffce
commit
8c0bce7191
1 changed files with 154 additions and 175 deletions
|
@ -91,7 +91,7 @@ use crate::{
|
||||||
pointer::PointerElement, pointer_render_elements, take_presentation_feedback,
|
pointer::PointerElement, pointer_render_elements, take_presentation_feedback,
|
||||||
OutputRenderElement,
|
OutputRenderElement,
|
||||||
},
|
},
|
||||||
state::{State, SurfaceDmabufFeedback, WithState},
|
state::{Pinnacle, State, SurfaceDmabufFeedback, WithState},
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::drm_util::EdidInfo;
|
use self::drm_util::EdidInfo;
|
||||||
|
@ -171,7 +171,10 @@ impl Udev {
|
||||||
RenderState::Idle => {
|
RenderState::Idle => {
|
||||||
let output = output.clone();
|
let output = output.clone();
|
||||||
let token = loop_handle.insert_idle(move |state| {
|
let token = loop_handle.insert_idle(move |state| {
|
||||||
state.render_surface(&output);
|
state
|
||||||
|
.backend
|
||||||
|
.udev_mut()
|
||||||
|
.render_surface(&mut state.pinnacle, &output);
|
||||||
});
|
});
|
||||||
|
|
||||||
surface.render_state = RenderState::Scheduled(token);
|
surface.render_state = RenderState::Scheduled(token);
|
||||||
|
@ -349,32 +352,32 @@ pub fn setup_udev(
|
||||||
// Initialize the udev backend
|
// Initialize the udev backend
|
||||||
let udev_backend = UdevBackend::new(session.seat())?;
|
let udev_backend = UdevBackend::new(session.seat())?;
|
||||||
|
|
||||||
let udev_dispatcher =
|
let udev_dispatcher = Dispatcher::new(udev_backend, move |event, _, state: &mut State| {
|
||||||
Dispatcher::new(
|
let udev = state.backend.udev_mut();
|
||||||
udev_backend,
|
let pinnacle = &mut state.pinnacle;
|
||||||
move |event, _, state: &mut State| match event {
|
match event {
|
||||||
// GPU connected
|
// GPU connected
|
||||||
UdevEvent::Added { device_id, path } => {
|
UdevEvent::Added { device_id, path } => {
|
||||||
if let Err(err) = DrmNode::from_dev_id(device_id)
|
if let Err(err) = DrmNode::from_dev_id(device_id)
|
||||||
.map_err(DeviceAddError::DrmNode)
|
.map_err(DeviceAddError::DrmNode)
|
||||||
.and_then(|node| state.device_added(node, &path))
|
.and_then(|node| udev.device_added(pinnacle, node, &path))
|
||||||
{
|
{
|
||||||
error!("Skipping device {device_id}: {err}");
|
error!("Skipping device {device_id}: {err}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UdevEvent::Changed { device_id } => {
|
UdevEvent::Changed { device_id } => {
|
||||||
if let Ok(node) = DrmNode::from_dev_id(device_id) {
|
if let Ok(node) = DrmNode::from_dev_id(device_id) {
|
||||||
state.device_changed(node)
|
udev.device_changed(pinnacle, node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// GPU disconnected
|
// GPU disconnected
|
||||||
UdevEvent::Removed { device_id } => {
|
UdevEvent::Removed { device_id } => {
|
||||||
if let Ok(node) = DrmNode::from_dev_id(device_id) {
|
if let Ok(node) = DrmNode::from_dev_id(device_id) {
|
||||||
state.device_removed(node)
|
udev.device_removed(pinnacle, node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
);
|
});
|
||||||
|
|
||||||
event_loop
|
event_loop
|
||||||
.handle()
|
.handle()
|
||||||
|
@ -417,18 +420,18 @@ pub fn setup_udev(
|
||||||
.map(|(id, path)| (id, path.to_path_buf()))
|
.map(|(id, path)| (id, path.to_path_buf()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let udev = state.backend.udev_mut();
|
||||||
|
|
||||||
// Create DrmNodes from already connected GPUs
|
// Create DrmNodes from already connected GPUs
|
||||||
for (device_id, path) in things {
|
for (device_id, path) in things {
|
||||||
if let Err(err) = DrmNode::from_dev_id(device_id)
|
if let Err(err) = DrmNode::from_dev_id(device_id)
|
||||||
.map_err(DeviceAddError::DrmNode)
|
.map_err(DeviceAddError::DrmNode)
|
||||||
.and_then(|node| state.device_added(node, &path))
|
.and_then(|node| udev.device_added(&mut state.pinnacle, node, &path))
|
||||||
{
|
{
|
||||||
error!("Skipping device {device_id}: {err}");
|
error!("Skipping device {device_id}: {err}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let udev = state.backend.udev_mut();
|
|
||||||
|
|
||||||
// Initialize libinput backend
|
// Initialize libinput backend
|
||||||
let mut libinput_context = Libinput::new_with_udev::<LibinputSessionInterface<LibSeatSession>>(
|
let mut libinput_context = Libinput::new_with_udev::<LibinputSessionInterface<LibSeatSession>>(
|
||||||
udev.session.clone().into(),
|
udev.session.clone().into(),
|
||||||
|
@ -471,12 +474,10 @@ pub fn setup_udev(
|
||||||
error!("Failed to resume libinput context");
|
error!("Failed to resume libinput context");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: All this dance around borrowing is a consequence of the fact that I haven't
|
let udev = state.backend.udev_mut();
|
||||||
// | split the State struct into a main State and a substruct like
|
let pinnacle = &mut state.pinnacle;
|
||||||
// | Niri and cosmic-comp have done
|
|
||||||
|
|
||||||
let (mut device_list, connected_devices, disconnected_devices) = {
|
let (mut device_list, connected_devices, disconnected_devices) = {
|
||||||
let udev = state.backend.udev();
|
|
||||||
let device_list = udev
|
let device_list = udev
|
||||||
.udev_dispatcher
|
.udev_dispatcher
|
||||||
.as_source_ref()
|
.as_source_ref()
|
||||||
|
@ -497,17 +498,14 @@ pub fn setup_udev(
|
||||||
|
|
||||||
for node in disconnected_devices {
|
for node in disconnected_devices {
|
||||||
device_list.remove(&node);
|
device_list.remove(&node);
|
||||||
state.device_removed(node);
|
udev.device_removed(pinnacle, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
for node in connected_devices {
|
for node in connected_devices {
|
||||||
device_list.remove(&node);
|
device_list.remove(&node);
|
||||||
|
|
||||||
// TODO: split off the big State struct to avoid this bs
|
// INFO: see if this can be moved below udev.device_changed
|
||||||
|
|
||||||
{
|
{
|
||||||
let udev = state.backend.udev_mut();
|
|
||||||
|
|
||||||
let Some(backend) = udev.backends.get_mut(&node) else {
|
let Some(backend) = udev.backends.get_mut(&node) else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
};
|
};
|
||||||
|
@ -517,16 +515,16 @@ pub fn setup_udev(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.device_changed(node);
|
udev.device_changed(pinnacle, node);
|
||||||
|
|
||||||
|
let Some(backend) = udev.backends.get_mut(&node) else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
|
||||||
// Apply pending gammas
|
// Apply pending gammas
|
||||||
//
|
//
|
||||||
// Also welcome to some really doodoo code
|
// Also welcome to some really doodoo code
|
||||||
|
|
||||||
let udev = state.backend.udev_mut();
|
|
||||||
let Some(backend) = udev.backends.get_mut(&node) else {
|
|
||||||
unreachable!();
|
|
||||||
};
|
|
||||||
for (crtc, surface) in backend.surfaces.iter_mut() {
|
for (crtc, surface) in backend.surfaces.iter_mut() {
|
||||||
match std::mem::take(&mut surface.pending_gamma_change) {
|
match std::mem::take(&mut surface.pending_gamma_change) {
|
||||||
PendingGammaChange::Idle => {
|
PendingGammaChange::Idle => {
|
||||||
|
@ -573,7 +571,12 @@ pub fn setup_udev(
|
||||||
|
|
||||||
// Newly connected devices
|
// Newly connected devices
|
||||||
for (node, path) in device_list.into_iter() {
|
for (node, path) in device_list.into_iter() {
|
||||||
if let Err(err) = state.device_added(node, &path) {
|
if let Err(err) =
|
||||||
|
state
|
||||||
|
.backend
|
||||||
|
.udev_mut()
|
||||||
|
.device_added(&mut state.pinnacle, node, &path)
|
||||||
|
{
|
||||||
error!("Error adding device: {err}");
|
error!("Error adding device: {err}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -884,13 +887,16 @@ fn render_frame<'a>(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl Udev {
|
||||||
/// A GPU was plugged in.
|
/// A GPU was plugged in.
|
||||||
fn device_added(&mut self, node: DrmNode, path: &Path) -> Result<(), DeviceAddError> {
|
fn device_added(
|
||||||
let udev = self.backend.udev_mut();
|
&mut self,
|
||||||
|
pinnacle: &mut Pinnacle,
|
||||||
|
node: DrmNode,
|
||||||
|
path: &Path,
|
||||||
|
) -> Result<(), DeviceAddError> {
|
||||||
// Try to open the device
|
// Try to open the device
|
||||||
let fd = udev
|
let fd = self
|
||||||
.session
|
.session
|
||||||
.open(
|
.open(
|
||||||
path,
|
path,
|
||||||
|
@ -904,12 +910,14 @@ impl State {
|
||||||
DrmDevice::new(fd.clone(), true).map_err(DeviceAddError::DrmDevice)?;
|
DrmDevice::new(fd.clone(), true).map_err(DeviceAddError::DrmDevice)?;
|
||||||
let gbm = GbmDevice::new(fd).map_err(DeviceAddError::GbmDevice)?;
|
let gbm = GbmDevice::new(fd).map_err(DeviceAddError::GbmDevice)?;
|
||||||
|
|
||||||
let registration_token = self
|
let registration_token = pinnacle
|
||||||
.pinnacle
|
|
||||||
.loop_handle
|
.loop_handle
|
||||||
.insert_source(notifier, move |event, metadata, state| match event {
|
.insert_source(notifier, move |event, metadata, state| match event {
|
||||||
DrmEvent::VBlank(crtc) => {
|
DrmEvent::VBlank(crtc) => {
|
||||||
state.on_vblank(node, crtc, metadata);
|
state
|
||||||
|
.backend
|
||||||
|
.udev_mut()
|
||||||
|
.on_vblank(&state.pinnacle, node, crtc, metadata);
|
||||||
}
|
}
|
||||||
DrmEvent::Error(error) => {
|
DrmEvent::Error(error) => {
|
||||||
error!("{:?}", error);
|
error!("{:?}", error);
|
||||||
|
@ -925,12 +933,12 @@ impl State {
|
||||||
.and_then(|x| x.try_get_render_node().ok().flatten())
|
.and_then(|x| x.try_get_render_node().ok().flatten())
|
||||||
.unwrap_or(node);
|
.unwrap_or(node);
|
||||||
|
|
||||||
udev.gpu_manager
|
self.gpu_manager
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.add_node(render_node, gbm.clone())
|
.add_node(render_node, gbm.clone())
|
||||||
.map_err(DeviceAddError::AddNode)?;
|
.map_err(DeviceAddError::AddNode)?;
|
||||||
|
|
||||||
udev.backends.insert(
|
self.backends.insert(
|
||||||
node,
|
node,
|
||||||
UdevBackendData {
|
UdevBackendData {
|
||||||
registration_token,
|
registration_token,
|
||||||
|
@ -942,7 +950,7 @@ impl State {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
self.device_changed(node);
|
self.device_changed(pinnacle, node);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -950,19 +958,18 @@ impl State {
|
||||||
/// A display was plugged in.
|
/// A display was plugged in.
|
||||||
fn connector_connected(
|
fn connector_connected(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
pinnacle: &mut Pinnacle,
|
||||||
node: DrmNode,
|
node: DrmNode,
|
||||||
connector: connector::Info,
|
connector: connector::Info,
|
||||||
crtc: crtc::Handle,
|
crtc: crtc::Handle,
|
||||||
) {
|
) {
|
||||||
let udev = self.backend.udev_mut();
|
let device = if let Some(device) = self.backends.get_mut(&node) {
|
||||||
|
|
||||||
let device = if let Some(device) = udev.backends.get_mut(&node) {
|
|
||||||
device
|
device
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut renderer = udev
|
let mut renderer = self
|
||||||
.gpu_manager
|
.gpu_manager
|
||||||
.single_renderer(&device.render_node)
|
.single_renderer(&device.render_node)
|
||||||
.expect("failed to get primary gpu MultiRenderer");
|
.expect("failed to get primary gpu MultiRenderer");
|
||||||
|
@ -1014,7 +1021,7 @@ impl State {
|
||||||
|
|
||||||
let (phys_w, phys_h) = connector.size().unwrap_or((0, 0));
|
let (phys_w, phys_h) = connector.size().unwrap_or((0, 0));
|
||||||
|
|
||||||
if self.pinnacle.space.outputs().any(|op| {
|
if pinnacle.space.outputs().any(|op| {
|
||||||
op.user_data()
|
op.user_data()
|
||||||
.get::<UdevOutputData>()
|
.get::<UdevOutputData>()
|
||||||
.is_some_and(|op_id| op_id.crtc == crtc)
|
.is_some_and(|op_id| op_id.crtc == crtc)
|
||||||
|
@ -1031,16 +1038,16 @@ impl State {
|
||||||
model,
|
model,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let global = output.create_global::<State>(&udev.display_handle);
|
let global = output.create_global::<State>(&self.display_handle);
|
||||||
|
|
||||||
output.with_state_mut(|state| state.serial = serial);
|
output.with_state_mut(|state| state.serial = serial);
|
||||||
|
|
||||||
output.set_preferred(wl_mode);
|
output.set_preferred(wl_mode);
|
||||||
|
|
||||||
self.pinnacle.output_focus_stack.set_focus(output.clone());
|
pinnacle.output_focus_stack.set_focus(output.clone());
|
||||||
|
|
||||||
let x = self.pinnacle.space.outputs().fold(0, |acc, o| {
|
let x = pinnacle.space.outputs().fold(0, |acc, o| {
|
||||||
let Some(geo) = self.pinnacle.space.output_geometry(o) else {
|
let Some(geo) = pinnacle.space.output_geometry(o) else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
acc + geo.size.w
|
acc + geo.size.w
|
||||||
|
@ -1092,14 +1099,14 @@ impl State {
|
||||||
};
|
};
|
||||||
|
|
||||||
let dmabuf_feedback = get_surface_dmabuf_feedback(
|
let dmabuf_feedback = get_surface_dmabuf_feedback(
|
||||||
udev.primary_gpu,
|
self.primary_gpu,
|
||||||
device.render_node,
|
device.render_node,
|
||||||
&mut udev.gpu_manager,
|
&mut self.gpu_manager,
|
||||||
&compositor,
|
&compositor,
|
||||||
);
|
);
|
||||||
|
|
||||||
let surface = RenderSurface {
|
let surface = RenderSurface {
|
||||||
display_handle: udev.display_handle.clone(),
|
display_handle: self.display_handle.clone(),
|
||||||
device_id: node,
|
device_id: node,
|
||||||
render_node: device.render_node,
|
render_node: device.render_node,
|
||||||
global: Some(global),
|
global: Some(global),
|
||||||
|
@ -1113,24 +1120,21 @@ impl State {
|
||||||
|
|
||||||
device.surfaces.insert(crtc, surface);
|
device.surfaces.insert(crtc, surface);
|
||||||
|
|
||||||
self.pinnacle
|
pinnacle.change_output_state(&output, Some(wl_mode), None, None, Some(position));
|
||||||
.change_output_state(&output, Some(wl_mode), None, None, Some(position));
|
|
||||||
|
|
||||||
// If there is saved connector state, the connector was previously plugged in.
|
// If there is saved connector state, the connector was previously plugged in.
|
||||||
// In this case, restore its tags and location.
|
// In this case, restore its tags and location.
|
||||||
// TODO: instead of checking the connector, check the monitor's edid info instead
|
// TODO: instead of checking the connector, check the monitor's edid info instead
|
||||||
if let Some(saved_state) = self
|
if let Some(saved_state) = pinnacle
|
||||||
.pinnacle
|
|
||||||
.config
|
.config
|
||||||
.connector_saved_states
|
.connector_saved_states
|
||||||
.get(&OutputName(output.name()))
|
.get(&OutputName(output.name()))
|
||||||
{
|
{
|
||||||
let ConnectorSavedState { loc, tags, scale } = saved_state;
|
let ConnectorSavedState { loc, tags, scale } = saved_state;
|
||||||
output.with_state_mut(|state| state.tags = tags.clone());
|
output.with_state_mut(|state| state.tags = tags.clone());
|
||||||
self.pinnacle
|
pinnacle.change_output_state(&output, None, None, *scale, Some(*loc));
|
||||||
.change_output_state(&output, None, None, *scale, Some(*loc));
|
|
||||||
} else {
|
} else {
|
||||||
self.pinnacle.signal_state.output_connect.signal(|buffer| {
|
pinnacle.signal_state.output_connect.signal(|buffer| {
|
||||||
buffer.push_back(OutputConnectResponse {
|
buffer.push_back(OutputConnectResponse {
|
||||||
output_name: Some(output.name()),
|
output_name: Some(output.name()),
|
||||||
})
|
})
|
||||||
|
@ -1141,15 +1145,14 @@ impl State {
|
||||||
/// A display was unplugged.
|
/// A display was unplugged.
|
||||||
fn connector_disconnected(
|
fn connector_disconnected(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
pinnacle: &mut Pinnacle,
|
||||||
node: DrmNode,
|
node: DrmNode,
|
||||||
_connector: connector::Info,
|
_connector: connector::Info,
|
||||||
crtc: crtc::Handle,
|
crtc: crtc::Handle,
|
||||||
) {
|
) {
|
||||||
tracing::debug!(?crtc, "connector_disconnected");
|
tracing::debug!(?crtc, "connector_disconnected");
|
||||||
|
|
||||||
let udev = self.backend.udev_mut();
|
let device = if let Some(device) = self.backends.get_mut(&node) {
|
||||||
|
|
||||||
let device = if let Some(device) = udev.backends.get_mut(&node) {
|
|
||||||
device
|
device
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
@ -1157,8 +1160,7 @@ impl State {
|
||||||
|
|
||||||
device.surfaces.remove(&crtc);
|
device.surfaces.remove(&crtc);
|
||||||
|
|
||||||
let output = self
|
let output = pinnacle
|
||||||
.pinnacle
|
|
||||||
.space
|
.space
|
||||||
.outputs()
|
.outputs()
|
||||||
.find(|o| {
|
.find(|o| {
|
||||||
|
@ -1171,7 +1173,7 @@ impl State {
|
||||||
|
|
||||||
if let Some(output) = output {
|
if let Some(output) = output {
|
||||||
// Save this output's state. It will be restored if the monitor gets replugged.
|
// Save this output's state. It will be restored if the monitor gets replugged.
|
||||||
self.pinnacle.config.connector_saved_states.insert(
|
pinnacle.config.connector_saved_states.insert(
|
||||||
OutputName(output.name()),
|
OutputName(output.name()),
|
||||||
ConnectorSavedState {
|
ConnectorSavedState {
|
||||||
loc: output.current_location(),
|
loc: output.current_location(),
|
||||||
|
@ -1179,15 +1181,10 @@ impl State {
|
||||||
scale: Some(output.current_scale()),
|
scale: Some(output.current_scale()),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
self.pinnacle.space.unmap_output(&output);
|
pinnacle.space.unmap_output(&output);
|
||||||
self.pinnacle
|
pinnacle.gamma_control_manager_state.output_removed(&output);
|
||||||
.gamma_control_manager_state
|
|
||||||
.output_removed(&output);
|
|
||||||
|
|
||||||
self.pinnacle
|
pinnacle.signal_state.output_disconnect.signal(|buffer| {
|
||||||
.signal_state
|
|
||||||
.output_disconnect
|
|
||||||
.signal(|buffer| {
|
|
||||||
buffer.push_back(OutputDisconnectResponse {
|
buffer.push_back(OutputDisconnectResponse {
|
||||||
output_name: Some(output.name()),
|
output_name: Some(output.name()),
|
||||||
})
|
})
|
||||||
|
@ -1195,10 +1192,8 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn device_changed(&mut self, node: DrmNode) {
|
fn device_changed(&mut self, pinnacle: &mut Pinnacle, node: DrmNode) {
|
||||||
let udev = self.backend.udev_mut();
|
let device = if let Some(device) = self.backends.get_mut(&node) {
|
||||||
|
|
||||||
let device = if let Some(device) = udev.backends.get_mut(&node) {
|
|
||||||
device
|
device
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
@ -1210,13 +1205,13 @@ impl State {
|
||||||
connector,
|
connector,
|
||||||
crtc: Some(crtc),
|
crtc: Some(crtc),
|
||||||
} => {
|
} => {
|
||||||
self.connector_connected(node, connector, crtc);
|
self.connector_connected(pinnacle, node, connector, crtc);
|
||||||
}
|
}
|
||||||
DrmScanEvent::Disconnected {
|
DrmScanEvent::Disconnected {
|
||||||
connector,
|
connector,
|
||||||
crtc: Some(crtc),
|
crtc: Some(crtc),
|
||||||
} => {
|
} => {
|
||||||
self.connector_disconnected(node, connector, crtc);
|
self.connector_disconnected(pinnacle, node, connector, crtc);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -1224,38 +1219,30 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A GPU was unplugged.
|
/// A GPU was unplugged.
|
||||||
fn device_removed(&mut self, node: DrmNode) {
|
fn device_removed(&mut self, pinnacle: &mut Pinnacle, node: DrmNode) {
|
||||||
let crtcs = {
|
let Some(device) = self.backends.get(&node) else {
|
||||||
let udev = self.backend.udev();
|
|
||||||
|
|
||||||
let Some(device) = udev.backends.get(&node) else {
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
device
|
let crtcs = device
|
||||||
.drm_scanner
|
.drm_scanner
|
||||||
.crtcs()
|
.crtcs()
|
||||||
.map(|(info, crtc)| (info.clone(), crtc))
|
.map(|(info, crtc)| (info.clone(), crtc))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>();
|
||||||
};
|
|
||||||
|
|
||||||
for (connector, crtc) in crtcs {
|
for (connector, crtc) in crtcs {
|
||||||
self.connector_disconnected(node, connector, crtc);
|
self.connector_disconnected(pinnacle, node, connector, crtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
tracing::debug!("Surfaces dropped");
|
tracing::debug!("Surfaces dropped");
|
||||||
|
|
||||||
let udev = self.backend.udev_mut();
|
|
||||||
|
|
||||||
// drop the backends on this side
|
// drop the backends on this side
|
||||||
if let Some(backend_data) = udev.backends.remove(&node) {
|
if let Some(backend_data) = self.backends.remove(&node) {
|
||||||
udev.gpu_manager
|
self.gpu_manager
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.remove_node(&backend_data.render_node);
|
.remove_node(&backend_data.render_node);
|
||||||
|
|
||||||
self.pinnacle
|
pinnacle.loop_handle.remove(backend_data.registration_token);
|
||||||
.loop_handle
|
|
||||||
.remove(backend_data.registration_token);
|
|
||||||
|
|
||||||
tracing::debug!("Dropping device");
|
tracing::debug!("Dropping device");
|
||||||
}
|
}
|
||||||
|
@ -1264,13 +1251,12 @@ impl State {
|
||||||
/// Mark [`OutputPresentationFeedback`]s as presented and schedule a new render on idle.
|
/// Mark [`OutputPresentationFeedback`]s as presented and schedule a new render on idle.
|
||||||
fn on_vblank(
|
fn on_vblank(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
pinnacle: &Pinnacle,
|
||||||
dev_id: DrmNode,
|
dev_id: DrmNode,
|
||||||
crtc: crtc::Handle,
|
crtc: crtc::Handle,
|
||||||
metadata: &mut Option<DrmEventMetadata>,
|
metadata: &mut Option<DrmEventMetadata>,
|
||||||
) {
|
) {
|
||||||
let udev = self.backend.udev_mut();
|
let Some(surface) = self
|
||||||
|
|
||||||
let Some(surface) = udev
|
|
||||||
.backends
|
.backends
|
||||||
.get_mut(&dev_id)
|
.get_mut(&dev_id)
|
||||||
.and_then(|device| device.surfaces.get_mut(&crtc))
|
.and_then(|device| device.surfaces.get_mut(&crtc))
|
||||||
|
@ -1278,7 +1264,7 @@ impl State {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let output = if let Some(output) = self.pinnacle.space.outputs().find(|o| {
|
let output = if let Some(output) = pinnacle.space.outputs().find(|o| {
|
||||||
let udev_op_data = o.user_data().get::<UdevOutputData>();
|
let udev_op_data = o.user_data().get::<UdevOutputData>();
|
||||||
udev_op_data
|
udev_op_data
|
||||||
.is_some_and(|data| data.device_id == surface.device_id && data.crtc == crtc)
|
.is_some_and(|data| data.device_id == surface.device_id && data.crtc == crtc)
|
||||||
|
@ -1313,10 +1299,7 @@ impl State {
|
||||||
| wp_presentation_feedback::Kind::HwCompletion,
|
| wp_presentation_feedback::Kind::HwCompletion,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(
|
(pinnacle.clock.now(), wp_presentation_feedback::Kind::Vsync)
|
||||||
self.pinnacle.clock.now(),
|
|
||||||
wp_presentation_feedback::Kind::Vsync,
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
feedback.presented(
|
feedback.presented(
|
||||||
|
@ -1345,12 +1328,12 @@ impl State {
|
||||||
surface.render_state = RenderState::Idle;
|
surface.render_state = RenderState::Idle;
|
||||||
|
|
||||||
if dirty {
|
if dirty {
|
||||||
self.schedule_render(&output);
|
self.schedule_render(&pinnacle.loop_handle, &output);
|
||||||
} else {
|
} else {
|
||||||
for window in self.pinnacle.windows.iter() {
|
for window in pinnacle.windows.iter() {
|
||||||
window.send_frame(
|
window.send_frame(
|
||||||
&output,
|
&output,
|
||||||
self.pinnacle.clock.now(),
|
pinnacle.clock.now(),
|
||||||
Some(Duration::ZERO),
|
Some(Duration::ZERO),
|
||||||
|_, _| Some(output.clone()),
|
|_, _| Some(output.clone()),
|
||||||
);
|
);
|
||||||
|
@ -1359,38 +1342,36 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render to the [`RenderSurface`] associated with the given `output`.
|
/// Render to the [`RenderSurface`] associated with the given `output`.
|
||||||
#[tracing::instrument(level = "debug", skip(self), fields(output = output.name()))]
|
#[tracing::instrument(level = "debug", skip(self, pinnacle), fields(output = output.name()))]
|
||||||
fn render_surface(&mut self, output: &Output) {
|
fn render_surface(&mut self, pinnacle: &mut Pinnacle, output: &Output) {
|
||||||
let udev = self.backend.udev_mut();
|
let Some(surface) = render_surface_for_output(output, &mut self.backends) else {
|
||||||
|
|
||||||
let Some(surface) = render_surface_for_output(output, &mut udev.backends) else {
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
assert!(matches!(surface.render_state, RenderState::Scheduled(_)));
|
assert!(matches!(surface.render_state, RenderState::Scheduled(_)));
|
||||||
|
|
||||||
// TODO get scale from the rendersurface when supporting HiDPI
|
// TODO get scale from the rendersurface when supporting HiDPI
|
||||||
let frame = udev.pointer_image.get_image(
|
let frame = self.pointer_image.get_image(
|
||||||
1,
|
1,
|
||||||
// output.current_scale().integer_scale() as u32,
|
// output.current_scale().integer_scale() as u32,
|
||||||
self.pinnacle.clock.now().into(),
|
pinnacle.clock.now().into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let render_node = surface.render_node;
|
let render_node = surface.render_node;
|
||||||
let primary_gpu = udev.primary_gpu;
|
let primary_gpu = self.primary_gpu;
|
||||||
let mut renderer = if primary_gpu == render_node {
|
let mut renderer = if primary_gpu == render_node {
|
||||||
udev.gpu_manager.single_renderer(&render_node)
|
self.gpu_manager.single_renderer(&render_node)
|
||||||
} else {
|
} else {
|
||||||
let format = surface.compositor.format();
|
let format = surface.compositor.format();
|
||||||
udev.gpu_manager
|
self.gpu_manager
|
||||||
.renderer(&primary_gpu, &render_node, format)
|
.renderer(&primary_gpu, &render_node, format)
|
||||||
}
|
}
|
||||||
.expect("failed to create MultiRenderer");
|
.expect("failed to create MultiRenderer");
|
||||||
|
|
||||||
let _ = renderer.upscale_filter(udev.upscale_filter);
|
let _ = renderer.upscale_filter(self.upscale_filter);
|
||||||
let _ = renderer.downscale_filter(udev.downscale_filter);
|
let _ = renderer.downscale_filter(self.downscale_filter);
|
||||||
|
|
||||||
let pointer_images = &mut udev.pointer_images;
|
let pointer_images = &mut self.pointer_images;
|
||||||
let pointer_image = pointer_images
|
let pointer_image = pointer_images
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(
|
.find_map(
|
||||||
|
@ -1418,36 +1399,35 @@ impl State {
|
||||||
texture
|
texture
|
||||||
});
|
});
|
||||||
|
|
||||||
let windows = self.pinnacle.space.elements().cloned().collect::<Vec<_>>();
|
let windows = pinnacle.space.elements().cloned().collect::<Vec<_>>();
|
||||||
|
|
||||||
let pointer_location = self
|
let pointer_location = pinnacle
|
||||||
.pinnacle
|
|
||||||
.seat
|
.seat
|
||||||
.get_pointer()
|
.get_pointer()
|
||||||
.map(|ptr| ptr.current_location())
|
.map(|ptr| ptr.current_location())
|
||||||
.unwrap_or((0.0, 0.0).into());
|
.unwrap_or((0.0, 0.0).into());
|
||||||
|
|
||||||
// set cursor
|
// set cursor
|
||||||
udev.pointer_element.set_texture(pointer_image.clone());
|
self.pointer_element.set_texture(pointer_image.clone());
|
||||||
|
|
||||||
// draw the cursor as relevant and
|
// draw the cursor as relevant and
|
||||||
// reset the cursor if the surface is no longer alive
|
// reset the cursor if the surface is no longer alive
|
||||||
if let CursorImageStatus::Surface(surface) = &self.pinnacle.cursor_status {
|
if let CursorImageStatus::Surface(surface) = &pinnacle.cursor_status {
|
||||||
if !surface.alive() {
|
if !surface.alive() {
|
||||||
self.pinnacle.cursor_status = CursorImageStatus::default_named();
|
pinnacle.cursor_status = CursorImageStatus::default_named();
|
||||||
} else {
|
} else {
|
||||||
send_frames_surface_tree(
|
send_frames_surface_tree(
|
||||||
surface,
|
surface,
|
||||||
output,
|
output,
|
||||||
self.pinnacle.clock.now(),
|
pinnacle.clock.now(),
|
||||||
Some(Duration::ZERO),
|
Some(Duration::ZERO),
|
||||||
|_, _| None,
|
|_, _| None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
udev.pointer_element
|
self.pointer_element
|
||||||
.set_status(self.pinnacle.cursor_status.clone());
|
.set_status(pinnacle.cursor_status.clone());
|
||||||
|
|
||||||
let pending_screencopy_with_cursor =
|
let pending_screencopy_with_cursor =
|
||||||
output.with_state(|state| state.screencopy.as_ref().map(|sc| sc.overlay_cursor()));
|
output.with_state(|state| state.screencopy.as_ref().map(|sc| sc.overlay_cursor()));
|
||||||
|
@ -1466,18 +1446,18 @@ impl State {
|
||||||
// | Unfortunately that means I can't composite the cursor separately from
|
// | Unfortunately that means I can't composite the cursor separately from
|
||||||
// | the screencopy, meaning if you have an active screencopy recording
|
// | the screencopy, meaning if you have an active screencopy recording
|
||||||
// | without cursor overlay then the cursor will dim/flicker out/disappear.
|
// | without cursor overlay then the cursor will dim/flicker out/disappear.
|
||||||
udev.pointer_element
|
self.pointer_element
|
||||||
.set_element_kind(element::Kind::Unspecified);
|
.set_element_kind(element::Kind::Unspecified);
|
||||||
let pointer_render_elements = pointer_render_elements(
|
let pointer_render_elements = pointer_render_elements(
|
||||||
output,
|
output,
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
&self.pinnacle.space,
|
&pinnacle.space,
|
||||||
pointer_location,
|
pointer_location,
|
||||||
&mut self.pinnacle.cursor_status,
|
&mut pinnacle.cursor_status,
|
||||||
self.pinnacle.dnd_icon.as_ref(),
|
pinnacle.dnd_icon.as_ref(),
|
||||||
&udev.pointer_element,
|
&self.pointer_element,
|
||||||
);
|
);
|
||||||
udev.pointer_element.set_element_kind(element::Kind::Cursor);
|
self.pointer_element.set_element_kind(element::Kind::Cursor);
|
||||||
output_render_elements.extend(pointer_render_elements);
|
output_render_elements.extend(pointer_render_elements);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1485,11 +1465,11 @@ impl State {
|
||||||
let pointer_render_elements = pointer_render_elements(
|
let pointer_render_elements = pointer_render_elements(
|
||||||
output,
|
output,
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
&self.pinnacle.space,
|
&pinnacle.space,
|
||||||
pointer_location,
|
pointer_location,
|
||||||
&mut self.pinnacle.cursor_status,
|
&mut pinnacle.cursor_status,
|
||||||
self.pinnacle.dnd_icon.as_ref(),
|
pinnacle.dnd_icon.as_ref(),
|
||||||
&udev.pointer_element,
|
&self.pointer_element,
|
||||||
);
|
);
|
||||||
output_render_elements.extend(pointer_render_elements);
|
output_render_elements.extend(pointer_render_elements);
|
||||||
}
|
}
|
||||||
|
@ -1498,7 +1478,7 @@ impl State {
|
||||||
output_render_elements.extend(crate::render::output_render_elements(
|
output_render_elements.extend(crate::render::output_render_elements(
|
||||||
output,
|
output,
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
&self.pinnacle.space,
|
&pinnacle.space,
|
||||||
&windows,
|
&windows,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -1521,13 +1501,13 @@ impl State {
|
||||||
output,
|
output,
|
||||||
surface,
|
surface,
|
||||||
&render_frame_result,
|
&render_frame_result,
|
||||||
&self.pinnacle.loop_handle,
|
&pinnacle.loop_handle,
|
||||||
);
|
);
|
||||||
|
|
||||||
super::post_repaint(
|
super::post_repaint(
|
||||||
output,
|
output,
|
||||||
&render_frame_result.states,
|
&render_frame_result.states,
|
||||||
&self.pinnacle.space,
|
&pinnacle.space,
|
||||||
surface
|
surface
|
||||||
.dmabuf_feedback
|
.dmabuf_feedback
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -1535,8 +1515,8 @@ impl State {
|
||||||
render_feedback: &feedback.render_feedback,
|
render_feedback: &feedback.render_feedback,
|
||||||
scanout_feedback: &feedback.scanout_feedback,
|
scanout_feedback: &feedback.scanout_feedback,
|
||||||
}),
|
}),
|
||||||
Duration::from(self.pinnacle.clock.now()),
|
Duration::from(pinnacle.clock.now()),
|
||||||
&self.pinnacle.cursor_status,
|
&pinnacle.cursor_status,
|
||||||
);
|
);
|
||||||
|
|
||||||
let rendered = !render_frame_result.is_empty;
|
let rendered = !render_frame_result.is_empty;
|
||||||
|
@ -1544,7 +1524,7 @@ impl State {
|
||||||
if rendered {
|
if rendered {
|
||||||
let output_presentation_feedback = take_presentation_feedback(
|
let output_presentation_feedback = take_presentation_feedback(
|
||||||
output,
|
output,
|
||||||
&self.pinnacle.space,
|
&pinnacle.space,
|
||||||
&render_frame_result.states,
|
&render_frame_result.states,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1740,14 +1720,13 @@ fn handle_pending_screencopy<'a>(
|
||||||
// renderer.wait(&sync_point)?; // no-op
|
// renderer.wait(&sync_point)?; // no-op
|
||||||
|
|
||||||
// INFO: I have literally no idea why but doing
|
// INFO: I have literally no idea why but doing
|
||||||
// | a blit_to offscreen -> dmabuf leads to some weird
|
// a blit_to offscreen -> dmabuf leads to some weird
|
||||||
// | artifacting within the first few frames of a wf-recorder
|
// artifacting within the first few frames of a wf-recorder
|
||||||
// | recording, but doing it with the targets reversed
|
// recording, but doing it with the targets reversed
|
||||||
// | is completely fine???? Bruh that essentially runs the same internal
|
// is completely fine???? Bruh that essentially runs the same internal
|
||||||
// | code and I don't understand why there's different behavior.
|
// code and I don't understand why there's different behavior.
|
||||||
// |.
|
// I can see in the code that `blit_to` is missing a `self.unbind()?`
|
||||||
// | I can see in the code that `blit_to` is missing a `self.unbind()?`
|
// call, but adding that back in doesn't fix anything. So strange
|
||||||
// | call, but adding that back in doesn't fix anything. So strange
|
|
||||||
renderer.bind(dmabuf)?;
|
renderer.bind(dmabuf)?;
|
||||||
|
|
||||||
renderer.blit_from(
|
renderer.blit_from(
|
||||||
|
|
Loading…
Add table
Reference in a new issue