1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-02 06:40:06 -04:00

Not will only redraw what is needed and the cpu will not be at 100% all the time

This commit is contained in:
Konkitoman
2023-07-19 11:16:51 +03:00
parent cd48e2b1ad
commit b66cf96343

View File

@@ -79,7 +79,7 @@ trait WinitApp {
fn save_and_destroy(&mut self); fn save_and_destroy(&mut self);
fn run_ui_and_paint(&mut self, window_id: Option<winit::window::WindowId>) -> EventResult; fn run_ui_and_paint(&mut self, window_id: Option<winit::window::WindowId>) -> Vec<EventResult>;
fn on_event( fn on_event(
&mut self, &mut self,
@@ -135,7 +135,7 @@ fn run_and_return(
let mut returned_result = Ok(()); let mut returned_result = Ok(());
event_loop.run_return(|event, event_loop, control_flow| { event_loop.run_return(|event, event_loop, control_flow| {
let event_result = match &event { let events = match &event {
winit::event::Event::LoopDestroyed => { winit::event::Event::LoopDestroyed => {
// On Mac, Cmd-Q we get here and then `run_return` doesn't return (despite its name), // On Mac, Cmd-Q we get here and then `run_return` doesn't return (despite its name),
// so we need to save state now: // so we need to save state now:
@@ -165,13 +165,13 @@ fn run_and_return(
if winit_app.frame_nr() == *frame_nr { if winit_app.frame_nr() == *frame_nr {
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_id(*window_id) { if let Some(window_id) = winit_app.get_window_id(*window_id) {
EventResult::RepaintAt(window_id, *when) vec![EventResult::RepaintAt(window_id, *when)]
} else { } else {
EventResult::Wait vec![EventResult::Wait]
} }
} else { } else {
log::trace!("Got outdated UserEvent::RequestRepaint"); log::trace!("Got outdated UserEvent::RequestRepaint");
EventResult::Wait // old request - we've already repainted vec![EventResult::Wait] // old request - we've already repainted
} }
} }
@@ -179,7 +179,7 @@ fn run_and_return(
.. ..
}) => { }) => {
log::trace!("Woke up to check next_repaint_time"); log::trace!("Woke up to check next_repaint_time");
EventResult::Wait vec![EventResult::Wait]
} }
winit::event::Event::WindowEvent { window_id, .. } winit::event::Event::WindowEvent { window_id, .. }
@@ -187,51 +187,55 @@ fn run_and_return(
{ {
// This can happen if we close a window, and then reopen a new one, // This can happen if we close a window, and then reopen a new one,
// or if we have multiple windows open. // or if we have multiple windows open.
EventResult::Wait vec![EventResult::Wait]
} }
event => match winit_app.on_event(event_loop, event) { event => match winit_app.on_event(event_loop, event) {
Ok(event_result) => event_result, Ok(event_result) => vec![event_result],
Err(err) => { Err(err) => {
log::error!("Exiting because of error: {err:?} on event {event:?}"); log::error!("Exiting because of error: {err:?} on event {event:?}");
returned_result = Err(err); returned_result = Err(err);
EventResult::Exit vec![EventResult::Exit]
} }
}, },
}; };
match event_result { for event in events {
EventResult::Wait => {} match event {
EventResult::RepaintNow(window_id) => { EventResult::Wait => {
log::trace!("Repaint caused by winit::Event: {:?}", event); control_flow.set_wait();
if cfg!(windows) { }
// Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280 EventResult::RepaintNow(window_id) => {
windows_next_repaint_times.remove(&window_id); log::trace!("Repaint caused by winit::Event: {:?}", event);
if cfg!(windows) {
// Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280
windows_next_repaint_times.remove(&window_id);
winit_app.run_ui_and_paint(Some(window_id)); winit_app.run_ui_and_paint(Some(window_id));
} else { } else {
// Fix for https://github.com/emilk/egui/issues/2425 // Fix for https://github.com/emilk/egui/issues/2425
windows_next_repaint_times.insert(window_id, Instant::now());
}
}
EventResult::RepaintNext(window_id) => {
log::trace!("Repaint caused by winit::Event: {:?}", event);
windows_next_repaint_times.insert(window_id, Instant::now()); windows_next_repaint_times.insert(window_id, Instant::now());
} }
} EventResult::RepaintAt(window_id, repaint_time) => {
EventResult::RepaintNext(window_id) => { windows_next_repaint_times.insert(
log::trace!("Repaint caused by winit::Event: {:?}", event); window_id,
windows_next_repaint_times.insert(window_id, Instant::now()); windows_next_repaint_times
} .get(&window_id)
EventResult::RepaintAt(window_id, repaint_time) => { .map(|last| (*last).min(repaint_time))
windows_next_repaint_times.insert( .unwrap_or(repaint_time),
window_id, );
windows_next_repaint_times }
.get(&window_id) EventResult::Exit => {
.map(|last| (*last).min(repaint_time)) log::debug!("Asking to exit event loop…");
.unwrap_or(repaint_time), winit_app.save_and_destroy();
); *control_flow = ControlFlow::Exit;
} return;
EventResult::Exit => { }
log::debug!("Asking to exit event loop…");
winit_app.save_and_destroy();
*control_flow = ControlFlow::Exit;
return;
} }
} }
@@ -287,10 +291,10 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +
let mut windows_next_repaint_times = HashMap::default(); let mut windows_next_repaint_times = HashMap::default();
event_loop.run(move |event, event_loop, control_flow| { event_loop.run(move |event, event_loop, control_flow| {
let event_result = match event { let events = match event {
winit::event::Event::LoopDestroyed => { winit::event::Event::LoopDestroyed => {
log::debug!("Received Event::LoopDestroyed"); log::debug!("Received Event::LoopDestroyed");
EventResult::Exit vec![EventResult::Exit]
} }
// Platform-dependent event handlers to workaround a winit bug // Platform-dependent event handlers to workaround a winit bug
@@ -312,57 +316,59 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +
}) => { }) => {
if winit_app.frame_nr() == frame_nr { if winit_app.frame_nr() == frame_nr {
if let Some(window_id) = winit_app.get_window_id(window_id) { if let Some(window_id) = winit_app.get_window_id(window_id) {
EventResult::RepaintAt(window_id, when) vec![EventResult::RepaintAt(window_id, when)]
} else { } else {
EventResult::Wait vec![EventResult::Wait]
} }
} else { } else {
EventResult::Wait // old request - we've already repainted vec![EventResult::Wait] // old request - we've already repainted
} }
} }
winit::event::Event::NewEvents(winit::event::StartCause::ResumeTimeReached { winit::event::Event::NewEvents(winit::event::StartCause::ResumeTimeReached {
.. ..
}) => EventResult::Wait, // We just woke up to check next_repaint_time }) => vec![EventResult::Wait], // We just woke up to check next_repaint_time
event => match winit_app.on_event(event_loop, &event) { event => match winit_app.on_event(event_loop, &event) {
Ok(event_result) => event_result, Ok(event_result) => vec![event_result],
Err(err) => { Err(err) => {
panic!("eframe encountered a fatal error: {err}"); panic!("eframe encountered a fatal error: {err}");
} }
}, },
}; };
match event_result { for event in events {
EventResult::Wait => {} match event {
EventResult::RepaintNow(window_id) => { EventResult::Wait => {}
if cfg!(windows) { EventResult::RepaintNow(window_id) => {
// Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280 if cfg!(windows) {
windows_next_repaint_times.remove(&window_id); // Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280
windows_next_repaint_times.remove(&window_id);
winit_app.run_ui_and_paint(Some(window_id)); winit_app.run_ui_and_paint(Some(window_id));
} else { } else {
// Fix for https://github.com/emilk/egui/issues/2425 // Fix for https://github.com/emilk/egui/issues/2425
windows_next_repaint_times.insert(window_id, Instant::now());
}
}
EventResult::RepaintNext(window_id) => {
windows_next_repaint_times.insert(window_id, Instant::now()); windows_next_repaint_times.insert(window_id, Instant::now());
} }
} EventResult::RepaintAt(window_id, repaint_time) => {
EventResult::RepaintNext(window_id) => { windows_next_repaint_times.insert(
windows_next_repaint_times.insert(window_id, Instant::now()); window_id,
} windows_next_repaint_times
EventResult::RepaintAt(window_id, repaint_time) => { .get(&window_id)
windows_next_repaint_times.insert( .map(|last| (*last).min(repaint_time))
window_id, .unwrap_or(repaint_time),
windows_next_repaint_times );
.get(&window_id) }
.map(|last| (*last).min(repaint_time)) EventResult::Exit => {
.unwrap_or(repaint_time), log::debug!("Quitting - saving app state…");
); winit_app.save_and_destroy();
} #[allow(clippy::exit)]
EventResult::Exit => { std::process::exit(0);
log::debug!("Quitting - saving app state…"); }
winit_app.save_and_destroy();
#[allow(clippy::exit)]
std::process::exit(0);
} }
} }
@@ -944,7 +950,10 @@ mod glow_integration {
} }
} }
fn run_ui_and_paint(&mut self, window_id: Option<winit::window::WindowId>) -> EventResult { fn run_ui_and_paint(
&mut self,
window_id: Option<winit::window::WindowId>,
) -> Vec<EventResult> {
if let Some(running) = &mut self.running { if let Some(running) = &mut self.running {
let mut windows_indexes = vec![]; let mut windows_indexes = vec![];
if let Some(window_id) = window_id { if let Some(window_id) = window_id {
@@ -1075,14 +1084,7 @@ mod glow_integration {
control_flow = if integration.should_close() { control_flow = if integration.should_close() {
EventResult::Exit EventResult::Exit
} else if repaint_after.is_zero() { } else if repaint_after.is_zero() {
let mut id = None; EventResult::RepaintNext(window.id())
for window in gl_window.windows.iter() {
if window.window_id == 0 {
id = window.window.as_ref().map(|w| w.id());
break;
}
}
EventResult::RepaintNext(id.unwrap())
} else if let Some(repaint_after_instant) = } else if let Some(repaint_after_instant) =
std::time::Instant::now().checked_add(repaint_after) std::time::Instant::now().checked_add(repaint_after)
{ {
@@ -1092,14 +1094,7 @@ mod glow_integration {
// winit to use `WaitUntil(MAX_INSTANT)` explicitly. they can roll their own // winit to use `WaitUntil(MAX_INSTANT)` explicitly. they can roll their own
// egui backend impl i guess. // egui backend impl i guess.
let mut id = None; EventResult::RepaintAt(window.id(), repaint_after_instant)
for window in gl_window.windows.iter() {
if window.window_id == 0 {
id = window.window.as_ref().map(|w| w.id());
break;
}
}
EventResult::RepaintAt(id.unwrap(), repaint_after_instant)
} else { } else {
EventResult::Wait EventResult::Wait
}; };
@@ -1157,29 +1152,12 @@ mod glow_integration {
// Re do this is a really way to implement this // Re do this is a really way to implement this
// We need to change the output of this function to `Vec<EventResult>` // We need to change the output of this function to `Vec<EventResult>`
let mut ret = EventResult::Wait; windows_indexes
for event in windows_indexes
.into_iter() .into_iter()
.map(|window_index| inner(window_index)) .map(|window_index| inner(window_index))
{ .collect()
match event {
EventResult::Wait => {}
EventResult::RepaintNow(w) => ret = event,
EventResult::RepaintNext(w) => ret = event,
EventResult::RepaintAt(_, time) => match ret {
EventResult::RepaintAt(_, last_time) => {
if last_time > time {
ret = event;
}
}
_ => {}
},
EventResult::Exit => ret = event,
}
}
ret
} else { } else {
EventResult::Wait vec![EventResult::Wait]
} }
} }
@@ -1560,7 +1538,10 @@ mod wgpu_integration {
} }
} }
fn run_ui_and_paint(&mut self, window_id: Option<winit::window::WindowId>) -> EventResult { fn run_ui_and_paint(
&mut self,
window_id: Option<winit::window::WindowId>,
) -> Vec<EventResult> {
// !!! WARNING !!! // !!! WARNING !!!
// Nothing is implemented for WGPU // Nothing is implemented for WGPU