Commit 8a73f3b68818
tarball1 file changed+37-30
@@ -618,19 +618,10 @@ fn schedule(state: &mut State, crtc: crtc::Handle) {
618618
draw(state, crtc, now);619619
return;620620
}621
- let wait = Timer::from_duration(Duration::from_nanos(CURSOR_FRAME_NS - since_flip));622
- let token = drm.handle.insert_source(wait, move |_, _, state| {623
- if let Some(s) = state624
- .backend625
- .drm_mut()626
- .and_then(|d| d.surfaces.get_mut(&crtc))627
- {628
- s.scheduled = None;629
- }621
+ let wait = Duration::from_nanos(CURSOR_FRAME_NS - since_flip);622
+ arm(&drm.handle, surface, crtc, wait, move |state| {630623
draw(state, crtc, now_ns());631
- TimeoutAction::Drop632624
});633
- surface.scheduled = token.ok();634625
return;635626
}636627
let Some((vblank, start)) = surface.next_deadline(now) else {@@ -638,19 +629,44 @@ fn schedule(state: &mut State, crtc: crtc::Handle) {
638629
return;639630
};640631
surface.target_ns = Some(vblank);641
- let wait = Timer::from_duration(Duration::from_nanos(start.saturating_sub(now)));642
- let token = drm.handle.insert_source(wait, move |_, _, state| {643
- let target = state.backend.drm_mut().and_then(|d| {644
- let s = d.surfaces.get_mut(&crtc)?;645
- s.scheduled = None;646
- s.target_ns647
- });632
+ let wait = Duration::from_nanos(start.saturating_sub(now));633
+ arm(&drm.handle, surface, crtc, wait, move |state| {634
+ let target = state635
+ .backend636
+ .drm()637
+ .and_then(|d| d.surfaces.get(&crtc)?.target_ns);648638
if let Some(target) = target {649639
draw(state, crtc, target);650640
}641
+ });642
+}643
+644
+/// Runs `fire` once after `after`, tracked in `surface.scheduled` until then.645
+fn arm(646
+ handle: &LoopHandle<'static, State>,647
+ surface: &mut Surface,648
+ crtc: crtc::Handle,649
+ after: Duration,650
+ mut fire: impl FnMut(&mut State) + 'static,651
+) {652
+ let token = handle.insert_source(Timer::from_duration(after), move |_, _, state| {653
+ if let Some(s) = state654
+ .backend655
+ .drm_mut()656
+ .and_then(|d| d.surfaces.get_mut(&crtc))657
+ {658
+ s.scheduled = None;659
+ }660
+ fire(state);651661
TimeoutAction::Drop652662
});653
- surface.scheduled = token.ok();663
+ match token {664
+ Ok(token) => surface.scheduled = Some(token),665
+ Err(e) => tracing::warn!(666
+ output = surface.output.name(),667
+ "could not arm a render timer: {e}"668
+ ),669
+ }654670
}655671
656672
/// An animation whose frame had nothing to show, like one hidden behind a@@ -670,19 +686,10 @@ fn draw(state: &mut State, crtc: crtc::Handle, target: u64) {
670686
if surface.scheduled.is_some() {671687
return;672688
}673
- let wait = Timer::from_duration(Duration::from_nanos(surface.refresh_ns.max(1_000_000)));674
- let token = drm.handle.insert_source(wait, move |_, _, state| {675
- if let Some(s) = state676
- .backend677
- .drm_mut()678
- .and_then(|d| d.surfaces.get_mut(&crtc))679
- {680
- s.scheduled = None;681
- }689
+ let wait = Duration::from_nanos(surface.refresh_ns.max(1_000_000));690
+ arm(&drm.handle, surface, crtc, wait, move |state| {682691
schedule(state, crtc);683
- TimeoutAction::Drop684692
});685
- surface.scheduled = token.ok();686693
}687694
688695
/// Renders every output that has something new and no frame in flight.