DPMS with wlr-output-power-management-unstable-v1 protocol

This commit is contained in:
Ian Douglas Scott 2024-08-16 20:49:59 -07:00 committed by Victoria Brekenfeld
parent 65a54706f5
commit ea27ec5e28
10 changed files with 390 additions and 5 deletions

View file

@ -43,6 +43,7 @@ mod drm_helpers;
pub mod render;
mod socket;
mod surface;
pub(crate) use surface::Surface;
use device::*;
pub use surface::Timings;

View file

@ -102,9 +102,9 @@ static NVIDIA_LOGO: &'static [u8] = include_bytes!("../../../../resources/icons/
#[derive(Debug)]
pub struct Surface {
pub(super) connector: connector::Handle,
pub(crate) connector: connector::Handle,
pub(super) crtc: crtc::Handle,
pub(super) output: Output,
pub(crate) output: Output,
known_nodes: HashSet<DrmNode>,
active: Arc<AtomicBool>,
@ -114,6 +114,8 @@ pub struct Surface {
loop_handle: LoopHandle<'static, State>,
thread_command: Sender<ThreadCommand>,
thread_token: RegistrationToken,
dpms: bool,
}
pub struct SurfaceThreadState {
@ -238,6 +240,7 @@ pub enum ThreadCommand {
ScheduleRender,
SetMode(Mode, SyncSender<Result<()>>),
End,
DpmsOff,
}
#[derive(Debug)]
@ -350,6 +353,7 @@ impl Surface {
loop_handle: evlh.clone(),
thread_command: tx,
thread_token,
dpms: true,
})
}
@ -380,7 +384,9 @@ impl Surface {
}
pub fn schedule_render(&self) {
let _ = self.thread_command.send(ThreadCommand::ScheduleRender);
if self.dpms {
let _ = self.thread_command.send(ThreadCommand::ScheduleRender);
}
}
pub fn set_mirroring(&mut self, output: Option<Output>) {
@ -431,6 +437,21 @@ impl Surface {
rx.recv().context("Surface thread died")?
}
pub fn get_dpms(&mut self) -> bool {
self.dpms
}
pub fn set_dpms(&mut self, on: bool) {
if self.dpms != on {
self.dpms = on;
if on {
self.schedule_render();
} else {
let _ = self.thread_command.send(ThreadCommand::DpmsOff);
}
}
}
}
impl Drop for Surface {
@ -540,6 +561,30 @@ fn surface_thread(
let _ = result.send(Err(anyhow::anyhow!("Set mode with inactive surface")));
}
}
Event::Msg(ThreadCommand::DpmsOff) => {
if let Some(compositor) = state.compositor.as_mut() {
if let Err(err) = compositor.clear() {
error!("Failed to set DPMS off: {:?}", err);
}
match std::mem::replace(&mut state.state, QueueState::Idle) {
QueueState::Idle => {}
QueueState::Queued(token)
| QueueState::WaitingForEstimatedVBlank(token) => {
state.loop_handle.remove(token);
}
QueueState::WaitingForVBlank { .. } => {
state.timings.discard_current_frame()
}
QueueState::WaitingForEstimatedVBlankAndQueued {
estimated_vblank,
queued_render,
} => {
state.loop_handle.remove(estimated_vblank);
state.loop_handle.remove(queued_render);
}
};
}
}
Event::Closed | Event::Msg(ThreadCommand::End) => {
signal.stop();
signal.wakeup();