Separate stuff that took in State

I love me some non-overlapping borrows
This commit is contained in:
Ottatop 2024-04-26 20:25:40 -05:00
parent b99cc8ffce
commit 8c0bce7191

View file

@ -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(