diff --git a/src/backend/kms/device.rs b/src/backend/kms/device.rs index 465f13cc..2cc043c3 100644 --- a/src/backend/kms/device.rs +++ b/src/backend/kms/device.rs @@ -88,62 +88,54 @@ pub type GbmDrmOutputManager = DrmOutputManager< DrmDeviceFd, >; +#[derive(Debug)] pub struct Device { + pub inner: InnerDevice, + pub drm: GbmDrmOutputManager, + + supports_atomic: bool, + event_token: Option, + pub socket: Option, +} + +#[derive(Debug)] +pub struct LockedDevice<'a> { + pub inner: &'a mut InnerDevice, + pub drm: LockedGbmDrmOutputManager<'a>, +} + +pub struct InnerDevice { pub dev_node: DrmNode, pub render_node: DrmNode, pub egl: Option, pub outputs: HashMap, pub surfaces: HashMap, - pub drm: GbmDrmOutputManager, pub gbm: GbmDevice, - supports_atomic: bool, - pub leased_connectors: Vec<(connector::Handle, crtc::Handle)>, pub leasing_global: Option, pub active_leases: Vec, pub active_buffers: HashSet>, - - event_token: Option, - pub socket: Option, } -impl fmt::Debug for Device { +impl fmt::Debug for InnerDevice { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Device") - .field("dev_node", &self.render_node) + .field("dev_node", &self.dev_node) .field("render_node", &self.render_node) + .field("egl", &self.egl) .field("outputs", &self.outputs) .field("surfaces", &self.surfaces) - .field("drm", &"..") - .field("egl", &self.egl) - .field("supports_atomic", &self.supports_atomic) + .field("gbm", &"..") .field("leased_connectors", &self.leased_connectors) .field("leasing_global", &self.leasing_global) .field("active_leases", &self.active_leases) - .field("event_token", &self.event_token) - .field("socket", &self.socket) + .field("active_buffers", &self.active_buffers.len()) .finish() } } -pub struct LockedDevice<'a> { - pub dev_node: &'a DrmNode, - pub render_node: &'a DrmNode, - pub egl: &'a mut Option, - - pub outputs: &'a HashMap, - pub surfaces: &'a mut HashMap, - pub drm: LockedGbmDrmOutputManager<'a>, - pub gbm: &'a GbmDevice, - - pub leased_connectors: &'a mut Vec<(connector::Handle, crtc::Handle)>, - pub leasing_global: &'a mut Option, - pub active_leases: &'a mut Vec, - pub active_buffers: &'a HashSet>, -} - pub fn init_egl(gbm: &GbmDevice) -> Result { let path = gbm.dev_path(); @@ -268,7 +260,7 @@ impl State { move |event, metadata, state: &mut State| match event { DrmEvent::VBlank(crtc) => { if let Some(device) = state.backend.kms().drm_devices.get_mut(&drm_node) { - if let Some(surface) = device.surfaces.get_mut(&crtc) { + if let Some(surface) = device.inner.surfaces.get_mut(&crtc) { surface.on_vblank(metadata.take()); } } @@ -309,31 +301,32 @@ impl State { ); let mut device = Device { - dev_node: drm_node, - render_node, - egl: None, - - outputs: HashMap::new(), - surfaces: HashMap::new(), drm, - gbm, + inner: InnerDevice { + dev_node: drm_node, + render_node, + egl: None, + + outputs: HashMap::new(), + surfaces: HashMap::new(), + gbm, + + leased_connectors: Vec::new(), + leasing_global: DrmLeaseState::new::(dh, &drm_node) + .map_err(|err| { + // TODO: replace with inspect_err, once stable + warn!( + ?err, + "Failed to initialize drm lease global for: {}", drm_node + ); + err + }) + .ok(), + active_leases: Vec::new(), + active_buffers: HashSet::new(), + }, supports_atomic, - - leased_connectors: Vec::new(), - leasing_global: DrmLeaseState::new::(dh, &drm_node) - .map_err(|err| { - // TODO: replace with inspect_err, once stable - warn!( - ?err, - "Failed to initialize drm lease global for: {}", drm_node - ); - err - }) - .ok(), - active_leases: Vec::new(), - active_buffers: HashSet::new(), - event_token: Some(token), socket, }; @@ -344,7 +337,8 @@ impl State { { for (conn, maybe_crtc) in connectors { - match device.connector_added( + match device.inner.connector_added( + device.drm.device_mut(), self.backend.kms().primary_node.clone(), conn, maybe_crtc, @@ -359,7 +353,7 @@ impl State { w += output.geometry().size.w as u32; wl_outputs.push(output.clone()); } - device.outputs.insert(conn, output); + device.inner.outputs.insert(conn, output); } Err(err) => { warn!(?err, "Failed to initialize output, skipping"); @@ -411,26 +405,29 @@ impl State { for conn in changes.removed { // contains conns with updated crtcs, just drop the surface and re-create if let Some(pos) = device + .inner .leased_connectors .iter() .position(|(handle, _)| *handle == conn) { - let _ = device.leased_connectors.remove(pos); - if let Some(leasing_state) = device.leasing_global.as_mut() { + let _ = device.inner.leased_connectors.remove(pos); + if let Some(leasing_state) = device.inner.leasing_global.as_mut() { leasing_state.withdraw_connector(conn); } } else if let Some(crtc) = device + .inner .surfaces .iter() .find_map(|(crtc, surface)| (surface.connector == conn).then_some(crtc)) .cloned() { - device.surfaces.remove(&crtc).unwrap(); + device.inner.surfaces.remove(&crtc).unwrap(); } if !changes.added.iter().any(|(c, _)| c == &conn) { outputs_removed.push( device + .inner .outputs .remove(&conn) .expect("Connector without output?"), @@ -439,7 +436,8 @@ impl State { } for (conn, maybe_crtc) in changes.added { - match device.connector_added( + match device.inner.connector_added( + device.drm.device_mut(), backend.primary_node.clone(), conn, maybe_crtc, @@ -455,7 +453,7 @@ impl State { outputs_added.push(output.clone()); } - device.outputs.insert(conn, output); + device.inner.outputs.insert(conn, output); } Err(err) => { warn!(?err, "Failed to initialize output, skipping"); @@ -502,15 +500,17 @@ impl State { let drm_node = backend .drm_devices .values() - .find_map(|device| (device.dev_node.dev_id() == dev).then_some(device.dev_node)) + .find_map(|device| { + (device.inner.dev_node.dev_id() == dev).then_some(device.inner.dev_node) + }) .with_context(|| format!("Couldn't find drm node for {}", dev))?; let mut outputs_removed = Vec::new(); if let Some(mut device) = backend.drm_devices.shift_remove(&drm_node) { - if let Some(mut leasing_global) = device.leasing_global.take() { + if let Some(mut leasing_global) = device.inner.leasing_global.take() { leasing_global.disable_global::(); } - for surface in device.surfaces.values_mut() { + for surface in device.inner.surfaces.values_mut() { outputs_removed.push(surface.output.clone()); } if let Some(token) = device.event_token.take() { @@ -523,12 +523,12 @@ impl State { .destroy_global::(dh, socket.dmabuf_global); dh.remove_global::(socket.drm_global); } - backend.api.as_mut().remove_node(&device.render_node); + backend.api.as_mut().remove_node(&device.inner.render_node); backend .primary_node .write() .unwrap() - .take_if(|node| node == &device.render_node); + .take_if(|node| node == &device.inner.render_node); }; self.common .output_configuration_state @@ -570,11 +570,13 @@ impl Device { drm_helpers::display_configuration(self.drm.device_mut(), self.supports_atomic)?; let surfaces = self + .inner .surfaces .iter() .map(|(c, s)| (s.connector, *c)) .chain( - self.leased_connectors + self.inner + .leased_connectors .iter() .map(|(conn, crtc)| (*conn, *crtc)), ) @@ -591,6 +593,7 @@ impl Device { .collect::>(); let removed = self + .inner .outputs .iter() .filter(|(conn, _)| match config.get(conn) { @@ -605,17 +608,8 @@ impl Device { pub fn lock(&mut self) -> LockedDevice<'_> { LockedDevice { - dev_node: &self.dev_node, - render_node: &self.render_node, - egl: &mut self.egl, - outputs: &self.outputs, - surfaces: &mut self.surfaces, + inner: &mut self.inner, drm: self.drm.lock(), - gbm: &self.gbm, - leased_connectors: &mut self.leased_connectors, - leasing_global: &mut self.leasing_global, - active_leases: &mut self.active_leases, - active_buffers: &mut self.active_buffers, } } } @@ -629,13 +623,14 @@ impl<'a> LockedDevice<'a> { clock: &Clock, shell: &Arc>, ) -> Result<()> { - for surface in self.surfaces.values_mut() { + for surface in self.inner.surfaces.values_mut() { surface.allow_frame_flags(flag, flags); } if !flag { let now = clock.now(); let output_map = self + .inner .surfaces .iter() .filter(|(_, s)| s.is_active()) @@ -645,7 +640,7 @@ impl<'a> LockedDevice<'a> { for (crtc, compositor) in self.drm.compositors().iter() { let elements = match output_map.get(crtc) { Some(output) => output_elements( - Some(&self.render_node), + Some(&self.inner.render_node), renderer, shell, now, @@ -702,7 +697,7 @@ impl<'a> LockedDevice<'a> { )?; for (crtc, comp) in self.drm.compositors() { - let Some(surface) = self.surfaces.get_mut(crtc) else { + let Some(surface) = self.inner.surfaces.get_mut(crtc) else { continue; }; let comp = comp.lock().unwrap(); @@ -725,25 +720,16 @@ impl<'a> LockedDevice<'a> { } } -pub trait MaybeLockedDevice { - fn dev_node(&self) -> DrmNode; - fn render_node(&self) -> DrmNode; - fn output(&self, conn: &connector::Handle) -> Option<&Output>; - fn drm_device_mut(&mut self) -> &mut DrmDevice; - fn gbm(&self) -> &GbmDevice; - fn egl(&mut self) -> &mut Option; - fn insert_surface(&mut self, crtc: crtc::Handle, surface: Surface); +impl InnerDevice { + pub fn in_use(&self, primary: Option<&DrmNode>) -> bool { + Some(&self.render_node) == primary + || !self.surfaces.is_empty() + || !self.active_buffers.is_empty() + } - fn in_use(&self, primary: Option<&DrmNode>) -> bool; - fn add_leased_connector( - &mut self, - crtc: crtc::Handle, - conn: connector::Handle, - output: &Output, - ); - - fn connector_added( + pub fn connector_added( &mut self, + drm: &mut DrmDevice, primary_node: Arc>>, conn: connector::Handle, maybe_crtc: Option, @@ -754,27 +740,39 @@ pub trait MaybeLockedDevice { startup_done: Arc, ) -> Result<(Output, bool)> { let output = self - .output(&conn) + .outputs + .get(&conn) .cloned() .map(|output| Ok(output)) - .unwrap_or_else(|| create_output_for_conn(self.drm_device_mut(), conn)) + .unwrap_or_else(|| create_output_for_conn(drm, conn)) .context("Failed to create `Output`")?; - let non_desktop = - match drm_helpers::get_property_val(self.drm_device_mut(), conn, "non-desktop") { - Ok((val_type, value)) => val_type.convert_value(value).as_boolean().unwrap(), - Err(err) => { - warn!( - ?err, - "Failed to determine if connector is meant desktop usage, assuming so." - ); - false - } - }; + let non_desktop = match drm_helpers::get_property_val(drm, conn, "non-desktop") { + Ok((val_type, value)) => val_type.convert_value(value).as_boolean().unwrap(), + Err(err) => { + warn!( + ?err, + "Failed to determine if connector is meant desktop usage, assuming so." + ); + false + } + }; if non_desktop { if let Some(crtc) = maybe_crtc { - self.add_leased_connector(crtc, conn, &output); + self.leased_connectors.push((conn, crtc)); + info!( + "Connector {} is non-desktop, setting up for leasing", + output.name() + ); + if let Some(lease_state) = self.leasing_global.as_mut() { + let physical = output.physical_properties(); + lease_state.add_connector::( + conn, + output.name(), + format!("{} {}", physical.make, physical.model), + ); + } } else { warn!( "Connector {} is non-desktop, but we don't have a free crtc: not leasing", @@ -788,7 +786,7 @@ pub trait MaybeLockedDevice { .user_data() .insert_if_missing(|| RefCell::new(OutputConfig::default())); - populate_modes(self.drm_device_mut(), &output, conn, position) + populate_modes(drm, &output, conn, position) .with_context(|| "Failed to enumerate connector modes")?; let has_surface = if let Some(crtc) = maybe_crtc { @@ -797,15 +795,15 @@ pub trait MaybeLockedDevice { crtc, conn, primary_node, - self.dev_node(), - self.render_node(), + self.dev_node, + self.render_node, evlh, screen_filter, shell, startup_done, ) { Ok(data) => { - self.insert_surface(crtc, data); + self.surfaces.insert(crtc, data); true } Err(err) => { @@ -830,14 +828,14 @@ pub trait MaybeLockedDevice { } } - fn update_egl( + pub fn update_egl( &mut self, primary_node: Option<&DrmNode>, api: &mut GbmGlowBackend, ) -> Result { if self.in_use(primary_node) { - if self.egl().is_none() { - let egl = init_egl(self.gbm()).context("Failed to create EGL context")?; + if self.egl.is_none() { + let egl = init_egl(&self.gbm).context("Failed to create EGL context")?; let mut renderer = unsafe { GlowRenderer::new( EGLContext::new_shared_with_priority( @@ -851,96 +849,34 @@ pub trait MaybeLockedDevice { }; init_shaders(renderer.borrow_mut()).context("Failed to compile shaders")?; api.add_node( - self.render_node(), + self.render_node, GbmAllocator::new( - self.gbm().clone(), + self.gbm.clone(), // SCANOUT because stride bugs GbmBufferFlags::RENDERING | GbmBufferFlags::SCANOUT, ), renderer, ); - *self.egl() = Some(egl); + self.egl = Some(egl); } Ok(true) } else { - if self.egl().is_some() { - let _ = self.egl().take(); - api.remove_node(&self.render_node()); + if self.egl.is_some() { + let _ = self.egl.take(); + api.remove_node(&self.render_node); } Ok(false) } } - fn update_surface_nodes<'b>( + pub fn update_surface_nodes<'b>( &mut self, used_devices: &HashSet, - others: impl Iterator, + mut others: impl Iterator, ) -> Result<()> where - Self: 'b; -} - -impl MaybeLockedDevice for Device { - fn dev_node(&self) -> DrmNode { - self.dev_node - } - - fn render_node(&self) -> DrmNode { - self.render_node - } - - fn output(&self, conn: &connector::Handle) -> Option<&Output> { - self.outputs.get(conn) - } - - fn drm_device_mut(&mut self) -> &mut DrmDevice { - self.drm.device_mut() - } - - fn gbm(&self) -> &GbmDevice { - &self.gbm - } - - fn egl(&mut self) -> &mut Option { - &mut self.egl - } - - fn insert_surface(&mut self, crtc: crtc::Handle, surface: Surface) { - self.surfaces.insert(crtc, surface); - } - - fn in_use(&self, primary: Option<&DrmNode>) -> bool { - Some(&self.render_node) == primary - || !self.surfaces.is_empty() - || !self.active_buffers.is_empty() - } - - fn add_leased_connector( - &mut self, - crtc: crtc::Handle, - conn: connector::Handle, - output: &Output, - ) { - self.leased_connectors.push((conn, crtc)); - info!( - "Connector {} is non-desktop, setting up for leasing", - output.name() - ); - if let Some(lease_state) = self.leasing_global.as_mut() { - let physical = output.physical_properties(); - lease_state.add_connector::( - conn, - output.name(), - format!("{} {}", physical.make, physical.model), - ); - } - } - - fn update_surface_nodes<'b>( - &mut self, - used_devices: &HashSet, - mut others: impl Iterator, - ) -> Result<()> { + Self: 'b, + { for surface in self.surfaces.values_mut() { let known_nodes = surface.known_nodes().clone(); for gone_device in known_nodes.difference(&used_devices) { @@ -980,7 +916,59 @@ impl MaybeLockedDevice for Device { } } -impl<'a> MaybeLockedDevice for LockedDevice<'a> { +impl Device { + /* + fn dev_node(&self) -> DrmNode { + self.dev_node + } + + fn render_node(&self) -> DrmNode { + self.render_node + } + + fn output(&self, conn: &connector::Handle) -> Option<&Output> { + self.outputs.get(conn) + } + + fn drm_device_mut(&mut self) -> &mut DrmDevice { + self.drm.device_mut() + } + + fn gbm(&self) -> &GbmDevice { + &self.gbm + } + + fn egl(&mut self) -> &mut Option { + &mut self.egl + } + + fn insert_surface(&mut self, crtc: crtc::Handle, surface: Surface) { + } + + fn in_use(&self, primary: Option<&DrmNode>) -> bool { + } + + fn add_leased_connector( + &mut self, + crtc: crtc::Handle, + conn: connector::Handle, + output: &Output, + ) { + + } + + fn update_surface_nodes<'b>( + &mut self, + used_devices: &HashSet, + mut others: impl Iterator, + ) -> Result<()> { + + } + */ +} + +impl<'a> LockedDevice<'a> { + /* fn dev_node(&self) -> DrmNode { *self.dev_node } @@ -1081,6 +1069,7 @@ impl<'a> MaybeLockedDevice for LockedDevice<'a> { Ok(()) } + */ } fn create_output_for_conn(drm: &mut DrmDevice, conn: connector::Handle) -> Result { diff --git a/src/backend/kms/mod.rs b/src/backend/kms/mod.rs index 108ce231..6a07fdec 100644 --- a/src/backend/kms/mod.rs +++ b/src/backend/kms/mod.rs @@ -53,12 +53,10 @@ mod drm_helpers; pub mod render; mod socket; mod surface; +use device::*; pub(crate) use surface::Surface; pub use surface::Timings; -pub use device::MaybeLockedDevice; -use device::*; - use super::render::{output_elements, CursorMode, CLEAR_COLOR}; #[derive(Debug)] @@ -203,17 +201,18 @@ fn determine_primary_gpu( seat: String, ) -> Result> { if let Some(device) = dev_var("COSMIC_RENDER_DEVICE") { - if let Some(node) = drm_devices - .values() - .find_map(|dev| device.matches(&dev.render_node).then_some(dev.render_node)) - { + if let Some(node) = drm_devices.values().find_map(|dev| { + device + .matches(&dev.inner.render_node) + .then_some(dev.inner.render_node) + }) { return Ok(Some(node)); } } // try to find builtin display for dev in drm_devices.values() { - if dev.surfaces.values().any(|s| { + if dev.inner.surfaces.values().any(|s| { if let Some(conn_info) = dev.drm.device().get_connector(s.connector, false).ok() { let i = conn_info.interface(); i == Interface::EmbeddedDisplayPort || i == Interface::LVDS || i == Interface::DSI @@ -221,20 +220,23 @@ fn determine_primary_gpu( false } }) { - return Ok(Some(dev.render_node)); + return Ok(Some(dev.inner.render_node)); } } // else try to find the boot gpu let boot = determine_boot_gpu(seat); if let Some(boot) = boot { - if drm_devices.values().any(|dev| dev.render_node == boot) { + if drm_devices + .values() + .any(|dev| dev.inner.render_node == boot) + { return Ok(Some(boot)); } } // else just take the first - Ok(drm_devices.values().next().map(|dev| dev.render_node)) + Ok(drm_devices.values().next().map(|dev| dev.inner.render_node)) } /// Create `GlowRenderer` for `EGL_MESA_device_software` device, if present @@ -316,7 +318,7 @@ impl State { if let Err(err) = device.drm.lock().activate(true) { error!(?err, "Failed to resume drm device"); } - if let Some(lease_state) = device.leasing_global.as_mut() { + if let Some(lease_state) = device.inner.leasing_global.as_mut() { lease_state.resume::(); } } @@ -367,10 +369,10 @@ impl State { backend.libinput.suspend(); for device in backend.drm_devices.values_mut() { device.drm.pause(); - if let Some(lease_state) = device.leasing_global.as_mut() { + if let Some(lease_state) = device.inner.leasing_global.as_mut() { lease_state.suspend(); } - for surface in device.surfaces.values_mut() { + for surface in device.inner.surfaces.values_mut() { surface.suspend(); } } @@ -451,12 +453,16 @@ impl KmsState { let mut last_err = anyhow::anyhow!("Dmabuf cannot be imported on any gpu"); for device in expected_node.into_iter().chain(other_nodes.into_iter()) { let mut _egl = None; - let egl_display = if let Some(egl_display) = - device.egl.as_ref().map(|internals| &internals.display) + let egl_display = if let Some(egl_display) = device + .inner + .egl + .as_ref() + .map(|internals| &internals.display) { egl_display } else { - _egl = Some(init_egl(&device.gbm).context("Failed to initialize egl context")?); + _egl = + Some(init_egl(&device.inner.gbm).context("Failed to initialize egl context")?); &_egl.as_ref().unwrap().display }; @@ -466,7 +472,7 @@ impl KmsState { { trace!( "Skipping import of dmabuf on {:?}: unsupported format", - device.render_node + device.inner.render_node ); continue; } @@ -480,7 +486,7 @@ impl KmsState { image, ); }; - device.render_node + device.inner.render_node }) .map_err(Into::into); @@ -490,7 +496,11 @@ impl KmsState { return Ok(node); } Err(err) => { - trace!(?err, "Failed to import dmabuf on {:?}", device.render_node); + trace!( + ?err, + "Failed to import dmabuf on {:?}", + device.inner.render_node + ); last_err = err; } } @@ -503,7 +513,7 @@ impl KmsState { for surface in self .drm_devices .values() - .flat_map(|d| d.surfaces.values()) + .flat_map(|d| d.inner.surfaces.values()) .filter(|s| s.output == *output || s.output.mirroring().is_some_and(|o| &o == output)) { surface.schedule_render(); @@ -513,14 +523,14 @@ impl KmsState { pub fn target_node_for_output(&self, output: &Output) -> Option { self.drm_devices .values() - .find(|dev| dev.surfaces.values().any(|s| s.output == *output)) - .map(|dev| &dev.render_node) + .find(|dev| dev.inner.surfaces.values().any(|s| s.output == *output)) + .map(|dev| &dev.inner.render_node) .copied() } pub fn update_screen_filter(&mut self, screen_filter: &ScreenFilter) -> Result<()> { for device in self.drm_devices.values_mut() { - for surface in device.surfaces.values_mut() { + for surface in device.inner.surfaces.values_mut() { surface.set_screen_filter(screen_filter.clone()); } } @@ -538,8 +548,11 @@ impl KmsState { let mut used_devices = HashSet::new(); for device in self.drm_devices.values_mut() { - if device.update_egl(primary_node.as_ref(), self.api.as_mut())? { - used_devices.insert(device.render_node()); + if device + .inner + .update_egl(primary_node.as_ref(), self.api.as_mut())? + { + used_devices.insert(device.inner.render_node); } } @@ -552,14 +565,16 @@ impl KmsState { let all_devices = self .drm_devices .values() - .map(|d| d.render_node) + .map(|d| d.inner.render_node) .collect::>(); for node in all_devices { let (mut device, others) = self .drm_devices .values_mut() - .partition::, _>(|d| d.render_node == node); - device[0].update_surface_nodes(&used_devices, others.iter().map(|device| &**device))?; + .partition::, _>(|d| d.inner.render_node == node); + device[0] + .inner + .update_surface_nodes(&used_devices, others.iter().map(|device| &device.inner))?; } Ok(()) @@ -584,7 +599,7 @@ impl<'a> KmsGuard<'a> { for surface in self .drm_devices .values() - .flat_map(|d| d.surfaces.values()) + .flat_map(|d| d.inner.surfaces.values()) .filter(|s| s.output == *output || s.output.mirroring().is_some_and(|o| &o == output)) { surface.schedule_render(); @@ -596,8 +611,11 @@ impl<'a> KmsGuard<'a> { let mut used_devices = HashSet::new(); for device in self.drm_devices.values_mut() { - if device.update_egl(primary_node.as_ref(), self.api.as_mut())? { - used_devices.insert(device.render_node()); + if device + .inner + .update_egl(primary_node.as_ref(), self.api.as_mut())? + { + used_devices.insert(device.inner.render_node); } } @@ -610,14 +628,16 @@ impl<'a> KmsGuard<'a> { let all_devices = self .drm_devices .values() - .map(|d| d.render_node) + .map(|d| d.inner.render_node) .collect::>(); for node in all_devices { let (mut device, others) = self .drm_devices .values_mut() - .partition::, _>(|d| d.render_node == node); - device[0].update_surface_nodes(&used_devices, others.iter().map(|device| &**device))?; + .partition::, _>(|d| d.inner.render_node == node); + device[0] + .inner + .update_surface_nodes(&used_devices, others.iter().map(|device| &*device.inner))?; } Ok(()) @@ -628,10 +648,12 @@ impl<'a> KmsGuard<'a> { .values() .flat_map(|device| { device + .inner .outputs .iter() .filter(|(conn, _)| { !device + .inner .leased_connectors .iter() .any(|(leased_conn, _)| *conn == leased_conn) @@ -658,10 +680,12 @@ impl<'a> KmsGuard<'a> { // we only want outputs exposed to wayland - not leased ones // but that is also not all surface, because that doesn't contain all detected, but unmapped outputs let outputs = device + .inner .outputs .iter() .filter(|(conn, _)| { !device + .inner .leased_connectors .iter() .any(|(leased_conn, _)| *conn == leased_conn) @@ -681,6 +705,7 @@ impl<'a> KmsGuard<'a> { .iter() .filter(|crtc| { !device + .inner .surfaces .get(crtc) .is_some_and(|surface| surface.output.is_enabled()) @@ -690,10 +715,12 @@ impl<'a> KmsGuard<'a> { let open_conns = outputs .iter() .filter(|output| { - output.is_enabled() && !device.surfaces.values().any(|s| &s.output == *output) + output.is_enabled() + && !device.inner.surfaces.values().any(|s| &s.output == *output) }) .flat_map(|output| { device + .inner .outputs .iter() .find_map(|(conn, o)| (output == o).then_some(*conn)) @@ -731,6 +758,7 @@ impl<'a> KmsGuard<'a> { if !test_only { for output in outputs.iter().filter(|o| !o.is_enabled()) { device + .inner .surfaces .retain(|_, surface| surface.output != *output); } @@ -740,7 +768,8 @@ impl<'a> KmsGuard<'a> { let mut w = shell.read().global_space().size.w as u32; if !test_only { for (conn, crtc) in new_pairings { - let (output, _) = device.connector_added( + let (output, _) = device.inner.connector_added( + device.drm.device_mut(), self.primary_node.clone(), conn, Some(crtc), @@ -765,6 +794,7 @@ impl<'a> KmsGuard<'a> { for device in self.drm_devices.values_mut() { let now = clock.now(); let output_map = device + .inner .surfaces .iter() .filter(|(_, s)| s.is_active()) @@ -772,7 +802,7 @@ impl<'a> KmsGuard<'a> { .collect::>(); // reconfigure existing - for (crtc, surface) in device.surfaces.iter_mut() { + for (crtc, surface) in device.inner.surfaces.iter_mut() { let output_config = surface.output.config(); let drm = &mut device.drm; @@ -815,13 +845,13 @@ impl<'a> KmsGuard<'a> { let mut renderer = self .api - .single_renderer(&device.render_node) + .single_renderer(&device.inner.render_node) .with_context(|| "Failed to create renderer")?; let mut elements = DrmOutputRenderElements::default(); for (crtc, output) in output_map.iter() { let output_elements = output_elements( - Some(&device.render_node), + Some(&device.inner.render_node), &mut renderer, &shell, now, @@ -924,13 +954,13 @@ impl<'a> KmsGuard<'a> { let mut renderer = self .api - .single_renderer(&device.render_node) + .single_renderer(&device.inner.render_node) .with_context(|| "Failed to create renderer")?; let mut elements = DrmOutputRenderElements::default(); for (crtc, output) in output_map.iter() { let output_elements = output_elements( - Some(&device.render_node), + Some(&device.inner.render_node), &mut renderer, &shell, now, @@ -950,15 +980,16 @@ impl<'a> KmsGuard<'a> { } // configure primary scanout allowance - if !device.surfaces.is_empty() { + if !device.inner.surfaces.is_empty() { let mut renderer = self .api - .single_renderer(&device.render_node) + .single_renderer(&device.inner.render_node) .with_context(|| "Failed to create renderer")?; device .allow_primary_scanout_any( device + .inner .surfaces .values() .filter(|s| s.output.is_enabled() && s.output.mirroring().is_none()) @@ -973,7 +1004,7 @@ impl<'a> KmsGuard<'a> { let mut elements = DrmOutputRenderElements::default(); for (crtc, output) in output_map.iter() { let output_elements = output_elements( - Some(&device.render_node), + Some(&device.inner.render_node), &mut renderer, &shell, now, @@ -998,7 +1029,7 @@ impl<'a> KmsGuard<'a> { // we need to handle mirroring, after all outputs have been enabled let all_outputs = self.all_outputs(); for device in self.drm_devices.values_mut() { - for surface in device.surfaces.values_mut() { + for surface in device.inner.surfaces.values_mut() { let mirrored_output = if let OutputState::Mirroring(conn) = &surface.output.config().enabled { Some( diff --git a/src/backend/kms/surface/mod.rs b/src/backend/kms/surface/mod.rs index f997888f..3f11316f 100644 --- a/src/backend/kms/surface/mod.rs +++ b/src/backend/kms/surface/mod.rs @@ -296,6 +296,7 @@ impl Surface { .drm_devices .get_mut(&dev_node) .unwrap() + .inner .surfaces .get_mut(&crtc) .unwrap(); diff --git a/src/wayland/handlers/buffer.rs b/src/wayland/handlers/buffer.rs index 4087bd5f..83240822 100644 --- a/src/wayland/handlers/buffer.rs +++ b/src/wayland/handlers/buffer.rs @@ -1,9 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only -use crate::{ - backend::kms::MaybeLockedDevice, - state::{BackendData, State}, -}; +use crate::state::{BackendData, State}; use smithay::{ reexports::wayland_server::{protocol::wl_buffer::WlBuffer, Resource}, wayland::buffer::BufferHandler, @@ -14,8 +11,11 @@ impl BufferHandler for State { fn buffer_destroyed(&mut self, buffer: &WlBuffer) { if let BackendData::Kms(kms_state) = &mut self.backend { for device in kms_state.drm_devices.values_mut() { - if device.active_buffers.remove(&buffer.downgrade()) { - if !device.in_use(kms_state.primary_node.read().unwrap().as_ref()) { + if device.inner.active_buffers.remove(&buffer.downgrade()) { + if !device + .inner + .in_use(kms_state.primary_node.read().unwrap().as_ref()) + { if let Err(err) = kms_state.refresh_used_devices() { warn!(?err, "Failed to init devices."); }; diff --git a/src/wayland/handlers/dmabuf.rs b/src/wayland/handlers/dmabuf.rs index b0e81098..a1195d06 100644 --- a/src/wayland/handlers/dmabuf.rs +++ b/src/wayland/handlers/dmabuf.rs @@ -38,9 +38,9 @@ impl DmabufHandler for State { if let Some(device) = kms_state .drm_devices .values_mut() - .find(|dev| dev.render_node == node) + .find(|dev| dev.inner.render_node == node) { - device.active_buffers.insert(buffer.downgrade()); + device.inner.active_buffers.insert(buffer.downgrade()); } if let Err(err) = kms_state.refresh_used_devices() { warn!(?err, "Failed to init devices."); diff --git a/src/wayland/handlers/drm.rs b/src/wayland/handlers/drm.rs index 27fa5418..ffdd75e9 100644 --- a/src/wayland/handlers/drm.rs +++ b/src/wayland/handlers/drm.rs @@ -29,9 +29,9 @@ impl DrmHandler> for State { if let Some(device) = kms_state .drm_devices .values_mut() - .find(|device| device.render_node == node) + .find(|device| device.inner.render_node == node) { - device.active_buffers.insert(buffer.downgrade()); + device.inner.active_buffers.insert(buffer.downgrade()); } if let Err(err) = kms_state.refresh_used_devices() { diff --git a/src/wayland/handlers/drm_lease.rs b/src/wayland/handlers/drm_lease.rs index 66561623..60ae2b52 100644 --- a/src/wayland/handlers/drm_lease.rs +++ b/src/wayland/handlers/drm_lease.rs @@ -16,6 +16,7 @@ impl DrmLeaseHandler for State { .drm_devices .get_mut(&node) .unwrap() + .inner .leasing_global .as_mut() .unwrap() @@ -32,7 +33,7 @@ impl DrmLeaseHandler for State { .get_mut(&node) .ok_or(LeaseRejected::default())? .lock(); - let mut renderer = match kms.api.single_renderer(&backend.render_node) { + let mut renderer = match kms.api.single_renderer(&backend.inner.render_node) { Ok(renderer) => renderer, Err(err) => { tracing::warn!( @@ -55,6 +56,7 @@ impl DrmLeaseHandler for State { let mut builder = DrmLeaseBuilder::new(backend.drm.device()); for conn in request.connectors { if let Some((_, crtc)) = backend + .inner .leased_connectors .iter() .find(|(handle, _)| *handle == conn) @@ -101,7 +103,7 @@ impl DrmLeaseHandler for State { fn new_active_lease(&mut self, node: DrmNode, lease: DrmLease) { if let Some(backend) = self.backend.kms().drm_devices.get_mut(&node) { - backend.active_leases.push(lease); + backend.inner.active_leases.push(lease); } // else the backend is gone, drop the lease } @@ -110,10 +112,10 @@ impl DrmLeaseHandler for State { let kms = self.backend.kms(); if let Some(backend) = kms.drm_devices.get_mut(&node) { let mut backend = backend.lock(); - backend.active_leases.retain(|l| l.id() != lease); + backend.inner.active_leases.retain(|l| l.id() != lease); - if backend.active_leases.is_empty() { - let mut renderer = match kms.api.single_renderer(&backend.render_node) { + if backend.inner.active_leases.is_empty() { + let mut renderer = match kms.api.single_renderer(&backend.inner.render_node) { Ok(renderer) => renderer, Err(err) => { tracing::warn!(?err, "Failed to create renderer to enable direct scanout."); diff --git a/src/wayland/handlers/output_power.rs b/src/wayland/handlers/output_power.rs index 515c604e..df1138b4 100644 --- a/src/wayland/handlers/output_power.rs +++ b/src/wayland/handlers/output_power.rs @@ -31,7 +31,7 @@ fn kms_surfaces(state: &mut State) -> impl Iterator { kms_state .drm_devices .values_mut() - .flat_map(|device| device.surfaces.values_mut()), + .flat_map(|device| device.inner.surfaces.values_mut()), ) } else { None