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

Move the viewport commands into the per-viewport output

This commit is contained in:
Emil Ernerfeldt
2023-11-15 18:43:52 +01:00
parent e36ef75f68
commit fb07dc1bd7
4 changed files with 100 additions and 71 deletions

View File

@@ -564,7 +564,6 @@ mod glow_integration {
shapes,
pixels_per_point,
viewports: viewports_out,
viewport_commands,
} = full_output;
let GlutinWindowContext {
@@ -649,19 +648,6 @@ mod glow_integration {
glutin.process_viewport_updates(viewports_out, focused_viewport);
for (viewport_id, command) in viewport_commands {
if let Some(viewport) = glutin.viewports.get(&viewport_id) {
if let Some(window) = &viewport.window {
let is_viewport_focused = focused_viewport == Some(viewport_id);
egui_winit::process_viewport_commands(
[command],
window,
is_viewport_focused,
);
}
}
}
if integration.should_close() {
EventResult::Exit
} else {
@@ -1169,7 +1155,7 @@ mod glow_integration {
fn process_viewport_updates(
&mut self,
viewport_output: Vec<ViewportOutput>,
viewport_output: ViewportIdMap<ViewportOutput>,
focused_viewport: Option<ViewportId>,
) {
crate::profile_function!();
@@ -1177,13 +1163,17 @@ mod glow_integration {
let mut active_viewports_ids = ViewportIdSet::default();
active_viewports_ids.insert(ViewportId::ROOT);
for ViewportOutput {
ids,
builder,
viewport_ui_cb,
} in viewport_output
for (
viewport_id,
ViewportOutput {
ids,
builder,
viewport_ui_cb,
commands,
},
) in viewport_output
{
active_viewports_ids.insert(ids.this);
active_viewports_ids.insert(viewport_id);
initialize_or_update_viewport(
&mut self.viewports,
@@ -1192,6 +1182,17 @@ mod glow_integration {
viewport_ui_cb,
focused_viewport,
);
if let Some(viewport) = self.viewports.get(&viewport_id) {
if let Some(window) = &viewport.window {
let is_viewport_focused = focused_viewport == Some(viewport_id);
egui_winit::process_viewport_commands(
commands,
window,
is_viewport_focused,
);
}
}
}
// GC old viewports
@@ -2455,10 +2456,7 @@ mod wgpu_integration {
let raw_input = egui_winit.as_mut().unwrap().take_egui_input(
window,
ViewportIdPair {
this: viewport_id,
parent: ids.parent,
},
ViewportIdPair::from_self_and_parent(viewport_id, ids.parent),
);
integration.pre_update(window);
@@ -2504,7 +2502,6 @@ mod wgpu_integration {
shapes,
pixels_per_point,
viewports: out_viewports,
viewport_commands,
} = full_output;
integration.handle_platform_output(window, viewport_id, platform_output, egui_winit);
@@ -2532,13 +2529,17 @@ mod wgpu_integration {
active_viewports_ids.insert(ViewportId::ROOT);
// Add new viewports, and update existing ones:
for ViewportOutput {
ids,
builder,
viewport_ui_cb,
} in out_viewports
for (
viewport_id,
ViewportOutput {
ids,
builder,
viewport_ui_cb,
commands,
},
) in out_viewports
{
active_viewports_ids.insert(ids.this);
active_viewports_ids.insert(viewport_id);
initialize_or_update_viewport(
viewports,
@@ -2547,16 +2548,13 @@ mod wgpu_integration {
viewport_ui_cb,
focused_viewport,
);
}
// Handle viewport commands:
for (viewport_id, command) in viewport_commands {
if let Some(window) = viewports
.get(&viewport_id)
.and_then(|vp| vp.window.as_ref())
{
let is_viewport_focused = focused_viewport == Some(viewport_id);
egui_winit::process_viewport_commands([command], window, is_viewport_focused);
egui_winit::process_viewport_commands(commands, window, is_viewport_focused);
}
}

View File

@@ -146,6 +146,7 @@ struct ViewportState {
// The output of a frame:
graphics: GraphicLayers,
output: PlatformOutput,
commands: Vec<ViewportCommand>,
}
/// Per-viewport state related to repaint scheduling.
@@ -185,7 +186,6 @@ struct ContextImpl {
viewport_parents: ViewportIdMap<ViewportId>,
viewports: ViewportIdMap<ViewportState>,
viewport_commands: Vec<(ViewportId, ViewportCommand)>,
embed_viewports: bool,
@@ -1563,24 +1563,36 @@ impl ContextImpl {
true
});
let out_viewports = self
.viewports
.iter()
.map(|(&id, viewport)| {
let parent = *self.viewport_parents.entry(id).or_default();
ViewportOutput {
ids: ViewportIdPair { this: id, parent },
builder: viewport.builder.clone(),
viewport_ui_cb: viewport.viewport_ui_cb.clone(),
}
})
.collect();
// This is used to resume the last frame!
self.viewport_stack.pop();
// The last viewport is not necessarily the root viewport,
// just the top _immediate_ viewport.
let is_last = self.viewport_stack.is_empty();
let out_viewports = self
.viewports
.iter_mut()
.map(|(&id, viewport)| {
let parent = *self.viewport_parents.entry(id).or_default();
let commands = if is_last {
std::mem::take(&mut viewport.commands)
} else {
vec![]
};
(
id,
ViewportOutput {
ids: ViewportIdPair::from_self_and_parent(id, parent),
builder: viewport.builder.clone(),
viewport_ui_cb: viewport.viewport_ui_cb.clone(),
commands,
},
)
})
.collect();
if is_last {
// Remove dead viewports:
self.viewports.retain(|id, _| all_viewport_ids.contains(id));
@@ -1597,12 +1609,6 @@ impl ContextImpl {
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 {
std::mem::take(&mut self.viewport_commands)
} else {
Vec::new()
},
}
}
}
@@ -2518,7 +2524,7 @@ impl Context {
/// Send a command to a speicfic viewport.
pub fn viewport_command_for(&self, id: ViewportId, command: ViewportCommand) {
self.write(|ctx| ctx.viewport_commands.push((id, command)));
self.write(|ctx| ctx.viewport_for(id).commands.push(command));
}
/// This creates a new native window, if possible.
@@ -2615,10 +2621,7 @@ impl Context {
viewport.used = true;
viewport.viewport_ui_cb = None; // it is immediate
ViewportIdPair {
this: new_viewport_id,
parent: parent_viewport_id,
}
ViewportIdPair::from_self_and_parent(new_viewport_id, parent_viewport_id)
});
let mut out = None;

View File

@@ -1,6 +1,6 @@
//! All the data egui returns to the backend at the end of each frame.
use crate::{ViewportCommand, ViewportId, ViewportOutput, WidgetType};
use crate::{ViewportIdMap, ViewportOutput, WidgetType};
/// What egui emits each frame from [`crate::Context::run`].
///
@@ -26,11 +26,8 @@ pub struct FullOutput {
/// You can pass this to [`crate::Context::tessellate`] together with [`Self::shapes`].
pub pixels_per_point: f32,
/// All the active viewports, excluding the root.
pub viewports: Vec<ViewportOutput>,
/// Commands sent to different viewports.
pub viewport_commands: Vec<(ViewportId, ViewportCommand)>,
/// All the active viewports, including the root.
pub viewports: ViewportIdMap<ViewportOutput>,
}
impl FullOutput {
@@ -41,16 +38,24 @@ impl FullOutput {
textures_delta,
shapes,
pixels_per_point,
mut viewports,
mut viewport_commands,
viewports,
} = newer;
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);
for (id, new_viewport) in viewports {
match self.viewports.entry(id) {
std::collections::hash_map::Entry::Vacant(entry) => {
entry.insert(new_viewport);
}
std::collections::hash_map::Entry::Occupied(mut entry) => {
entry.get_mut().append(new_viewport);
}
}
}
}
}

View File

@@ -83,6 +83,11 @@ impl ViewportIdPair {
this: ViewportId::ROOT,
parent: ViewportId::ROOT,
};
#[inline]
pub fn from_self_and_parent(this: ViewportId, parent: ViewportId) -> Self {
Self { this, parent }
}
}
/// The user-code that shows the ui in the viewport, used for deferred viewports.
@@ -669,12 +674,30 @@ pub struct ViewportOutput {
///
/// `None` for immediate viewports and the ROOT viewport.
pub viewport_ui_cb: Option<Arc<ViewportUiCallback>>,
/// Commands to change the viewport, e.g. window title and size.
pub commands: Vec<ViewportCommand>,
}
impl ViewportOutput {
pub fn id(&self) -> ViewportId {
self.ids.this
}
/// Add on new output.
pub fn append(&mut self, newer: Self) {
let Self {
ids,
builder,
viewport_ui_cb,
mut commands,
} = newer;
self.ids = ids;
self.builder.patch(&builder);
self.viewport_ui_cb = viewport_ui_cb;
self.commands.append(&mut commands);
}
}
/// Viewport for immediate rendering.