mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-10 17:18:25 -10:00
Wait instead of polling when a frame does not reach the screen
A window the compositor stops showing gets no RedrawRequested, and the event loop kept polling and asking for another redraw every pass, pinning a core with nothing to draw. Once a frame fails to reach the swap chain the loop now waits for the next event.
This commit is contained in:
1 parent
e12185820a
commit
d89499c0ae
1 file changed
+18
-1
@@ -2843,6 +2843,9 @@ struct Game<'a> {
|
||||
/// The world was saved for the application ending (`save_for_exit`).
|
||||
saved_for_exit: bool,
|
||||
pending_save: Option<saving::ClosingSave>,
|
||||
/// The last world frame reached the swap chain. A window the compositor
|
||||
/// stops showing gets no frames, and the event loop must not spin on it.
|
||||
frame_drawn: bool,
|
||||
/// The world list's icon in progress (`GameRenderer.tryTakeScreenshotIfNeeded`):
|
||||
/// `None` without a local world, or once the save has its icon.png.
|
||||
world_icon: Option<WorldIcon>,
|
||||
@@ -15705,6 +15708,8 @@ impl Game<'_> {
|
||||
}
|
||||
None => Err("renderer".into()),
|
||||
};
|
||||
// A frame the surface refused (occluded, lost, timed out) is `Ok(false)`.
|
||||
self.frame_drawn = matches!(result, Ok(true));
|
||||
// Restore storage even when rendering fails (for example, a lost surface).
|
||||
self.entity_vertices = entities;
|
||||
*self.entity_spans.get_mut() = entity_spans;
|
||||
@@ -18085,7 +18090,18 @@ impl Game<'_> {
|
||||
self.handle_window_event(event_loop, WindowId::dummy(), WindowEvent::RedrawRequested);
|
||||
return;
|
||||
}
|
||||
event_loop.set_control_flow(ControlFlow::Poll);
|
||||
// A window the compositor hides gets no `RedrawRequested` at all, so
|
||||
// polling would spin the loop with nothing to draw and pin a core.
|
||||
// Once a requested frame fails to reach the swap chain, wait for the
|
||||
// next event instead; a resize or occlusion change wakes the loop and
|
||||
// the frame that follows sets the pace back to polling.
|
||||
if self.frame_drawn {
|
||||
event_loop.set_control_flow(ControlFlow::Poll);
|
||||
} else {
|
||||
event_loop.set_control_flow(ControlFlow::WaitUntil(
|
||||
Instant::now() + Duration::from_millis(16),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// clouds.png as filled cells (`CloudRenderer.prepare`: alpha 10 or more).
|
||||
@@ -18556,6 +18572,7 @@ impl<'a> Game<'a> {
|
||||
text_selection: Default::default(),
|
||||
saved_for_exit: false,
|
||||
pending_save: None,
|
||||
frame_drawn: true,
|
||||
world_icon: None,
|
||||
forced_hit: None,
|
||||
tick_hit: None,
|
||||
|
||||
Reference in new issue
Block a user