Skip to content

Commit

Permalink
Add a clear method to DrmSurface and DrmCompositor
Browse files Browse the repository at this point in the history
This sets DPMS state to off. Submitting a new frame will re-enable the
output.
  • Loading branch information
ids1024 committed Oct 17, 2024
1 parent c54e079 commit 5ffdb6f
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 1 deletion.
18 changes: 18 additions & 0 deletions src/backend/drm/compositor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4216,6 +4216,24 @@ where
Err(Some(RenderingReason::ScanoutFailed))
}
}

/// Clear the surface, setting DPMS state to off, disable all planes,
/// and clear the pending frame.
///
/// Calling [`queue_frame`][Self::queue_frame] will re-enable.
pub fn clear(&mut self) -> Result<(), DrmError> {
self.surface.clear()?;

self.current_frame
.planes
.iter_mut()
.for_each(|(_, state)| *state = Default::default());
self.pending_frame = None;
self.queued_frame = None;
self.next_frame = None;

Ok(())
}
}

#[inline]
Expand Down
4 changes: 4 additions & 0 deletions src/backend/drm/surface/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,10 @@ impl AtomicDrmSurface {
pub(crate) fn device_fd(&self) -> &DrmDeviceFd {
self.fd.device_fd()
}

pub fn clear(&self) -> Result<(), Error> {
self.clear_state()
}
}

struct TestBuffer {
Expand Down
28 changes: 27 additions & 1 deletion src/backend/drm/surface/legacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use drm::control::{connector, crtc, encoder, framebuffer, Device as ControlDevic
use std::collections::HashSet;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc, RwLock,
Arc, Mutex, RwLock,
};

use crate::backend::drm::error::AccessError;
Expand Down Expand Up @@ -86,6 +86,7 @@ pub struct LegacyDrmSurface {
crtc: crtc::Handle,
state: RwLock<State>,
pending: RwLock<State>,
dpms: Mutex<bool>,
pub(super) span: tracing::Span,
}

Expand Down Expand Up @@ -114,6 +115,7 @@ impl LegacyDrmSurface {
crtc,
state: RwLock::new(state),
pending: RwLock::new(pending),
dpms: Mutex::new(true),
span,
};

Expand Down Expand Up @@ -233,6 +235,13 @@ impl LegacyDrmSurface {

let mut current = self.state.write().unwrap();
let pending = self.pending.read().unwrap();
let mut dpms = self.dpms.lock().unwrap();

if !*dpms {
let connectors = current.connectors.intersection(&pending.connectors);
set_connector_state(&*self.fd, connectors.copied(), true)?;
*dpms = true;
}

{
let removed = current.connectors.difference(&pending.connectors);
Expand Down Expand Up @@ -331,6 +340,13 @@ impl LegacyDrmSurface {
return Err(Error::DeviceInactive);
}

let current = self.state.read().unwrap();
let mut dpms = self.dpms.lock().unwrap();
if !*dpms {
set_connector_state(&*self.fd, current.connectors.iter().copied(), true)?;
*dpms = true;
}

ControlDevice::page_flip(
&*self.fd,
self.crtc,
Expand Down Expand Up @@ -452,6 +468,16 @@ impl LegacyDrmSurface {
pub(crate) fn device_fd(&self) -> &DrmDeviceFd {
self.fd.device_fd()
}

pub fn clear(&self) -> Result<(), Error> {
let current = self.state.read().unwrap();
let mut dpms = self.dpms.lock().unwrap();
if *dpms {
set_connector_state(&*self.fd, current.connectors.iter().copied(), false)?;
*dpms = false;
}
Ok(())
}
}

impl Drop for LegacyDrmSurface {
Expand Down
11 changes: 11 additions & 0 deletions src/backend/drm/surface/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,17 @@ impl DrmSurface {
DrmSurfaceInternal::Legacy(surf) => &surf.span,
}
}

/// Clear the surface, setting DPMS state to off and disabling all planes.
///
/// The surface will be re-enabled on the next [`page_flip`][Self::page_flip] or
/// [`commit`][Self::commit].
pub fn clear(&self) -> Result<(), Error> {
match &*self.internal {
DrmSurfaceInternal::Atomic(surf) => surf.clear(),
DrmSurfaceInternal::Legacy(surf) => surf.clear(),
}
}
}

fn ensure_legacy_planes<'a>(
Expand Down

0 comments on commit 5ffdb6f

Please sign in to comment.