diff --git a/src/backend/drm/surface/atomic.rs b/src/backend/drm/surface/atomic.rs index 7844e3e..909ef81 100644 --- a/src/backend/drm/surface/atomic.rs +++ b/src/backend/drm/surface/atomic.rs @@ -56,7 +56,7 @@ impl AtomicDrmSurface { source, })?; - // If we have no current mode, we create a fake one, which will not match (and thus gets overriden on the commit below). + // If we have no current mode, we create a fake one, which will not match (and thus gets overridden on the commit below). // A better fix would probably be making mode an `Option`, but that would mean // we need to be sure, we require a mode to always be set without relying on the compiler. // So we cheat, because it works and is easier to handle later. @@ -509,9 +509,17 @@ impl AtomicDrmSurface { source, })?; + let current = self.state.read().unwrap(); + let pending = self.pending.read().unwrap(); + + let current_conns = current.connectors.clone(); + let pending_conns = pending.connectors.clone(); + let mut removed = current_conns.difference(&pending_conns); + let mut added = pending_conns.difference(¤t_conns); + let req = self.build_request( - &mut [].iter(), - &mut [].iter(), + &mut added, + &mut removed, self.plane, Some(fb), Some(*mode), @@ -519,11 +527,6 @@ impl AtomicDrmSurface { )?; let result = self.fd.atomic_commit(&[AtomicCommitFlags::AllowModeset, AtomicCommitFlags::TestOnly], req).is_ok(); - - if let Err(err) = self.fd.destroy_framebuffer(fb) { - debug!(self.logger, "Failed to destroy framebuffer({:?}): {}", fb, err); - } - Ok(result) } diff --git a/src/backend/drm/surface/legacy.rs b/src/backend/drm/surface/legacy.rs index f22f58f..9a31c5d 100644 --- a/src/backend/drm/surface/legacy.rs +++ b/src/backend/drm/surface/legacy.rs @@ -321,12 +321,18 @@ impl LegacyDrmSurface { return Err(Error::DeviceInactive); } + let pending = self.pending.read().unwrap(); + debug!(self.logger, "Setting screen for buffer *testing*"); Ok(self.fd.set_crtc( self.crtc, Some(fb), (0, 0), - &[], + &pending + .connectors + .iter() + .copied() + .collect::>(), Some(*mode), ).is_ok()) } diff --git a/src/backend/drm/surface/mod.rs b/src/backend/drm/surface/mod.rs index c3e3eeb..1032c76 100644 --- a/src/backend/drm/surface/mod.rs +++ b/src/backend/drm/surface/mod.rs @@ -185,64 +185,12 @@ impl DrmSurface { &self.formats } - pub fn test_buffer(&self, buffer: &B, bpp: u32, modifier: Option<[Modifier; 4]>, mode: &Mode, allow_screen_change: bool) -> Result, Error> - where - B: drm::buffer::Buffer + drm::buffer::PlanarBuffer - { - use std::sync::atomic::Ordering; - - let (active, logger) = match &*self.internal { - DrmSurfaceInternal::Atomic(surf) => (surf.active.load(Ordering::SeqCst), surf.logger.clone()), - DrmSurfaceInternal::Legacy(surf) => (surf.active.load(Ordering::SeqCst), surf.logger.clone()), - }; - - if !active { - return Err(Error::DeviceInactive); - } - - let fb = match - if let Some(mods) = modifier { - self.add_planar_framebuffer(buffer, unsafe { - std::mem::transmute::<&[Modifier; 4], &[Option; 4]>(&mods) - }, drm_ffi::DRM_MODE_FB_MODIFIERS) - } else { - self.add_planar_framebuffer(buffer, &[None, None, None, None], 0) - } - { - Ok(fb) => fb, - Err(_) => { - // We only support this as a fallback of last resort for ARGB8888 visuals, - // like xf86-video-modesetting does. - if drm::buffer::Buffer::format(buffer) != Fourcc::Argb8888 - || buffer.handles()[1].is_some() { - return Ok(false); - } - debug!(logger, "Failed to add framebuffer, trying legacy method"); - self.add_framebuffer(buffer, bpp, 32).map_err(|source| Error::Access { - errmsg: "Failed to add framebuffer", - dev: self.dev_path(), - source, - })? - } - }; - - let result = match &*self.internal { + pub fn test_buffer(&self, fb: framebuffer::Handle, mode: &Mode, allow_screen_change: bool) -> Result { + match &*self.internal { DrmSurfaceInternal::Atomic(surf) => surf.test_buffer(fb, mode), DrmSurfaceInternal::Legacy(surf) => if allow_screen_change { surf.test_buffer(fb, mode) } else { Ok(false) } // There is no test-commiting with the legacy interface - }; - - if !result.unwrap_or(false) { - if let Err(err) = self.destroy_framebuffer(fb) { - debug!(logger, "Failed to destroy framebuffer({:?}): {}", fb, err); - } } - - result.map(|x| if x { - Some(fb) - } else { - None - }) } } \ No newline at end of file