Desktop: Only rerender the UI if it has changed (#3688)

* Only rerender ui if it has changed

* Don't immedeatly request new frame at the end of the event loop

* Request redraw after ui update

* Always request redraw after timeout

* Fix setting control flow in all cases

* Remove comment

---------

Co-authored-by: Timon <me@timon.zip>
This commit is contained in:
Dennis Kobert 2026-02-03 14:04:44 +01:00 committed by GitHub
parent 2e297777a0
commit f36d455d03
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 26 additions and 7 deletions

View File

@ -6,7 +6,7 @@ use std::thread;
use std::time::{Duration, Instant};
use winit::application::ApplicationHandler;
use winit::dpi::{PhysicalPosition, PhysicalSize};
use winit::event::{ButtonSource, ElementState, MouseButton, WindowEvent};
use winit::event::{ButtonSource, ElementState, MouseButton, StartCause, WindowEvent};
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
use winit::window::WindowId;
@ -260,6 +260,9 @@ impl App {
if let Some(render_state) = &mut self.render_state {
render_state.set_overlays_scene(scene);
}
if let Some(window) = &self.window {
window.request_redraw();
}
}
DesktopFrontendMessage::PersistenceWriteDocument { id, document } => {
self.persistent_data.write_document(id, document);
@ -632,10 +635,17 @@ impl ApplicationHandler for App {
}
}
fn new_events(&mut self, event_loop: &dyn ActiveEventLoop, cause: winit::event::StartCause) {
if let StartCause::ResumeTimeReached { .. } = cause
&& let Some(window) = &self.window
{
window.request_redraw();
}
}
fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) {
// Set a timeout in case we miss any cef schedule requests
let timeout = Instant::now() + Duration::from_millis(10);
let wait_until = timeout.min(self.cef_schedule.unwrap_or(timeout));
let mut wait_until = Instant::now() + Duration::from_millis(10);
if let Some(schedule) = self.cef_schedule
&& schedule < Instant::now()
{
@ -644,11 +654,9 @@ impl ApplicationHandler for App {
for _ in 0..CEF_MESSAGE_LOOP_MAX_ITERATIONS {
self.cef_context.work();
}
} else if let Some(cef_schedule) = self.cef_schedule {
wait_until = wait_until.min(cef_schedule);
}
if let Some(window) = &self.window.as_ref() {
window.request_redraw();
}
event_loop.set_control_flow(ControlFlow::WaitUntil(wait_until));
}
}

View File

@ -23,6 +23,7 @@ pub(crate) struct RenderState {
bind_group: Option<wgpu::BindGroup>,
#[derivative(Debug = "ignore")]
overlays_scene: Option<vello::Scene>,
surface_outdated: bool,
}
impl RenderState {
@ -186,6 +187,7 @@ impl RenderState {
ui_texture: None,
bind_group: None,
overlays_scene: None,
surface_outdated: true,
}
}
@ -196,6 +198,7 @@ impl RenderState {
self.desired_width = width;
self.desired_height = height;
self.surface_outdated = true;
if width > 0 && height > 0 && (self.config.width != width || self.config.height != height) {
self.config.width = width;
@ -215,14 +218,17 @@ impl RenderState {
}
pub(crate) fn set_viewport_scale(&mut self, scale: [f32; 2]) {
self.surface_outdated = true;
self.viewport_scale = scale;
}
pub(crate) fn set_viewport_offset(&mut self, offset: [f32; 2]) {
self.surface_outdated = true;
self.viewport_offset = offset;
}
pub(crate) fn set_overlays_scene(&mut self, scene: vello::Scene) {
self.surface_outdated = true;
self.overlays_scene = Some(scene);
}
@ -241,6 +247,9 @@ impl RenderState {
}
pub(crate) fn render(&mut self, window: &Window) -> Result<(), RenderError> {
if !self.surface_outdated {
return Ok(());
}
let ui_scale = if let Some(ui_texture) = &self.ui_texture
&& (self.desired_width != ui_texture.width() || self.desired_height != ui_texture.height())
{
@ -302,11 +311,13 @@ impl RenderState {
if ui_scale.is_some() {
return Err(RenderError::OutdatedUITextureError);
}
self.surface_outdated = false;
Ok(())
}
fn update_bindgroup(&mut self) {
self.surface_outdated = true;
let viewport_texture_view = self.viewport_texture.as_ref().unwrap_or(&self.transparent_texture).create_view(&wgpu::TextureViewDescriptor::default());
let overlays_texture_view = self
.overlays_texture