From fb80880ff89abf8674040229dab428b7b88b0b1a Mon Sep 17 00:00:00 2001 From: Konkitoman Date: Wed, 6 Sep 2023 16:30:20 +0300 Subject: [PATCH] * Fix posibile deadlock when sending a viewport command from a sync viewport * Improve viewports example --- crates/eframe/src/native/run.rs | 19 -------------- crates/egui/src/context.rs | 17 +++++++++++-- examples/viewports/src/main.rs | 44 +++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 21 deletions(-) diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index e81066e0f..bfb5e46f1 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -1030,8 +1030,6 @@ mod glow_integration { let _painter = painter.clone(); let time = integration.beginning; - let focused = self.is_focused.clone(); - // ## Sync Rendering integration.egui_ctx.set_render_sync_callback( move |viewport_builder, viewport_id, parent_id, render| { @@ -1129,17 +1127,6 @@ mod glow_integration { break 'try_render; } } - egui_winit::process_viewports_commands( - output.viewport_commands, - *focused.read(), - |id| { - glutin - .read() - .windows - .get(&id) - .and_then(|w| w.read().window.clone()) - }, - ); } } }, @@ -2124,12 +2111,6 @@ mod wgpu_integration { break 'try_render; } } - - egui_winit::process_viewports_commands( - output.viewport_commands, - *focused.read(), - |id| _windows.read().get(&id).and_then(|w| w.window.clone()), - ); } } }, diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index 4ff4212f6..6857964ae 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -1570,9 +1570,13 @@ impl Context { avalibile_viewports }); + let viewport_id = self.get_viewport_id(); + + // We should not process viewport commands when we are a sync viewport, because that will cause a deadlock or a memory race + let mut is_async = viewport_id == ViewportId::MAIN; + let mut viewports = Vec::new(); self.write(|ctx| { - let viewport_id = ctx.get_viewport_id(); ctx.viewports .retain(|_, (builder, id, parent, used, render)| { let out = *used; @@ -1581,6 +1585,10 @@ impl Context { *used = false; } + if !is_async && viewport_id == *id { + is_async = render.is_some(); + } + viewports.push((*id, *parent, builder.clone(), render.clone())); (out || viewport_id != *parent) && avalibile_viewports.contains(parent) }); @@ -1601,13 +1609,18 @@ impl Context { ctx.memory.resume_frame(viewport_id); }); } + FullOutput { platform_output, repaint_after, textures_delta, shapes, viewports, - viewport_commands: self.write(|ctx| std::mem::take(&mut ctx.viewport_commands)), + viewport_commands: if is_async { + self.write(|ctx| std::mem::take(&mut ctx.viewport_commands)) + } else { + Vec::new() + }, } } diff --git a/examples/viewports/src/main.rs b/examples/viewports/src/main.rs index e0babc547..b576990fa 100644 --- a/examples/viewports/src/main.rs +++ b/examples/viewports/src/main.rs @@ -86,6 +86,17 @@ impl eframe::App for App { if ui.button("Add").clicked() { *state += 1; } + + if ui.button("Set parent pos {0, 0}").clicked() { + let ctx = ui.ctx().clone(); + let parent_id = ctx.get_parent_viewport_id(); + ctx.viewport_command_for( + parent_id, + egui::ViewportCommand::OuterPosition( + egui::pos2(0.0, 0.0), + ), + ); + } }; show_as_popup( @@ -111,6 +122,17 @@ impl eframe::App for App { if ui.button("Add").clicked() { *state += 1; } + + if ui.button("Set parent pos {0, 0}").clicked() { + let ctx = ui.ctx().clone(); + let parent_id = ctx.get_parent_viewport_id(); + ctx.viewport_command_for( + parent_id, + egui::ViewportCommand::OuterPosition( + egui::pos2(0.0, 0.0), + ), + ); + } }; show_as_popup( @@ -160,6 +182,17 @@ impl eframe::App for App { if ui.button("Add").clicked() { *state += 1; } + + if ui.button("Set parent pos {0, 0}").clicked() { + let ctx = ui.ctx().clone(); + let parent_id = ctx.get_parent_viewport_id(); + ctx.viewport_command_for( + parent_id, + egui::ViewportCommand::OuterPosition( + egui::pos2(0.0, 0.0), + ), + ); + } }; show_as_popup( @@ -185,6 +218,17 @@ impl eframe::App for App { if ui.button("Add").clicked() { *state += 1; } + + if ui.button("Set parent pos {0, 0}").clicked() { + let ctx = ui.ctx().clone(); + let parent_id = ctx.get_parent_viewport_id(); + ctx.viewport_command_for( + parent_id, + egui::ViewportCommand::OuterPosition( + egui::pos2(0.0, 0.0), + ), + ); + } }; show_as_popup(