1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-27 15:13:12 -04:00

"Final" touch-ups on wgpu integration

This commit is contained in:
Emil Ernerfeldt
2023-11-14 07:58:04 +01:00
parent 274cdea620
commit aad7ed23d2
5 changed files with 171 additions and 207 deletions

View File

@@ -1,5 +1,9 @@
//! Note that this file contains two similar paths - one for [`glow`], one for [`wgpu`].
//! When making changes to one you often also want to apply it to the other.
//!
//! This is also very complex code, and not very pretty.
//! There is a bunch of improvements we could do,
//! like removing a bunch of `unwraps`.
use std::{cell::RefCell, rc::Rc, sync::Arc, time::Instant};
@@ -96,8 +100,6 @@ trait WinitApp {
fn window_id_from_viewport_id(&self, id: ViewportId) -> Option<WindowId>;
fn viewport_id_from_window_id(&self, id: &WindowId) -> Option<ViewportId>;
fn save_and_destroy(&mut self);
fn run_ui_and_paint(&mut self, window_id: WindowId) -> EventResult;
@@ -492,12 +494,7 @@ mod glow_integration {
window_id: WindowId,
focused_viewport: Option<ViewportId>,
) -> EventResult {
let Some(viewport_id) = self
.glutin
.borrow()
.viewport_maps
.get(&window_id)
.copied()
let Some(viewport_id) = self.glutin.borrow().viewport_from_window.get(&window_id).copied()
else {
return EventResult::Wait;
};
@@ -511,10 +508,10 @@ mod glow_integration {
let viewport = &glutin.viewports[&viewport_id];
let is_immediate = viewport.viewport_ui_cb.is_none();
if is_immediate && viewport_id != ViewportId::ROOT {
// This will only happen if this is an immediate viewport.
// That means that the viewport cannot be rendered by itself and needs his parent to be rendered.
if let Some(parent_viewport) = glutin.viewports.get(&viewport.ids.parent) {
if let Some(window) = parent_viewport.window.as_ref() {
// This will only happen if this is an immediate viewport.
// That means that the viewport cannot be rendered by itself and needs his parent to be rendered.
return EventResult::RepaintNext(window.id());
}
}
@@ -553,6 +550,9 @@ mod glow_integration {
..
} = self;
let mut glutin = glutin.borrow_mut();
let mut painter = painter.borrow_mut();
let egui::FullOutput {
platform_output,
textures_delta,
@@ -561,7 +561,6 @@ mod glow_integration {
viewport_commands,
} = full_output;
let mut glutin = glutin.borrow_mut();
let GlutinWindowContext {
viewports,
current_gl_context,
@@ -569,41 +568,36 @@ mod glow_integration {
} = &mut *glutin;
let viewport = viewports.get_mut(&viewport_id).unwrap();
let window = viewport.window.as_ref().unwrap();
let gl_surface = viewport.gl_surface.as_ref().unwrap();
let egui_winit = viewport.egui_winit.as_mut().unwrap();
integration.post_update(app.as_mut(), window);
integration.handle_platform_output(
window,
viewport_id,
platform_output,
viewport.egui_winit.as_mut().unwrap(),
);
let clipped_primitives = integration.egui_ctx.tessellate(shapes);
if let Some(gl_surface) = &viewport.gl_surface {
*current_gl_context = Some(
current_gl_context
.take()
.unwrap()
.make_not_current()
.unwrap()
.make_current(gl_surface)
.unwrap(),
);
}
let screen_size_in_pixels: [u32; 2] = window.inner_size().into();
painter.borrow().clear(
screen_size_in_pixels,
app.clear_color(&integration.egui_ctx.style().visuals),
);
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());
painter.borrow_mut().paint_and_update_textures(
let clipped_primitives = integration.egui_ctx.tessellate(shapes, pixels_per_point);
*current_gl_context = Some(
current_gl_context
.take()
.unwrap()
.make_not_current()
.unwrap()
.make_current(gl_surface)
.unwrap(),
);
let screen_size_in_pixels: [u32; 2] = window.inner_size().into();
painter.clear(
screen_size_in_pixels,
app.clear_color(&integration.egui_ctx.style().visuals),
);
painter.paint_and_update_textures(
screen_size_in_pixels,
pixels_per_point,
&clipped_primitives,
@@ -612,39 +606,32 @@ mod glow_integration {
{
let screenshot_requested = &mut integration.frame.output.screenshot_requested;
if *screenshot_requested {
*screenshot_requested = false;
let screenshot = painter.borrow().read_screen_rgba(screen_size_in_pixels);
let screenshot = painter.read_screen_rgba(screen_size_in_pixels);
integration.frame.screenshot.set(Some(screenshot));
}
integration.post_rendering(app.as_mut(), viewport.window.as_ref().unwrap());
integration.post_rendering(app.as_mut(), window);
}
{
crate::profile_scope!("swap_buffers");
if let Err(err) = viewport
.gl_surface
.as_ref()
.expect("failed to get surface to swap buffers")
.swap_buffers(
current_gl_context
.as_ref()
.expect("failed to get current context to swap buffers"),
)
{
if let Err(err) = gl_surface.swap_buffers(
current_gl_context
.as_ref()
.expect("failed to get current context to swap buffers"),
) {
log::error!("swap_buffers failed: {err}");
}
}
integration.post_present(viewport.window.as_ref().unwrap());
integration.post_present(window);
// give it time to settle:
#[cfg(feature = "__screenshot")]
if integration.egui_ctx.frame_nr() == 2 {
if let Ok(path) = std::env::var("EFRAME_SCREENSHOT_TO") {
save_screeshot_and_exit(&path, painter, screen_size_in_pixels);
save_screeshot_and_exit(&path, &painter, screen_size_in_pixels);
}
}
@@ -682,14 +669,14 @@ mod glow_integration {
fn save_screeshot_and_exit(
path: &str,
painter: &mut Rc<RefCell<egui_glow::Painter>>,
painter: &egui_glow::Painter,
screen_size_in_pixels: [u32; 2],
) {
assert!(
path.ends_with(".png"),
"Expected EFRAME_SCREENSHOT_TO to end with '.png', got {path:?}"
);
let screenshot = painter.borrow().read_screen_rgba(screen_size_in_pixels);
let screenshot = painter.read_screen_rgba(screen_size_in_pixels);
image::save_buffer(
path,
screenshot.as_raw(),
@@ -742,7 +729,7 @@ mod glow_integration {
not_current_gl_context: Option<glutin::context::NotCurrentContext>,
viewports: ViewportIdMap<Viewport>,
viewport_maps: HashMap<WindowId, ViewportId>,
viewport_from_window: HashMap<WindowId, ViewportId>,
window_maps: ViewportIdMap<WindowId>,
}
@@ -859,10 +846,10 @@ mod glow_integration {
};
let not_current_gl_context = Some(gl_context);
let mut viewport_maps = HashMap::default();
let mut viewport_from_window = HashMap::default();
let mut window_maps = ViewportIdMap::default();
if let Some(window) = &window {
viewport_maps.insert(window.id(), ViewportId::ROOT);
viewport_from_window.insert(window.id(), ViewportId::ROOT);
window_maps.insert(ViewportId::ROOT, window.id());
}
@@ -890,7 +877,7 @@ mod glow_integration {
current_gl_context: None,
not_current_gl_context,
viewports,
viewport_maps,
viewport_from_window,
max_texture_side: None,
window_maps,
};
@@ -998,7 +985,8 @@ mod glow_integration {
viewport.gl_surface = Some(gl_surface);
self.current_gl_context = Some(current_gl_context);
self.viewport_maps.insert(window.id(), viewport.ids.this);
self.viewport_from_window
.insert(window.id(), viewport.ids.this);
self.window_maps.insert(viewport.ids.this, window.id());
}
viewport.window = Some(window);
@@ -1102,7 +1090,7 @@ mod glow_integration {
// GC old viewports
self.viewports
.retain(|id, _| active_viewports_ids.contains(id));
self.viewport_maps
self.viewport_from_window
.retain(|_, id| active_viewports_ids.contains(id));
self.window_maps
.retain(|id, _| active_viewports_ids.contains(id));
@@ -1479,7 +1467,8 @@ mod glow_integration {
let screen_size_in_pixels: [u32; 2] = window.inner_size().into();
let clipped_primitives = egui_ctx.tessellate(output.shapes);
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 mut painter = painter.borrow_mut();
@@ -1507,7 +1496,6 @@ mod glow_integration {
let gl = &painter.gl().clone();
egui_glow::painter::clear(gl, screen_size_in_pixels, [0.0, 0.0, 0.0, 0.0]);
let pixels_per_point = egui_ctx.input_for(ids.this, |i| i.pixels_per_point());
painter.paint_and_update_textures(
screen_size_in_pixels,
pixels_per_point,
@@ -1540,7 +1528,9 @@ mod glow_integration {
fn is_focused(&self, window_id: WindowId) -> bool {
if let Some(focused_viewport) = self.focused_viewport {
if let Some(running) = self.running.as_ref() {
if let Some(window_id) = running.glutin.borrow().viewport_maps.get(&window_id) {
if let Some(window_id) =
running.glutin.borrow().viewport_from_window.get(&window_id)
{
return focused_viewport == *window_id;
}
}
@@ -1555,7 +1545,7 @@ mod glow_integration {
fn window(&self, window_id: WindowId) -> Option<Rc<Window>> {
let running = self.running.as_ref()?;
let glutin = running.glutin.borrow();
let viewport_id = *glutin.viewport_maps.get(&window_id)?;
let viewport_id = *glutin.viewport_from_window.get(&window_id)?;
if let Some(viewport) = glutin.viewports.get(&viewport_id) {
viewport.window.clone()
} else {
@@ -1569,12 +1559,6 @@ mod glow_integration {
.and_then(|r| r.glutin.borrow().window_maps.get(&id).copied())
}
fn viewport_id_from_window_id(&self, id: &WindowId) -> Option<ViewportId> {
self.running
.as_ref()
.and_then(|r| r.glutin.borrow().viewport_maps.get(id).copied())
}
fn save_and_destroy(&mut self) {
if let Some(mut running) = self.running.take() {
crate::profile_function!();
@@ -1670,7 +1654,7 @@ mod glow_integration {
running
.glutin
.borrow_mut()
.viewport_maps
.viewport_from_window
.get(window_id)
.copied()
})
@@ -1684,7 +1668,7 @@ mod glow_integration {
// This solves an issue where the app would panic when minimizing on Windows.
let glutin = &mut *running.glutin.borrow_mut();
if 0 < physical_size.width && 0 < physical_size.height {
if let Some(id) = glutin.viewport_maps.get(window_id) {
if let Some(id) = glutin.viewport_from_window.get(window_id) {
glutin.resize(*id, *physical_size);
}
}
@@ -1695,7 +1679,7 @@ mod glow_integration {
} => {
let glutin = &mut *running.glutin.borrow_mut();
repaint_asap = true;
if let Some(id) = glutin.viewport_maps.get(window_id) {
if let Some(id) = glutin.viewport_from_window.get(window_id) {
glutin.resize(*id, **new_inner_size);
}
}
@@ -1703,7 +1687,7 @@ mod glow_integration {
if running
.glutin
.borrow()
.viewport_maps
.viewport_from_window
.get(window_id)
.map_or(false, |id| *id == ViewportId::ROOT)
&& running.integration.should_close() =>
@@ -1716,7 +1700,8 @@ mod glow_integration {
let event_response = 'res: {
let mut glutin = running.glutin.borrow_mut();
if let Some(viewport_id) = glutin.viewport_maps.get(window_id).copied()
if let Some(viewport_id) =
glutin.viewport_from_window.get(window_id).copied()
{
if let Some(viewport) = glutin.viewports.get_mut(&viewport_id) {
break 'res running.integration.on_event(
@@ -1758,7 +1743,9 @@ mod glow_integration {
crate::profile_scope!("on_accesskit_action_request");
let mut glutin = running.glutin.borrow_mut();
if let Some(viewport_id) = glutin.viewport_maps.get(window_id).copied() {
if let Some(viewport_id) =
glutin.viewport_from_window.get(window_id).copied()
{
if let Some(viewport) = glutin.viewports.get_mut(&viewport_id) {
viewport
.egui_winit
@@ -1823,8 +1810,11 @@ mod wgpu_integration {
/// `None` for sync viewports.
viewport_ui_cb: Option<Arc<ViewportUiCallback>>,
// `window` and `egui_winit` are initialized together.
/// Window surface state that's initialized when the app starts running via a Resumed event
/// and on Android will also be destroyed if the application is paused.
window: Option<Rc<Window>>,
/// `window` and `egui_winit` are initialized together.
egui_winit: Option<egui_winit::State>,
}
@@ -1837,13 +1827,15 @@ mod wgpu_integration {
) {
crate::profile_function!();
let id = self.ids.this;
let viewport_id = self.ids.this;
if let Ok(new_window) = create_winit_window_builder(&self.builder).build(event_loop) {
windows_id.insert(new_window.id(), id);
windows_id.insert(new_window.id(), viewport_id);
if let Err(err) = pollster::block_on(painter.set_window(id, Some(&new_window))) {
log::error!("on set_window: viewport_id {id:?} {err}");
if let Err(err) =
pollster::block_on(painter.set_window(viewport_id, Some(&new_window)))
{
log::error!("on set_window: viewport_id {viewport_id:?} {err}");
}
self.egui_winit = Some(egui_winit::State::new(
@@ -1865,7 +1857,7 @@ mod wgpu_integration {
pub struct SharedState {
viewports: Viewports,
painter: egui_wgpu::winit::Painter,
viewport_maps: HashMap<WindowId, ViewportId>,
viewport_from_window: HashMap<WindowId, ViewportId>,
}
/// State that is initialized when the application is first starts running via
@@ -1873,20 +1865,25 @@ mod wgpu_integration {
/// initialized once the application has an associated `SurfaceView`.
struct WgpuWinitRunning {
integration: epi_integration::EpiIntegration,
/// The users application.
app: Box<dyn epi::App>,
/// Wrapped in an `Rc<RefCell<…>>` so it can be re-entrantly shared via a weak-pointer.
shared: Rc<RefCell<SharedState>>,
}
struct WgpuWinitApp {
repaint_proxy: Arc<Mutex<EventLoopProxy<UserEvent>>>,
app_name: String,
native_options: epi::NativeOptions,
/// Set at initialization, then taken and set to `None` in `init_run_state`.
app_creator: Option<epi::AppCreator>,
/// Set when we are actually up and running.
running: Option<WgpuWinitRunning>,
/// Window surface state that's initialized when the app starts running via a Resumed event
/// and on Android will also be destroyed if the application is paused.
focused_viewport: Option<ViewportId>,
}
@@ -1898,6 +1895,7 @@ mod wgpu_integration {
app_creator: epi::AppCreator,
) -> Self {
crate::profile_function!();
#[cfg(feature = "__screenshot")]
assert!(
std::env::var("EFRAME_SCREENSHOT_TO").is_err(),
@@ -1922,12 +1920,12 @@ mod wgpu_integration {
let SharedState {
viewports,
painter,
viewport_maps,
viewport_from_window,
} = &mut *shared;
for viewport in viewports.values_mut() {
if viewport.window.is_none() {
viewport.init_window(viewport_maps, painter, event_loop);
viewport.init_window(viewport_from_window, painter, event_loop);
}
}
}
@@ -2034,8 +2032,8 @@ mod wgpu_integration {
integration.warm_up(app.as_mut(), &window, &mut egui_winit);
}
let mut viewport_maps = HashMap::default();
viewport_maps.insert(window.id(), ViewportId::ROOT);
let mut viewport_from_window = HashMap::default();
viewport_from_window.insert(window.id(), ViewportId::ROOT);
let mut viewports = Viewports::default();
viewports.insert(
@@ -2050,7 +2048,7 @@ mod wgpu_integration {
);
let shared = Rc::new(RefCell::new(SharedState {
viewport_maps,
viewport_from_window,
viewports,
painter,
}));
@@ -2127,22 +2125,18 @@ mod wgpu_integration {
} = immediate_viewport;
let input = {
let mut shared = shared.borrow_mut();
let SharedState {
viewports,
painter,
viewport_maps,
} = &mut *shared;
viewport_from_window,
} = &mut *shared.borrow_mut();
let viewport = initialize_or_update_viewport(viewports, ids, builder, None, None);
if viewport.window.is_none() {
viewport.init_window(viewport_maps, painter, event_loop);
viewport.init_window(viewport_from_window, painter, event_loop);
}
let Some(winit_state) = &mut viewport.egui_winit else {
return;
};
let Some(window) = &viewport.window else {
let (Some(window), Some(winit_state)) = (&viewport.window, &mut viewport.egui_winit) else {
return;
};
@@ -2153,7 +2147,8 @@ mod wgpu_integration {
// ------------------------------------------
// Run the user code, which could re-entrantly call this function again (!)
// Run the user code, which could re-entrantly call this function again (!).
// Make sure no locks are held during this call.
let output = egui_ctx.run(input, |ctx| {
viewport_ui_cb(ctx);
});
@@ -2183,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);
let clipped_primitives = egui_ctx.tessellate(output.shapes, pixels_per_point);
painter.paint_and_update_textures(
ids.this,
pixels_per_point,
@@ -2204,12 +2199,15 @@ mod wgpu_integration {
}
fn is_focused(&self, window_id: WindowId) -> bool {
if let Some(focus) = self.focused_viewport {
self.viewport_id_from_window_id(&window_id)
.map_or(false, |i| i == focus)
} else {
false
}
let viewport_id = self.running.as_ref().and_then(|r| {
r.shared
.borrow()
.viewport_from_window
.get(&window_id)
.copied()
});
self.focused_viewport.is_some() && self.focused_viewport == viewport_id
}
fn integration(&self) -> Option<&EpiIntegration> {
@@ -2222,7 +2220,7 @@ mod wgpu_integration {
.and_then(|r| {
let shared = r.shared.borrow();
shared
.viewport_maps
.viewport_from_window
.get(&window_id)
.and_then(|id| shared.viewports.get(id).map(|v| v.window.clone()))
})
@@ -2230,13 +2228,17 @@ mod wgpu_integration {
}
fn window_id_from_viewport_id(&self, id: ViewportId) -> Option<WindowId> {
self.running.as_ref().and_then(|r| {
r.shared
Some(
self.running
.as_ref()?
.shared
.borrow()
.viewports
.get(&id)
.and_then(|v| v.window.as_ref().map(|w| w.id()))
})
.get(&id)?
.window
.as_ref()?
.id(),
)
}
fn save_and_destroy(&mut self) {
@@ -2295,6 +2297,7 @@ mod wgpu_integration {
)?;
self.init_run_state(event_loop, storage, window, builder)?
};
EventResult::RepaintNow(
running.shared.borrow().viewports[&ViewportId::ROOT]
.window
@@ -2325,11 +2328,11 @@ mod wgpu_integration {
if let Some(running) = &mut self.running {
let mut shared_lock = running.shared.borrow_mut();
let SharedState {
viewport_maps,
viewport_from_window,
viewports,
..
} = &mut *shared_lock;
if let Some(viewport) = viewport_maps
if let Some(viewport) = viewport_from_window
.get(window_id)
.and_then(|id| viewports.get_mut(id))
{
@@ -2347,12 +2350,6 @@ mod wgpu_integration {
_ => EventResult::Wait,
})
}
fn viewport_id_from_window_id(&self, id: &WindowId) -> Option<ViewportId> {
self.running
.as_ref()
.and_then(|r| r.shared.borrow().viewport_maps.get(id).copied())
}
}
impl WgpuWinitRunning {
@@ -2391,6 +2388,11 @@ mod wgpu_integration {
window_id: WindowId,
focused_viewport: Option<ViewportId>,
) -> EventResult {
let Some(viewport_id) = self.shared.borrow().viewport_from_window.get(&window_id).copied()
else {
return EventResult::Wait;
};
#[cfg(feature = "puffin")]
puffin::GlobalProfiler::lock().new_frame();
@@ -2406,21 +2408,16 @@ mod wgpu_integration {
let mut shared_lock = shared.borrow_mut();
let SharedState {
viewports,
painter,
viewport_maps,
viewports, painter, ..
} = &mut *shared_lock;
let Some(viewport_id) = viewport_maps.get(&window_id).copied() else {
return EventResult::Wait;
};
let Some(viewport) = viewports.get(&viewport_id) else {
return EventResult::Wait;
};
// This is used to not render a viewport if is sync
if viewport_id != ViewportId::ROOT && viewport.viewport_ui_cb.is_none() {
// This will only happen if this is an immediate viewport.
// That means that the viewport cannot be rendered by itself and needs his parent to be rendered.
if let Some(viewport) = viewports.get(&viewport.ids.parent) {
if let Some(window) = viewport.window.as_ref() {
return EventResult::RepaintNext(window.id());
@@ -2477,22 +2474,19 @@ mod wgpu_integration {
let SharedState {
viewports,
painter,
viewport_maps,
viewport_from_window,
} = &mut *shared;
let Some(viewport_id) = viewport_maps.get(&window_id).copied() else {
return EventResult::Wait;
};
let Some(viewport) = viewports.get_mut(&viewport_id) else {
return EventResult::Wait;
};
let Viewport {
window, egui_winit, ..
} = viewport;
let Some(window) = window else {
window: Some(window),
egui_winit: Some(egui_winit),
..
} = viewport
else {
return EventResult::Wait;
};
@@ -2502,35 +2496,31 @@ mod wgpu_integration {
platform_output,
textures_delta,
shapes,
viewports: mut out_viewports,
viewports: out_viewports,
viewport_commands,
} = full_output;
integration.handle_platform_output(
window,
viewport_id,
platform_output,
egui_winit.as_mut().unwrap(),
);
integration.handle_platform_output(window, viewport_id, platform_output, egui_winit);
let clipped_primitives = integration.egui_ctx.tessellate(shapes);
{
let pixels_per_point = integration
.egui_ctx
.input_for(viewport_id, |i| i.pixels_per_point());
let screenshot_requested = &mut integration.frame.output.screenshot_requested;
let clipped_primitives = integration.egui_ctx.tessellate(shapes, pixels_per_point);
let pixels_per_point = integration
.egui_ctx
.input_for(viewport_id, |i| i.pixels_per_point());
let screenshot = painter.paint_and_update_textures(
viewport_id,
pixels_per_point,
app.clear_color(&integration.egui_ctx.style().visuals),
&clipped_primitives,
&textures_delta,
*screenshot_requested,
);
*screenshot_requested = false;
integration.frame.screenshot.set(screenshot);
let screenshot_requested = &mut integration.frame.output.screenshot_requested;
let screenshot = painter.paint_and_update_textures(
viewport_id,
pixels_per_point,
app.clear_color(&integration.egui_ctx.style().visuals),
&clipped_primitives,
&textures_delta,
*screenshot_requested,
);
*screenshot_requested = false;
integration.frame.screenshot.set(screenshot);
}
integration.post_rendering(app.as_mut(), window);
integration.post_present(window);
@@ -2538,24 +2528,6 @@ mod wgpu_integration {
let mut active_viewports_ids = ViewportIdSet::default();
active_viewports_ids.insert(ViewportId::ROOT);
// Update exisitng viewports:
out_viewports.retain_mut(
|ViewportOutput {
ids: ViewportIdPair { this, parent },
viewport_ui_cb,
..
}| {
if let Some(viewport) = viewports.get_mut(this) {
viewport.viewport_ui_cb = viewport_ui_cb.clone();
viewport.ids.parent = *parent;
active_viewports_ids.insert(*this);
false
} else {
true
}
},
);
// Add new viewports, and update existing ones:
for ViewportOutput {
ids,
@@ -2574,6 +2546,7 @@ mod wgpu_integration {
);
}
// Handle viewport commands:
for (viewport_id, command) in viewport_commands {
if let Some(window) = viewports
.get(&viewport_id)
@@ -2590,10 +2563,10 @@ mod wgpu_integration {
// Prune dead viewports:
viewports.retain(|id, _| active_viewports_ids.contains(id));
viewport_maps.retain(|_, id| active_viewports_ids.contains(id));
viewport_from_window.retain(|_, id| active_viewports_ids.contains(id));
painter.gc_viewports(&active_viewports_ids);
let window = viewport_maps
let window = viewport_from_window
.get(&window_id)
.and_then(|id| viewports.get(id))
.and_then(|vp| vp.window.as_ref());
@@ -2629,7 +2602,7 @@ mod wgpu_integration {
} = self;
let mut shared = shared.borrow_mut();
let viewport_id = shared.viewport_maps.get(&window_id).copied();
let viewport_id = shared.viewport_from_window.get(&window_id).copied();
// On Windows, if a window is resized by the user, it should repaint synchronously, inside the
// event handler.
@@ -2671,7 +2644,7 @@ mod wgpu_integration {
if let (Some(width), Some(height), Some(viewport_id)) = (
NonZeroU32::new(new_inner_size.width),
NonZeroU32::new(new_inner_size.height),
shared.viewport_maps.get(&window_id).copied(),
shared.viewport_from_window.get(&window_id).copied(),
) {
repaint_asap = true;
shared.painter.on_window_resized(viewport_id, width, height);

View File

@@ -1631,22 +1631,12 @@ impl Context {
})
}
/// Tessellate the given shapes into triangle meshes.
///
/// Will use the `pixels_per_point` of the last viewport for feathering (anti-aliasing).
pub fn tessellate(&self, shapes: Vec<ClippedShape>) -> Vec<ClippedPrimitive> {
let last_viewport = self.read(|ctx| ctx.last_viewport);
// here we expect that we are the only user of context, since frame is ended
let pixels_per_point = self.input_for(last_viewport, |i| i.pixels_per_point());
self.tessellate_with_pixels_per_point(shapes, pixels_per_point)
}
/// Tessellate the given shapes into triangle meshes.
///
/// `pixels_per_point` is used for feathering (anti-aliasing).
pub fn tessellate_with_pixels_per_point(
/// You can use [`Self::pixels_per_point`] for this,
/// or whatever is appropiate for your viewport.
pub fn tessellate(
&self,
shapes: Vec<ClippedShape>,
pixels_per_point: f32,

View File

@@ -9,6 +9,7 @@ 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| {
@@ -16,7 +17,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)
ctx.tessellate(full_output.shapes, pixels_per_point)
});
});
@@ -32,7 +33,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()));
b.iter(|| ctx.tessellate(full_output.shapes.clone(), pixels_per_point));
});
}

View File

@@ -71,13 +71,14 @@ 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);
let clipped_primitives = ctx.tessellate(full_output.shapes, pixels_per_point);
assert!(!clipped_primitives.is_empty());
}
}
@@ -90,13 +91,14 @@ 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);
let clipped_primitives = ctx.tessellate(full_output.shapes, pixels_per_point);
assert!(
clipped_primitives.is_empty(),
"There should be nothing to show, has at least one primitive with clip_rect: {:?}",

View File

@@ -88,13 +88,11 @@ impl EguiGlow {
self.painter.set_texture(id, &image_delta);
}
let clipped_primitives = self.egui_ctx.tessellate(shapes);
let pixels_per_point = self.egui_ctx.pixels_per_point();
let clipped_primitives = self.egui_ctx.tessellate(shapes, pixels_per_point);
let dimensions: [u32; 2] = window.inner_size().into();
self.painter.paint_primitives(
dimensions,
self.egui_ctx.pixels_per_point(),
&clipped_primitives,
);
self.painter
.paint_primitives(dimensions, pixels_per_point, &clipped_primitives);
for id in textures_delta.free.drain(..) {
self.painter.free_texture(id);