1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-31 22:00:03 -04:00

Simplify Context::end_frame

This commit is contained in:
Emil Ernerfeldt
2023-11-15 11:03:32 +01:00
parent ab67a310c2
commit c18eb1987e

View File

@@ -1478,51 +1478,54 @@ impl Context {
#[must_use] #[must_use]
pub fn end_frame(&self) -> FullOutput { pub fn end_frame(&self) -> FullOutput {
crate::profile_function!(); crate::profile_function!();
self.write(|ctx| ctx.end_frame())
}
}
if self.input(|i| i.wants_repaint()) { impl ContextImpl {
self.request_repaint(); fn end_frame(&mut self) -> FullOutput {
let ended_viewport_id = self.viewport_id();
let viewport = self.viewports.entry(ended_viewport_id).or_default();
if viewport.input.wants_repaint() {
self.repaint.requested_repaint(&ended_viewport_id);
} }
let textures_delta = self.write(|ctx| { self.memory
let viewport = ctx.viewports.entry(ctx.viewport_id()).or_default(); .end_frame(&viewport.input, &viewport.frame_state.used_ids);
ctx.memory
.end_frame(&viewport.input, &viewport.frame_state.used_ids);
let font_image_delta = ctx.fonts.as_ref().unwrap().font_image_delta(); let font_image_delta = self.fonts.as_ref().unwrap().font_image_delta();
if let Some(font_image_delta) = font_image_delta { if let Some(font_image_delta) = font_image_delta {
ctx.tex_manager self.tex_manager
.0 .0
.write() .write()
.set(TextureId::default(), font_image_delta); .set(TextureId::default(), font_image_delta);
} }
ctx.tex_manager.0.write().take_delta() let textures_delta = self.tex_manager.0.write().take_delta();
});
#[cfg_attr(not(feature = "accesskit"), allow(unused_mut))] #[cfg_attr(not(feature = "accesskit"), allow(unused_mut))]
let mut platform_output: PlatformOutput = self.output_mut(std::mem::take); let mut platform_output: PlatformOutput = std::mem::take(&mut viewport.output);
#[cfg(feature = "accesskit")] #[cfg(feature = "accesskit")]
{ {
crate::profile_scope!("accesskit"); crate::profile_scope!("accesskit");
let state = self.frame_state_mut(|fs| fs.accesskit_state.take()); let state = viewport.frame_state.accesskit_state.take();
if let Some(state) = state { if let Some(state) = state {
let root_id = crate::accesskit_root_id().accesskit_id(); let root_id = crate::accesskit_root_id().accesskit_id();
let nodes = self.write(|ctx| { let nodes = {
state state
.node_builders .node_builders
.into_iter() .into_iter()
.map(|(id, builder)| { .map(|(id, builder)| {
( (
id.accesskit_id(), id.accesskit_id(),
builder.build(&mut ctx.accesskit_node_classes), builder.build(&mut self.accesskit_node_classes),
) )
}) })
.collect() .collect()
}); };
let focus_id = self let focus_id = self.memory.focus().map_or(root_id, |id| id.accesskit_id());
.memory(|mem| mem.focus())
.map_or(root_id, |id| id.accesskit_id());
platform_output.accesskit_update = Some(accesskit::TreeUpdate { platform_output.accesskit_update = Some(accesskit::TreeUpdate {
nodes, nodes,
tree: Some(accesskit::Tree::new(root_id)), tree: Some(accesskit::Tree::new(root_id)),
@@ -1531,87 +1534,74 @@ impl Context {
} }
} }
let shapes = self.drain_paint_lists(); let shapes = viewport.graphics.drain(self.memory.areas().order());
let all_viewport_ids: ViewportIdSet = self.read(|ctx| { let all_viewport_ids: ViewportIdSet = self
ctx.viewports .viewports
.keys() .keys()
.copied() .copied()
.chain([ViewportId::ROOT]) .chain([ViewportId::ROOT])
.collect() .collect();
});
let current_viewport_id = self.viewport_id();
let mut out_viewports = Vec::new(); let mut out_viewports = Vec::new();
self.write(|ctx| { self.last_viewport = ended_viewport_id;
ctx.last_viewport = current_viewport_id;
ctx.viewports.retain(|&id, viewport| { self.viewports.retain(|&id, viewport| {
let parent = *ctx.viewport_parents.entry(id).or_default(); let parent = *self.viewport_parents.entry(id).or_default();
if !all_viewport_ids.contains(&parent) { if !all_viewport_ids.contains(&parent) {
#[cfg(feature = "log")]
log::debug!(
"Removing viewport {:?} ({:?}): the parent is gone",
id,
viewport.builder.title
);
return false;
}
let is_out_child = parent == ended_viewport_id && id != ViewportId::ROOT;
if is_out_child {
if !viewport.used {
#[cfg(feature = "log")] #[cfg(feature = "log")]
log::debug!( log::debug!(
"Removing viewport {:?} ({:?}): the parent is gone", "Removing viewport {:?} ({:?}): it was never used this frame",
id, id,
viewport.builder.title viewport.builder.title
); );
return false; return false; // Only keep children that have been updated this frame
} }
let is_out_child = parent == current_viewport_id && id != ViewportId::ROOT; viewport.used = false; // reset so we can check again next frame
if is_out_child { }
if !viewport.used {
#[cfg(feature = "log")]
log::debug!(
"Removing viewport {:?} ({:?}): it was never used this frame",
id,
viewport.builder.title
);
return false; // Only keep children that have been updated this frame out_viewports.push(ViewportOutput {
} builder: viewport.builder.clone(),
ids: ViewportIdPair { this: id, parent },
viewport.used = false; // reset so we can check again next frame viewport_ui_cb: viewport.viewport_ui_cb.clone(),
}
out_viewports.push(ViewportOutput {
builder: viewport.builder.clone(),
ids: ViewportIdPair { this: id, parent },
viewport_ui_cb: viewport.viewport_ui_cb.clone(),
});
true
}); });
true
}); });
// This is used to resume the last frame! // This is used to resume the last frame!
let is_last = self.write(|ctx| { self.viewport_stack.pop();
ctx.viewport_stack.pop();
ctx.viewport_stack.is_empty() let is_last = self.viewport_stack.is_empty();
});
if is_last { if is_last {
self.write(|ctx| { // Remove dead viewports:
// Remove dead viewports: self.viewports.retain(|id, _| all_viewport_ids.contains(id));
ctx.viewports.retain(|id, _| all_viewport_ids.contains(id)); self.viewport_parents
ctx.viewport_parents .retain(|id, _| all_viewport_ids.contains(id));
.retain(|id, _| all_viewport_ids.contains(id));
});
} else { } else {
let viewport_id = self.viewport_id(); let viewport_id = self.viewport_id();
self.write(|ctx| { self.memory.set_viewport_id(viewport_id);
ctx.memory.set_viewport_id(viewport_id);
});
} }
self.write(|ctx| { self.repaint.end_frame(ended_viewport_id, &all_viewport_ids);
ctx.repaint
.end_frame(current_viewport_id, &all_viewport_ids);
});
FullOutput { FullOutput {
platform_output, platform_output,
@@ -1620,21 +1610,15 @@ impl Context {
viewports: out_viewports, viewports: out_viewports,
// We should not process viewport commands when we are a sync viewport, because that will cause a deadlock for egui backend // 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 { viewport_commands: if is_last {
self.write(|ctx| std::mem::take(&mut ctx.viewport_commands)) std::mem::take(&mut self.viewport_commands)
} else { } else {
Vec::new() Vec::new()
}, },
} }
} }
}
fn drain_paint_lists(&self) -> Vec<ClippedShape> { impl Context {
crate::profile_function!();
self.write(|ctx| {
let viewport = ctx.viewports.entry(ctx.viewport_id()).or_default();
viewport.graphics.drain(ctx.memory.areas().order())
})
}
/// Tessellate the given shapes into triangle meshes. /// Tessellate the given shapes into triangle meshes.
/// ///
/// `pixels_per_point` is used for feathering (anti-aliasing). /// `pixels_per_point` is used for feathering (anti-aliasing).