From 1b1be3cd6c778d056016bc171d6b9f7f44648b2a Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 15 Nov 2023 11:14:13 +0100 Subject: [PATCH] Pass out `pixels_per_point` in output for use in tesselation --- crates/eframe/src/native/run.rs | 14 ++++---------- crates/egui/src/context.rs | 4 +++- crates/egui/src/data/output.rs | 7 +++++++ crates/egui/src/lib.rs | 2 +- crates/egui_demo_lib/benches/benchmark.rs | 5 ++--- crates/egui_demo_lib/src/lib.rs | 6 ++---- crates/egui_glow/src/winit.rs | 20 ++++++++++++++------ 7 files changed, 33 insertions(+), 25 deletions(-) diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index 14584c72029..7933a2b2e71 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -562,6 +562,7 @@ mod glow_integration { platform_output, textures_delta, shapes, + pixels_per_point, viewports: viewports_out, viewport_commands, } = full_output; @@ -580,10 +581,6 @@ mod glow_integration { integration.post_update(app.as_mut(), window); integration.handle_platform_output(window, viewport_id, platform_output, egui_winit); - let pixels_per_point = integration - .egui_ctx - .input_for(viewport_id, |i| i.pixels_per_point()); - let clipped_primitives = integration.egui_ctx.tessellate(shapes, pixels_per_point); *current_gl_context = Some( @@ -1581,7 +1578,7 @@ mod glow_integration { let screen_size_in_pixels: [u32; 2] = window.inner_size().into(); let pixels_per_point = egui_ctx.input_for(ids.this, |i| i.pixels_per_point()); - let clipped_primitives = egui_ctx.tessellate(output.shapes, pixels_per_point); + let clipped_primitives = egui_ctx.tessellate(output.shapes, output.pixels_per_point); let mut painter = painter.borrow_mut(); @@ -2181,7 +2178,7 @@ mod wgpu_integration { } let pixels_per_point = egui_ctx.input_for(ids.this, |i| i.pixels_per_point()); - let clipped_primitives = egui_ctx.tessellate(output.shapes, pixels_per_point); + let clipped_primitives = egui_ctx.tessellate(output.shapes, output.pixels_per_point); painter.paint_and_update_textures( ids.this, pixels_per_point, @@ -2504,6 +2501,7 @@ mod wgpu_integration { platform_output, textures_delta, shapes, + pixels_per_point, viewports: out_viewports, viewport_commands, } = full_output; @@ -2511,10 +2509,6 @@ mod wgpu_integration { integration.handle_platform_output(window, viewport_id, platform_output, egui_winit); { - let pixels_per_point = integration - .egui_ctx - .input_for(viewport_id, |i| i.pixels_per_point()); - let clipped_primitives = integration.egui_ctx.tessellate(shapes, pixels_per_point); let screenshot_requested = &mut integration.frame.output.screenshot_requested; diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index de2c3ffa1bb..f963d952e5e 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -429,7 +429,7 @@ impl ContextImpl { /// }); /// }); /// handle_platform_output(full_output.platform_output); -/// let clipped_primitives = ctx.tessellate(full_output.shapes); // create triangles to paint +/// let clipped_primitives = ctx.tessellate(full_output.shapes, full_output.pixels_per_point); /// paint(full_output.textures_delta, clipped_primitives); /// } /// ``` @@ -1486,6 +1486,7 @@ impl ContextImpl { fn end_frame(&mut self) -> FullOutput { let ended_viewport_id = self.viewport_id(); let viewport = self.viewports.entry(ended_viewport_id).or_default(); + let pixels_per_point = viewport.input.pixels_per_point; if viewport.input.wants_repaint() { self.repaint.requested_repaint(&ended_viewport_id); @@ -1607,6 +1608,7 @@ impl ContextImpl { platform_output, textures_delta, shapes, + pixels_per_point, viewports: out_viewports, // We should not process viewport commands when we are a sync viewport, because that will cause a deadlock for egui backend viewport_commands: if is_last { diff --git a/crates/egui/src/data/output.rs b/crates/egui/src/data/output.rs index 2707680f7e8..ed8d7b4b5a1 100644 --- a/crates/egui/src/data/output.rs +++ b/crates/egui/src/data/output.rs @@ -21,6 +21,11 @@ pub struct FullOutput { /// You can use [`crate::Context::tessellate`] to turn this into triangles. pub shapes: Vec, + /// The number of physical pixels per logical ui point, for the viewport that was updated. + /// + /// You can pass this to [`Context::tesselate`] together with [`Self::shapes`]. + pub pixels_per_point: f32, + /// All the active viewports, excluding the root. pub viewports: Vec, @@ -35,6 +40,7 @@ impl FullOutput { platform_output, textures_delta, shapes, + pixels_per_point, mut viewports, mut viewport_commands, } = newer; @@ -42,6 +48,7 @@ impl FullOutput { self.platform_output.append(platform_output); self.textures_delta.append(textures_delta); self.shapes = shapes; // Only paint the latest + self.pixels_per_point = pixels_per_point; // Use latest self.viewports.append(&mut viewports); self.viewport_commands.append(&mut viewport_commands); } diff --git a/crates/egui/src/lib.rs b/crates/egui/src/lib.rs index 7aab28bbf73..773667b44ba 100644 --- a/crates/egui/src/lib.rs +++ b/crates/egui/src/lib.rs @@ -134,7 +134,7 @@ //! }); //! }); //! handle_platform_output(full_output.platform_output); -//! let clipped_primitives = ctx.tessellate(full_output.shapes); // create triangles to paint +//! let clipped_primitives = ctx.tessellate(full_output.shapes, full_output.pixels_per_point); //! paint(full_output.textures_delta, clipped_primitives); //! } //! ``` diff --git a/crates/egui_demo_lib/benches/benchmark.rs b/crates/egui_demo_lib/benches/benchmark.rs index 1cecf303883..1baaefd7e01 100644 --- a/crates/egui_demo_lib/benches/benchmark.rs +++ b/crates/egui_demo_lib/benches/benchmark.rs @@ -9,7 +9,6 @@ pub fn criterion_benchmark(c: &mut Criterion) { { let ctx = egui::Context::default(); let mut demo_windows = egui_demo_lib::DemoWindows::default(); - let pixels_per_point = 1.0; // The most end-to-end benchmark. c.bench_function("demo_with_tessellate__realistic", |b| { @@ -17,7 +16,7 @@ pub fn criterion_benchmark(c: &mut Criterion) { let full_output = ctx.run(RawInput::default(), |ctx| { demo_windows.ui(ctx); }); - ctx.tessellate(full_output.shapes, pixels_per_point) + ctx.tessellate(full_output.shapes, full_output.pixels_per_point) }); }); @@ -33,7 +32,7 @@ pub fn criterion_benchmark(c: &mut Criterion) { demo_windows.ui(ctx); }); c.bench_function("demo_only_tessellate", |b| { - b.iter(|| ctx.tessellate(full_output.shapes.clone(), pixels_per_point)); + b.iter(|| ctx.tessellate(full_output.shapes.clone(), full_output.pixels_per_point)); }); } diff --git a/crates/egui_demo_lib/src/lib.rs b/crates/egui_demo_lib/src/lib.rs index 4d0fe58d068..893413f353d 100644 --- a/crates/egui_demo_lib/src/lib.rs +++ b/crates/egui_demo_lib/src/lib.rs @@ -71,14 +71,13 @@ fn test_egui_e2e() { let mut demo_windows = crate::DemoWindows::default(); let ctx = egui::Context::default(); let raw_input = egui::RawInput::default(); - let pixels_per_point = 1.0; const NUM_FRAMES: usize = 5; for _ in 0..NUM_FRAMES { let full_output = ctx.run(raw_input.clone(), |ctx| { demo_windows.ui(ctx); }); - let clipped_primitives = ctx.tessellate(full_output.shapes, pixels_per_point); + let clipped_primitives = ctx.tessellate(full_output.shapes, full_output.pixels_per_point); assert!(!clipped_primitives.is_empty()); } } @@ -91,14 +90,13 @@ fn test_egui_zero_window_size() { screen_rect: Some(egui::Rect::from_min_max(egui::Pos2::ZERO, egui::Pos2::ZERO)), ..Default::default() }; - let pixels_per_point = 1.0; const NUM_FRAMES: usize = 5; for _ in 0..NUM_FRAMES { let full_output = ctx.run(raw_input.clone(), |ctx| { demo_windows.ui(ctx); }); - let clipped_primitives = ctx.tessellate(full_output.shapes, pixels_per_point); + let clipped_primitives = ctx.tessellate(full_output.shapes, full_output.pixels_per_point); assert!( clipped_primitives.is_empty(), "There should be nothing to show, has at least one primitive with clip_rect: {:?}", diff --git a/crates/egui_glow/src/winit.rs b/crates/egui_glow/src/winit.rs index e591efdc8a3..6684b6cb8b4 100644 --- a/crates/egui_glow/src/winit.rs +++ b/crates/egui_glow/src/winit.rs @@ -10,7 +10,9 @@ pub struct EguiGlow { pub egui_winit: egui_winit::State, pub painter: crate::Painter, + // output from the last update: shapes: Vec, + pixels_per_point: f32, textures_delta: egui::TexturesDelta, } @@ -28,15 +30,19 @@ impl EguiGlow { }) .unwrap(); + let egui_winit = egui_winit::State::new( + event_loop, + native_pixels_per_point, + Some(painter.max_texture_side()), + ); + let pixels_per_point = egui_winit.pixels_per_point(); + Self { egui_ctx: Default::default(), - egui_winit: egui_winit::State::new( - event_loop, - native_pixels_per_point, - Some(painter.max_texture_side()), - ), + egui_winit, painter, shapes: Default::default(), + pixels_per_point, textures_delta: Default::default(), } } @@ -55,6 +61,7 @@ impl EguiGlow { platform_output, textures_delta, shapes, + pixels_per_point, viewports, viewport_commands, } = self.egui_ctx.run(raw_input, run_ui); @@ -76,6 +83,7 @@ impl EguiGlow { ); self.shapes = shapes; + self.pixels_per_point = pixels_per_point; self.textures_delta.append(textures_delta); } @@ -88,7 +96,7 @@ impl EguiGlow { self.painter.set_texture(id, &image_delta); } - let pixels_per_point = self.egui_ctx.pixels_per_point(); + let pixels_per_point = self.pixels_per_point; let clipped_primitives = self.egui_ctx.tessellate(shapes, pixels_per_point); let dimensions: [u32; 2] = window.inner_size().into(); self.painter