1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-01 06:10:06 -04:00
* now every viewport has his own frame_nr

eframe:
* some refactoring
* now on Windows spinner will make the async viewport refresh, this problem was only for async viewport in Windows

* problem found there are two redraw systems, one was broken now is fixed, the one that was broken on Linux X11 was not needed, but for Windows both are needed!
1: The egui repaint_callback system
2: The egui repaint_after from FullOutput
This commit is contained in:
Konkitoman
2023-10-18 18:47:16 +03:00
parent 701d31a887
commit b1e7fafe70
2 changed files with 48 additions and 54 deletions

View File

@@ -42,7 +42,7 @@ pub enum UserEvent {
/// A repaint is requested. /// A repaint is requested.
RequestRepaint { RequestRepaint {
/// What to repaint. /// What to repaint.
id: ViewportId, viewport_id: ViewportId,
/// When to repaint. /// When to repaint.
when: Instant, when: Instant,
@@ -91,7 +91,7 @@ enum EventResult {
trait WinitApp { trait WinitApp {
/// The current frame number, as reported by egui. /// The current frame number, as reported by egui.
fn frame_nr(&self) -> u64; fn frame_nr(&self, viewport_id: ViewportId) -> u64;
fn is_focused(&self, window_id: winit::window::WindowId) -> bool; fn is_focused(&self, window_id: winit::window::WindowId) -> bool;
@@ -187,16 +187,6 @@ fn run_and_return(
return; return;
} }
// Platform-dependent event handlers to workaround a winit bug
// See: https://github.com/rust-windowing/winit/issues/987
// See: https://github.com/rust-windowing/winit/issues/1619
// #[cfg(target_os = "windows")]
// winit::event::Event::RedrawEventsCleared => {
// windows_next_repaint_times.clear();
// winit_app.run_ui_and_paint(None)
// vec![EventResult::Wait]
// }
// #[cfg(not(target_os = "windows"))]
winit::event::Event::RedrawRequested(window_id) => { winit::event::Event::RedrawRequested(window_id) => {
windows_next_repaint_times.remove(window_id); windows_next_repaint_times.remove(window_id);
winit_app.run_ui_and_paint(*window_id) winit_app.run_ui_and_paint(*window_id)
@@ -205,11 +195,11 @@ fn run_and_return(
winit::event::Event::UserEvent(UserEvent::RequestRepaint { winit::event::Event::UserEvent(UserEvent::RequestRepaint {
when, when,
frame_nr, frame_nr,
id: window_id, viewport_id,
}) => { }) => {
if winit_app.frame_nr() == *frame_nr { if winit_app.frame_nr(*viewport_id) == *frame_nr + 1 {
log::trace!("UserEvent::RequestRepaint scheduling repaint at {when:?}"); log::trace!("UserEvent::RequestRepaint scheduling repaint at {when:?}");
if let Some(window_id) = winit_app.get_window_winit_id(*window_id) { if let Some(window_id) = winit_app.get_window_winit_id(*viewport_id) {
vec![EventResult::RepaintAt(window_id, *when)] vec![EventResult::RepaintAt(window_id, *when)]
} else { } else {
vec![EventResult::Wait] vec![EventResult::Wait]
@@ -287,13 +277,11 @@ fn run_and_return(
for (window_id, repaint_time) in &windows_next_repaint_times.clone() { for (window_id, repaint_time) in &windows_next_repaint_times.clone() {
if *repaint_time <= Instant::now() { if *repaint_time <= Instant::now() {
if let Some(window) = winit_app.window(*window_id) { if let Some(window) = winit_app.window(*window_id) {
log::trace!("request_redraw");
window.read().request_redraw(); window.read().request_redraw();
windows_next_repaint_times.remove(window_id);
control_flow.set_poll();
} else {
windows_next_repaint_times.remove(window_id);
control_flow.set_wait();
} }
windows_next_repaint_times.remove(window_id);
control_flow.set_poll();
} else { } else {
next_repaint_time = next_repaint_time =
Some(next_repaint_time.map_or(*repaint_time, |last| last.min(*repaint_time))); Some(next_repaint_time.map_or(*repaint_time, |last| last.min(*repaint_time)));
@@ -344,15 +332,7 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +
vec![EventResult::Exit] vec![EventResult::Exit]
} }
// Platform-dependent event handlers to workaround a winit bug winit::event::Event::RedrawRequested(window_id) => {
// See: https://github.com/rust-windowing/winit/issues/987
// See: https://github.com/rust-windowing/winit/issues/1619
winit::event::Event::RedrawEventsCleared if cfg!(target_os = "windows") => {
// windows_next_repaint_times.clear();
// winit_app.run_ui_and_paint(None)
vec![]
}
winit::event::Event::RedrawRequested(window_id) if !cfg!(target_os = "windows") => {
windows_next_repaint_times.remove(&window_id); windows_next_repaint_times.remove(&window_id);
winit_app.run_ui_and_paint(window_id) winit_app.run_ui_and_paint(window_id)
} }
@@ -360,10 +340,10 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +
winit::event::Event::UserEvent(UserEvent::RequestRepaint { winit::event::Event::UserEvent(UserEvent::RequestRepaint {
when, when,
frame_nr, frame_nr,
id: window_id, viewport_id,
}) => { }) => {
if winit_app.frame_nr() == frame_nr { if winit_app.frame_nr(viewport_id) == frame_nr + 1 {
if let Some(window_id) = winit_app.get_window_winit_id(window_id) { if let Some(window_id) = winit_app.get_window_winit_id(viewport_id) {
vec![EventResult::RepaintAt(window_id, when)] vec![EventResult::RepaintAt(window_id, when)]
} else { } else {
vec![EventResult::Wait] vec![EventResult::Wait]
@@ -425,8 +405,8 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +
if let Some(window) = winit_app.window(*window_id) { if let Some(window) = winit_app.window(*window_id) {
log::trace!("request_redraw"); log::trace!("request_redraw");
window.read().request_redraw(); window.read().request_redraw();
windows_next_repaint_times.remove(window_id);
} }
windows_next_repaint_times.remove(window_id);
control_flow.set_poll(); control_flow.set_poll();
} else { } else {
next_repaint_time = next_repaint_time =
@@ -1030,7 +1010,7 @@ mod glow_integration {
event_loop_proxy event_loop_proxy
.lock() .lock()
.send_event(UserEvent::RequestRepaint { .send_event(UserEvent::RequestRepaint {
id: info.viewport_id, viewport_id: info.viewport_id,
when, when,
frame_nr, frame_nr,
}) })
@@ -1303,11 +1283,10 @@ mod glow_integration {
} }
impl WinitApp for GlowWinitApp { impl WinitApp for GlowWinitApp {
fn frame_nr(&self) -> u64 { fn frame_nr(&self, viewport_id: ViewportId) -> u64 {
self.running self.running.read().as_ref().map_or(0, |r| {
.read() r.integration.read().egui_ctx.frame_nr_for(viewport_id)
.as_ref() })
.map_or(0, |r| r.integration.read().egui_ctx.frame_nr())
} }
fn is_focused(&self, window_id: winit::window::WindowId) -> bool { fn is_focused(&self, window_id: winit::window::WindowId) -> bool {
@@ -2073,7 +2052,7 @@ mod wgpu_integration {
.send_event(UserEvent::RequestRepaint { .send_event(UserEvent::RequestRepaint {
when, when,
frame_nr, frame_nr,
id: info.viewport_id, viewport_id: info.viewport_id,
}) })
.ok(); .ok();
}); });
@@ -2249,10 +2228,10 @@ mod wgpu_integration {
} }
impl WinitApp for WgpuWinitApp { impl WinitApp for WgpuWinitApp {
fn frame_nr(&self) -> u64 { fn frame_nr(&self, viewport_id: ViewportId) -> u64 {
self.running self.running.as_ref().map_or(0, |r| {
.as_ref() r.integration.read().egui_ctx.frame_nr_for(viewport_id)
.map_or(0, |r| r.integration.read().egui_ctx.frame_nr()) })
} }
fn is_focused(&self, window_id: winit::window::WindowId) -> bool { fn is_focused(&self, window_id: winit::window::WindowId) -> bool {

View File

@@ -58,7 +58,7 @@ struct Repaint {
/// The current frame number. /// The current frame number.
/// ///
/// Incremented at the end of each frame. /// Incremented at the end of each frame.
frame_nr: u64, viewports_frame_nr: HashMap<ViewportId, u64>,
/// The duration backend will poll for new events, before forcing another egui update /// The duration backend will poll for new events, before forcing another egui update
/// even if there's no new events. /// even if there's no new events.
@@ -83,7 +83,7 @@ impl Default for Repaint {
let mut repaint_requests = HashMap::default(); let mut repaint_requests = HashMap::default();
repaint_requests.insert(ViewportId::MAIN, 1); repaint_requests.insert(ViewportId::MAIN, 1);
Self { Self {
frame_nr: 0, viewports_frame_nr: HashMap::default(),
repaint_after, repaint_after,
repaint_requests, repaint_requests,
request_repaint_callback: None, request_repaint_callback: None,
@@ -118,7 +118,7 @@ impl Repaint {
if let Some(callback) = &self.request_repaint_callback { if let Some(callback) = &self.request_repaint_callback {
let info = RequestRepaintInfo { let info = RequestRepaintInfo {
after, after,
current_frame_nr: self.frame_nr, current_frame_nr: *self.viewports_frame_nr.entry(viewport_id).or_default(),
viewport_id, viewport_id,
}; };
(callback)(info); (callback)(info);
@@ -160,9 +160,11 @@ impl Repaint {
self.repaint_after.insert(viewport_id, repaint_after); self.repaint_after.insert(viewport_id, repaint_after);
self.requested_repaint_last_frame = repaint_after.is_zero(); self.requested_repaint_last_frame = repaint_after.is_zero();
self.frame_nr += 1; *self.viewports_frame_nr.entry(viewport_id).or_default() += 1;
self.repaint_after.retain(|id, _| viewports.contains(id)); self.repaint_after.retain(|id, _| viewports.contains(id));
self.viewports_frame_nr
.retain(|id, _| viewports.contains(id));
self.repaint_requests self.repaint_requests
.retain(|id, repaints| viewports.contains(id) && *repaints != 0); .retain(|id, repaints| viewports.contains(id) && *repaints != 0);
@@ -1150,13 +1152,28 @@ impl Context {
} }
} }
/// The current frame number. /// The current frame number for the current viewport.
/// ///
/// Starts at zero, and is incremented at the end of [`Self::run`] or by [`Self::end_frame`]. /// Starts at zero, and is incremented at the end of [`Self::run`] or by [`Self::end_frame`].
/// ///
/// Between calls to [`Self::run`], this is the frame number of the coming frame. /// Between calls to [`Self::run`], this is the frame number of the coming frame.
pub fn frame_nr(&self) -> u64 { pub fn frame_nr(&self) -> u64 {
self.read(|ctx| ctx.repaint.frame_nr) self.frame_nr_for(self.viewport_id())
}
/// The current frame number.
///
/// Starts at zero, and is incremented at the end of [`Self::run`] or by [`Self::end_frame`].
///
/// Between calls to [`Self::run`], this is the frame number of the coming frame.
pub fn frame_nr_for(&self, id: ViewportId) -> u64 {
self.read(|ctx| {
ctx.repaint
.viewports_frame_nr
.get(&id)
.copied()
.unwrap_or_default()
})
} }
/// Call this if there is need to repaint the UI, i.e. if you are showing an animation. /// Call this if there is need to repaint the UI, i.e. if you are showing an animation.
@@ -1648,10 +1665,8 @@ impl Context {
}); });
} }
let repaint_after = self.write(|ctx| { let repaint_after =
ctx.repaint self.write(|ctx| ctx.repaint.end_frame(viewport_id, &avalibile_viewports));
.end_frame(ctx.viewport_id(), &avalibile_viewports)
});
FullOutput { FullOutput {
platform_output, platform_output,