From e453d667e57f99798f79796707f12ad63bf75d5b Mon Sep 17 00:00:00 2001 From: Konkitoman Date: Tue, 26 Sep 2023 00:05:04 +0300 Subject: [PATCH] egui and eframe now uses more ViewportIdPair --- crates/eframe/src/native/epi_integration.rs | 34 ++++----- crates/eframe/src/native/run.rs | 63 +++++++---------- crates/egui/src/context.rs | 48 +++++-------- crates/egui/src/lib.rs | 26 +++---- crates/egui/src/viewport.rs | 13 ++++ crates/egui_demo_lib/benches/benchmark.rs | 77 +++++++-------------- crates/egui_demo_lib/src/lib.rs | 24 ++----- 7 files changed, 110 insertions(+), 175 deletions(-) diff --git a/crates/eframe/src/native/epi_integration.rs b/crates/eframe/src/native/epi_integration.rs index d928767a0..ef6bcac86 100644 --- a/crates/eframe/src/native/epi_integration.rs +++ b/crates/eframe/src/native/epi_integration.rs @@ -7,7 +7,9 @@ use winit::platform::macos::WindowBuilderExtMacOS as _; use raw_window_handle::{HasRawDisplayHandle as _, HasRawWindowHandle as _}; -use egui::{mutex::RwLock, NumExt as _, ViewportBuilder, ViewportId, ViewportRender}; +use egui::{ + mutex::RwLock, NumExt as _, ViewportBuilder, ViewportId, ViewportIdPair, ViewportRender, +}; #[cfg(feature = "accesskit")] use egui_winit::accesskit_winit; use egui_winit::{native_pixels_per_point, EventResponse, WindowSettings}; @@ -419,14 +421,7 @@ impl EpiIntegration { let saved_memory: egui::Memory = self.egui_ctx.memory(|mem| mem.clone()); self.egui_ctx .memory_mut(|mem| mem.set_everything_is_visible(true)); - let full_output = self.update( - app, - window, - egui_winit, - &None, - ViewportId::MAIN, - ViewportId::MAIN, - ); + let full_output = self.update(app, window, egui_winit, &None, ViewportIdPair::MAIN); self.pending_full_output.append(full_output); // Handle it next frame self.egui_ctx.memory_mut(|mem| *mem = saved_memory); // We don't want to remember that windows were huge. self.egui_ctx.clear_animations(); @@ -483,8 +478,7 @@ impl EpiIntegration { window: &winit::window::Window, egui_winit: &mut egui_winit::State, render: &Option>>, - viewport_id: egui::ViewportId, - parent_id: egui::ViewportId, + pair: ViewportIdPair, ) -> egui::FullOutput { let frame_start = std::time::Instant::now(); @@ -496,16 +490,14 @@ impl EpiIntegration { raw_input.time = Some(self.beginning.elapsed().as_secs_f64()); // Run user code: - let full_output = self - .egui_ctx - .run(raw_input, viewport_id, parent_id, |egui_ctx| { - crate::profile_scope!("App::update"); - if let Some(render) = render { - render(egui_ctx); - } else { - app.update(egui_ctx, &mut self.frame); - } - }); + let full_output = self.egui_ctx.run(raw_input, pair, |egui_ctx| { + crate::profile_scope!("App::update"); + if let Some(render) = render { + render(egui_ctx); + } else { + app.update(egui_ctx, &mut self.frame); + } + }); self.pending_full_output.append(full_output); let full_output = std::mem::take(&mut self.pending_full_output); diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index 4617b3f86..b9842242e 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -506,8 +506,7 @@ mod glow_integration { struct Window { gl_surface: Option>, window: Option>>, - viewport_id: ViewportId, - parent_id: ViewportId, + pair: ViewportIdPair, render: Option>>, egui_winit: Option, } @@ -672,10 +671,9 @@ mod glow_integration { Arc::new(RwLock::new(Window { gl_surface: None, window: window.map(|w| Arc::new(RwLock::new(w))), - viewport_id: ViewportId::MAIN, egui_winit: None, render: None, - parent_id: ViewportId::MAIN, + pair: ViewportIdPair::MAIN })), ); @@ -728,7 +726,7 @@ mod glow_integration { win: &Arc>, event_loop: &EventLoopWindowTarget, ) -> Result<()> { - let builder = &self.builders[&win.read().viewport_id]; + let builder = &self.builders[&win.read().pair.this]; let mut win = win.write(); // make sure we have a window or create one. let window = win.window.take().unwrap_or_else(|| { @@ -796,7 +794,7 @@ mod glow_integration { win.gl_surface = Some(gl_surface); self.current_gl_context = Some(current_gl_context); - self.viewports_maps.insert(window.id(), win.viewport_id); + self.viewports_maps.insert(window.id(), win.pair.this); } win.window = Some(window); Ok(()) @@ -1065,21 +1063,21 @@ mod glow_integration { // ## Sync Rendering integration.egui_ctx.set_render_sync_callback( - move |egui_ctx, mut viewport_builder, ViewportIdPair{ this: viewport_id, parent: parent_id }, render| { + move |egui_ctx, mut viewport_builder, pair, render| { - let has_window = c_glutin.read().viewports.get(&viewport_id).is_some(); + let has_window = c_glutin.read().viewports.get(&pair).is_some(); if !has_window{ if viewport_builder.icon.is_none(){ - viewport_builder.icon = c_glutin.read().builders.get(&parent_id).and_then(|b|b.icon.clone()); + viewport_builder.icon = c_glutin.read().builders.get(&pair.parent).and_then(|b|b.icon.clone()); } { let mut glutin = c_glutin.write(); - glutin.viewports.entry(viewport_id).or_insert(Arc::new(RwLock::new(Window{ gl_surface: None, window: None, viewport_id, parent_id, render: None, egui_winit: None }))); - glutin.builders.entry(viewport_id).or_insert(viewport_builder); + glutin.viewports.entry(pair.this).or_insert(Arc::new(RwLock::new(Window{ gl_surface: None, window: None, pair, render: None, egui_winit: None }))); + glutin.builders.entry(pair.this).or_insert(viewport_builder); } - let win = c_glutin.read().viewports[&viewport_id].clone(); + let win = c_glutin.read().viewports[&pair].clone(); let event_loop; #[allow(unsafe_code)] unsafe{ @@ -1089,7 +1087,7 @@ mod glow_integration { } 'try_render: { - let window = c_glutin.read().viewports.get(&viewport_id).cloned(); + let window = c_glutin.read().viewports.get(&pair).cloned(); if let Some(window) = window { let output; { @@ -1101,8 +1099,7 @@ mod glow_integration { input.time = Some(c_time.elapsed().as_secs_f64()); output = egui_ctx.run( input, - viewport_id, - parent_id, + pair, |ctx| { render(ctx); }, @@ -1131,7 +1128,7 @@ mod glow_integration { .unwrap() .is_current(glutin.current_gl_context.as_ref().unwrap()) { - let builder = &&glutin.builders[&window.viewport_id]; + let builder = &&glutin.builders[&window.pair]; log::error!("egui::create_viewport_sync with title: `{}` is not created in main thread, try to use wgpu!", builder.title); } @@ -1207,7 +1204,7 @@ mod glow_integration { w.window = None; w.gl_surface = None; w.render = render.clone(); - w.parent_id = *id; + w.pair.parent = *id; } if let Some(w) = w.window.clone() { process_viewport_commands(commands, *id, None, &w); @@ -1222,18 +1219,14 @@ mod glow_integration { for ViewportOutput { mut builder, - pair: - ViewportIdPair { - this: id, - parent: parent_id, - }, + pair, render, } in viewports { let default_icon = glutin_ctx .read() .builders - .get(&parent_id) + .get(&pair.parent) .and_then(|b| b.icon.clone()); if builder.icon.is_none() { @@ -1242,19 +1235,18 @@ mod glow_integration { { let mut glutin = glutin_ctx.write(); glutin.viewports.insert( - id, + pair.this, Arc::new(RwLock::new(Window { gl_surface: None, window: None, - viewport_id: id, egui_winit: None, render, - parent_id, + pair })), ); - glutin.builders.insert(id, builder); + glutin.builders.insert(pair.this, builder); } - active_viewports_ids.push(id); + active_viewports_ids.push(pair.this); } let mut gl_window = glutin_ctx.write(); @@ -1369,7 +1361,7 @@ mod glow_integration { { let win = &glutin.read().viewports[&viewport_id].clone(); if win.read().render.is_none() && viewport_id != ViewportId::MAIN { - if let Some(win) = glutin.read().viewports.get(&win.read().parent_id) { + if let Some(win) = glutin.read().viewports.get(&win.read().pair.parent) { if let Some(w) = win.read().window.as_ref() { return vec![EventResult::RepaintNow(w.read().id())]; } @@ -1423,8 +1415,7 @@ mod glow_integration { &win.window.as_ref().unwrap().read(), win.egui_winit.as_mut().unwrap(), &win.render.clone(), - win.viewport_id, - win.parent_id, + win.pair, ); integration.write().handle_platform_output( @@ -1707,7 +1698,7 @@ mod glow_integration { if let Some(win) = window.read().window.as_ref() { let win = win.read(); if win.id() == *window_id { - Some(window.read().viewport_id) + Some(window.read().pair.this) } else { None } @@ -1746,7 +1737,7 @@ mod glow_integration { running.app.write().as_mut(), event, viewport.egui_winit.as_mut().unwrap(), - viewport.viewport_id, + viewport.pair.this, ); } } @@ -2164,8 +2155,7 @@ mod wgpu_integration { input.time = Some(c_time.elapsed().as_secs_f64()); output = egui_ctx.run( input, - viewport_id, - parent_id, + ViewportIdPair::new(viewport_id, parent_id), |ctx| { render(ctx); }, @@ -2334,8 +2324,7 @@ mod wgpu_integration { &window.read(), state.write().as_mut().unwrap(), &render.clone(), - viewport_id, - parent_id, + ViewportIdPair::new(viewport_id, parent_id) ); integration.write().handle_platform_output( diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index eeac23e6a..73c4ed465 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -227,12 +227,7 @@ struct ContextImpl { } impl ContextImpl { - fn begin_frame_mut( - &mut self, - mut new_raw_input: RawInput, - viewport_id: ViewportId, - parent_viewport_id: ViewportId, - ) { + fn begin_frame_mut(&mut self, mut new_raw_input: RawInput, pair: ViewportIdPair) { // This is used to pause the last frame if !self.frame_stack.is_empty() { let viewport_id = self.viewport_id(); @@ -248,10 +243,7 @@ impl ContextImpl { ); } - self.frame_stack.push(ViewportIdPair { - this: viewport_id, - parent: parent_viewport_id, - }); + self.frame_stack.push(pair); self.output.entry(self.viewport_id()).or_default(); self.repaint.start_frame(self.viewport_id()); @@ -259,15 +251,15 @@ impl ContextImpl { if self .memory .new_pixels_per_viewport - .get(&viewport_id) + .get(&pair) .map_or(true, |pixels| *pixels != new_pixels_per_point) { new_raw_input.pixels_per_point = Some(new_pixels_per_point); self.memory .new_pixels_per_viewport - .insert(viewport_id, new_pixels_per_point); + .insert(pair.this, new_pixels_per_point); - let input = self.input.entry(viewport_id).or_default(); + let input = self.input.entry(pair.this).or_default(); // This is a bit hacky, but is required to avoid jitter: let ratio = input.pixels_per_point / new_pixels_per_point; let mut rect = input.screen_rect; @@ -279,31 +271,31 @@ impl ContextImpl { self.layer_rects_prev_frame = self .layer_rects_prev_viewports - .remove(&viewport_id) + .remove(&pair) .unwrap_or_default(); self.memory.begin_frame( - self.input.get(&viewport_id).unwrap_or(&Default::default()), + self.input.get(&pair).unwrap_or(&Default::default()), &new_raw_input, - viewport_id, + pair.this, ); let input = self .input - .remove(&viewport_id) + .remove(&pair) .unwrap_or_default() .begin_frame(new_raw_input, self.repaint.requested_repaint_last_frame); - self.input.insert(viewport_id, input); + self.input.insert(pair.this, input); self.frame_state - .entry(viewport_id) + .entry(pair.this) .or_default() - .begin_frame(&self.input[&viewport_id]); + .begin_frame(&self.input[&pair]); self.update_fonts_mut(); // Ensure we register the background area so panels and background ui can catch clicks: - let input = &self.input[&viewport_id]; + let input = &self.input[&pair]; let screen_rect = input.screen_rect(); self.memory.areas.set_state( LayerId::background(), @@ -524,13 +516,12 @@ impl Context { pub fn run( &self, new_input: RawInput, - viewport_id: ViewportId, - parent_viewport_id: ViewportId, + pair: ViewportIdPair, run_ui: impl FnOnce(&Context), ) -> FullOutput { crate::profile_function!(); - self.begin_frame(new_input, viewport_id, parent_viewport_id); + self.begin_frame(new_input, pair); run_ui(self); self.end_frame() } @@ -552,15 +543,10 @@ impl Context { /// let full_output = ctx.end_frame(); /// // handle full_output /// ``` - pub fn begin_frame( - &self, - new_input: RawInput, - viewport_id: ViewportId, - parent_viewport_id: ViewportId, - ) { + pub fn begin_frame(&self, new_input: RawInput, pair: ViewportIdPair) { crate::profile_function!(); - self.write(|ctx| ctx.begin_frame_mut(new_input, viewport_id, parent_viewport_id)); + self.write(|ctx| ctx.begin_frame_mut(new_input, pair)); } /// Create a new Context and specify if is desktop diff --git a/crates/egui/src/lib.rs b/crates/egui/src/lib.rs index 669fd6efc..c99f75d8f 100644 --- a/crates/egui/src/lib.rs +++ b/crates/egui/src/lib.rs @@ -620,30 +620,20 @@ pub enum WidgetType { pub fn __run_test_ctx(mut run_ui: impl FnMut(&Context)) { let ctx = Context::default(); ctx.set_fonts(FontDefinitions::empty()); // prevent fonts from being loaded (save CPU time) - let _ = ctx.run( - Default::default(), - ViewportId::MAIN, - ViewportId::MAIN, - |ctx| { - run_ui(ctx); - }, - ); + let _ = ctx.run(Default::default(), ViewportIdPair::MAIN, |ctx| { + run_ui(ctx); + }); } /// For use in tests; especially doctests. pub fn __run_test_ui(mut add_contents: impl FnMut(&mut Ui)) { let ctx = Context::default(); ctx.set_fonts(FontDefinitions::empty()); // prevent fonts from being loaded (save CPU time) - let _ = ctx.run( - Default::default(), - ViewportId::MAIN, - ViewportId::MAIN, - |ctx| { - crate::CentralPanel::default().show(ctx, |ui| { - add_contents(ui); - }); - }, - ); + let _ = ctx.run(Default::default(), ViewportIdPair::MAIN, |ctx| { + crate::CentralPanel::default().show(ctx, |ui| { + add_contents(ui); + }); + }); } #[cfg(feature = "accesskit")] diff --git a/crates/egui/src/viewport.rs b/crates/egui/src/viewport.rs index 3c6456fb4..a00f3bbea 100644 --- a/crates/egui/src/viewport.rs +++ b/crates/egui/src/viewport.rs @@ -21,6 +21,7 @@ impl ViewportId { pub const MAIN: Self = Self(0); } +/// This will deref to `ViewportIdPair::this` #[derive(Default, Debug, Hash, Clone, Copy, PartialEq, Eq)] pub struct ViewportIdPair { pub this: ViewportId, @@ -33,6 +34,18 @@ impl ViewportIdPair { this: ViewportId::MAIN, parent: ViewportId::MAIN, }; + + pub fn new(this: ViewportId, parent: ViewportId) -> Self { + Self { this, parent } + } +} + +impl std::ops::Deref for ViewportIdPair { + type Target = ViewportId; + + fn deref(&self) -> &Self::Target { + &self.this + } } /// This is used to render an async viewport diff --git a/crates/egui_demo_lib/benches/benchmark.rs b/crates/egui_demo_lib/benches/benchmark.rs index ddacda0ed..f8ed63dbf 100644 --- a/crates/egui_demo_lib/benches/benchmark.rs +++ b/crates/egui_demo_lib/benches/benchmark.rs @@ -1,6 +1,6 @@ use criterion::{criterion_group, criterion_main, Criterion}; -use egui::{epaint::TextShape, ViewportId}; +use egui::{epaint::TextShape, ViewportIdPair}; use egui_demo_lib::LOREM_IPSUM_LONG; pub fn criterion_benchmark(c: &mut Criterion) { @@ -13,39 +13,24 @@ pub fn criterion_benchmark(c: &mut Criterion) { // The most end-to-end benchmark. c.bench_function("demo_with_tessellate__realistic", |b| { b.iter(|| { - let full_output = ctx.run( - RawInput::default(), - ViewportId::MAIN, - ViewportId::MAIN, - |ctx| { - demo_windows.ui(ctx); - }, - ); + let full_output = ctx.run(RawInput::default(), ViewportIdPair::MAIN, |ctx| { + demo_windows.ui(ctx); + }); ctx.tessellate(full_output.shapes) }); }); c.bench_function("demo_no_tessellate", |b| { b.iter(|| { - ctx.run( - RawInput::default(), - ViewportId::MAIN, - ViewportId::MAIN, - |ctx| { - demo_windows.ui(ctx); - }, - ) + ctx.run(RawInput::default(), ViewportIdPair::MAIN, |ctx| { + demo_windows.ui(ctx); + }) }); }); - let full_output = ctx.run( - RawInput::default(), - ViewportId::MAIN, - ViewportId::MAIN, - |ctx| { - demo_windows.ui(ctx); - }, - ); + let full_output = ctx.run(RawInput::default(), ViewportIdPair::MAIN, |ctx| { + demo_windows.ui(ctx); + }); c.bench_function("demo_only_tessellate", |b| { b.iter(|| ctx.tessellate(full_output.shapes.clone())); }); @@ -57,44 +42,34 @@ pub fn criterion_benchmark(c: &mut Criterion) { let mut demo_windows = egui_demo_lib::DemoWindows::default(); c.bench_function("demo_full_no_tessellate", |b| { b.iter(|| { - ctx.run( - RawInput::default(), - ViewportId::MAIN, - ViewportId::MAIN, - |ctx| { - demo_windows.ui(ctx); - }, - ) + ctx.run(RawInput::default(), ViewportIdPair::MAIN, |ctx| { + demo_windows.ui(ctx); + }) }); }); } { let ctx = egui::Context::default(); - let _ = ctx.run( - RawInput::default(), - ViewportId::MAIN, - ViewportId::MAIN, - |ctx| { - egui::CentralPanel::default().show(ctx, |ui| { - c.bench_function("label &str", |b| { - b.iter(|| { - ui.label("the quick brown fox jumps over the lazy dog"); - }); - }); - c.bench_function("label format!", |b| { - b.iter(|| { - ui.label("the quick brown fox jumps over the lazy dog".to_owned()); - }); + let _ = ctx.run(RawInput::default(), ViewportIdPair::MAIN, |ctx| { + egui::CentralPanel::default().show(ctx, |ui| { + c.bench_function("label &str", |b| { + b.iter(|| { + ui.label("the quick brown fox jumps over the lazy dog"); }); }); - }, - ); + c.bench_function("label format!", |b| { + b.iter(|| { + ui.label("the quick brown fox jumps over the lazy dog".to_owned()); + }); + }); + }); + }); } { let ctx = egui::Context::default(); - ctx.begin_frame(RawInput::default(), ViewportId::MAIN, ViewportId::MAIN); + ctx.begin_frame(RawInput::default(), ViewportIdPair::MAIN); egui::CentralPanel::default().show(&ctx, |ui| { c.bench_function("Painter::rect", |b| { diff --git a/crates/egui_demo_lib/src/lib.rs b/crates/egui_demo_lib/src/lib.rs index 0031eada5..578fd92b9 100644 --- a/crates/egui_demo_lib/src/lib.rs +++ b/crates/egui_demo_lib/src/lib.rs @@ -19,7 +19,7 @@ pub mod easy_mark; pub use color_test::ColorTest; pub use demo::DemoWindows; #[cfg(test)] -use egui::ViewportId; +use egui::ViewportIdPair; /// View some Rust code with syntax highlighting and selection. pub(crate) fn rust_view_ui(ui: &mut egui::Ui, code: &str) { @@ -76,14 +76,9 @@ fn test_egui_e2e() { const NUM_FRAMES: usize = 5; for _ in 0..NUM_FRAMES { - let full_output = ctx.run( - raw_input.clone(), - ViewportId::MAIN, - ViewportId::MAIN, - |ctx| { - demo_windows.ui(ctx); - }, - ); + let full_output = ctx.run(raw_input.clone(), ViewportIdPair::MAIN, |ctx| { + demo_windows.ui(ctx); + }); let clipped_primitives = ctx.tessellate(full_output.shapes); assert!(!clipped_primitives.is_empty()); } @@ -100,14 +95,9 @@ fn test_egui_zero_window_size() { const NUM_FRAMES: usize = 5; for _ in 0..NUM_FRAMES { - let full_output = ctx.run( - raw_input.clone(), - ViewportId::MAIN, - ViewportId::MAIN, - |ctx| { - demo_windows.ui(ctx); - }, - ); + let full_output = ctx.run(raw_input.clone(), ViewportIdPair::MAIN, |ctx| { + demo_windows.ui(ctx); + }); let clipped_primitives = ctx.tessellate(full_output.shapes); assert!( clipped_primitives.is_empty(),