mirror of
https://github.com/emilk/egui.git
synced 2026-09-02 06:40:06 -04:00
Merge branch 'master' of https://github.com/emilk/egui into multiples_viewports
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1231,6 +1231,7 @@ dependencies = [
|
|||||||
"epaint",
|
"epaint",
|
||||||
"log",
|
"log",
|
||||||
"nohash-hasher",
|
"nohash-hasher",
|
||||||
|
"puffin",
|
||||||
"ron",
|
"ron",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -63,9 +63,9 @@ persistence = [
|
|||||||
|
|
||||||
## Enable profiling with the [`puffin`](https://docs.rs/puffin) crate.
|
## Enable profiling with the [`puffin`](https://docs.rs/puffin) crate.
|
||||||
##
|
##
|
||||||
## Only enabled on native, because of the low resolution (1ms) of time keeping in browsers.
|
## Only enabled on native, because of the low resolution (1ms) of clocks in browsers.
|
||||||
## `eframe` will call `puffin::GlobalProfiler::lock().new_frame()` for you
|
## `eframe` will call `puffin::GlobalProfiler::lock().new_frame()` for you
|
||||||
puffin = ["dep:puffin", "egui_glow?/puffin", "egui-wgpu?/puffin"]
|
puffin = ["dep:puffin", "egui/puffin", "egui_glow?/puffin", "egui-wgpu?/puffin"]
|
||||||
|
|
||||||
## Enable screen reader support (requires `ctx.options_mut(|o| o.screen_reader = true);`) on web.
|
## Enable screen reader support (requires `ctx.options_mut(|o| o.screen_reader = true);`) on web.
|
||||||
##
|
##
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ clipboard = ["arboard", "smithay-clipboard"]
|
|||||||
links = ["webbrowser"]
|
links = ["webbrowser"]
|
||||||
|
|
||||||
## Enable profiling with the [`puffin`](https://docs.rs/puffin) crate.
|
## Enable profiling with the [`puffin`](https://docs.rs/puffin) crate.
|
||||||
puffin = ["dep:puffin"]
|
puffin = ["dep:puffin", "egui/puffin"]
|
||||||
|
|
||||||
## Allow serialization of [`WindowSettings`] using [`serde`](https://docs.rs/serde).
|
## Allow serialization of [`WindowSettings`] using [`serde`](https://docs.rs/serde).
|
||||||
serde = ["egui/serde", "dep:serde"]
|
serde = ["egui/serde", "dep:serde"]
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ mint = ["epaint/mint"]
|
|||||||
## Enable persistence of memory (window positions etc).
|
## Enable persistence of memory (window positions etc).
|
||||||
persistence = ["serde", "epaint/serde", "ron"]
|
persistence = ["serde", "epaint/serde", "ron"]
|
||||||
|
|
||||||
|
## Enable profiling with the [`puffin`](https://docs.rs/puffin) crate.
|
||||||
|
##
|
||||||
|
## Only enabled on native, because of the low resolution (1ms) of clocks in browsers.
|
||||||
|
puffin = ["dep:puffin"]
|
||||||
|
|
||||||
## Allow serialization using [`serde`](https://docs.rs/serde).
|
## Allow serialization using [`serde`](https://docs.rs/serde).
|
||||||
serde = ["dep:serde", "epaint/serde", "accesskit?/serde"]
|
serde = ["dep:serde", "epaint/serde", "accesskit?/serde"]
|
||||||
|
|
||||||
@@ -79,5 +84,6 @@ accesskit = { version = "0.11", optional = true }
|
|||||||
document-features = { version = "0.2", optional = true }
|
document-features = { version = "0.2", optional = true }
|
||||||
|
|
||||||
log = { version = "0.4", optional = true, features = ["std"] }
|
log = { version = "0.4", optional = true, features = ["std"] }
|
||||||
|
puffin = { version = "0.16", optional = true }
|
||||||
ron = { version = "0.8", optional = true }
|
ron = { version = "0.8", optional = true }
|
||||||
serde = { version = "1", optional = true, features = ["derive", "rc"] }
|
serde = { version = "1", optional = true, features = ["derive", "rc"] }
|
||||||
|
|||||||
@@ -328,6 +328,7 @@ impl ContextImpl {
|
|||||||
|
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
if self.is_accesskit_enabled {
|
if self.is_accesskit_enabled {
|
||||||
|
crate::profile_scope!("accesskit");
|
||||||
use crate::frame_state::AccessKitFrameState;
|
use crate::frame_state::AccessKitFrameState;
|
||||||
let id = crate::accesskit_root_id();
|
let id = crate::accesskit_root_id();
|
||||||
let mut builder = accesskit::NodeBuilder::new(accesskit::Role::Window);
|
let mut builder = accesskit::NodeBuilder::new(accesskit::Role::Window);
|
||||||
@@ -346,25 +347,33 @@ impl ContextImpl {
|
|||||||
|
|
||||||
/// Load fonts unless already loaded.
|
/// Load fonts unless already loaded.
|
||||||
fn update_fonts_mut(&mut self) {
|
fn update_fonts_mut(&mut self) {
|
||||||
|
crate::profile_function!();
|
||||||
|
|
||||||
let input = self.input.entry(self.get_viewport_id()).or_default();
|
let input = self.input.entry(self.get_viewport_id()).or_default();
|
||||||
let pixels_per_point = input.pixels_per_point();
|
let pixels_per_point = input.pixels_per_point();
|
||||||
let max_texture_side = input.max_texture_side;
|
let max_texture_side = input.max_texture_side;
|
||||||
|
|
||||||
if let Some(font_definitions) = self.memory.new_font_definitions.take() {
|
if let Some(font_definitions) = self.memory.new_font_definitions.take() {
|
||||||
|
crate::profile_scope!("Fonts::new");
|
||||||
let fonts = Fonts::new(pixels_per_point, max_texture_side, font_definitions);
|
let fonts = Fonts::new(pixels_per_point, max_texture_side, font_definitions);
|
||||||
self.fonts = Some(fonts);
|
self.fonts = Some(fonts);
|
||||||
}
|
}
|
||||||
|
|
||||||
let fonts = self.fonts.get_or_insert_with(|| {
|
let fonts = self.fonts.get_or_insert_with(|| {
|
||||||
let font_definitions = FontDefinitions::default();
|
let font_definitions = FontDefinitions::default();
|
||||||
|
crate::profile_scope!("Fonts::new");
|
||||||
Fonts::new(pixels_per_point, max_texture_side, font_definitions)
|
Fonts::new(pixels_per_point, max_texture_side, font_definitions)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
{
|
||||||
|
crate::profile_scope!("Fonts::begin_frame");
|
||||||
fonts.begin_frame(pixels_per_point, max_texture_side);
|
fonts.begin_frame(pixels_per_point, max_texture_side);
|
||||||
|
}
|
||||||
|
|
||||||
if self.memory.options.preload_font_glyphs {
|
if self.memory.options.preload_font_glyphs {
|
||||||
|
crate::profile_scope!("preload_font_glyphs");
|
||||||
// Preload the most common characters for the most common fonts.
|
// Preload the most common characters for the most common fonts.
|
||||||
// This is not very important to do, but may a few GPU operations.
|
// This is not very important to do, but may save a few GPU operations.
|
||||||
for font_id in self.memory.options.style.text_styles.values() {
|
for font_id in self.memory.options.style.text_styles.values() {
|
||||||
fonts.lock().fonts.font(font_id).preload_common_characters();
|
fonts.lock().fonts.font(font_id).preload_common_characters();
|
||||||
}
|
}
|
||||||
@@ -531,6 +540,8 @@ impl Context {
|
|||||||
parent_viewport_id: ViewportId,
|
parent_viewport_id: ViewportId,
|
||||||
run_ui: impl FnOnce(&Context),
|
run_ui: impl FnOnce(&Context),
|
||||||
) -> FullOutput {
|
) -> FullOutput {
|
||||||
|
crate::profile_function!();
|
||||||
|
|
||||||
self.begin_frame(new_input, viewport_id, parent_viewport_id);
|
self.begin_frame(new_input, viewport_id, parent_viewport_id);
|
||||||
run_ui(self);
|
run_ui(self);
|
||||||
self.end_frame()
|
self.end_frame()
|
||||||
@@ -559,6 +570,8 @@ impl Context {
|
|||||||
viewport_id: ViewportId,
|
viewport_id: ViewportId,
|
||||||
parent_viewport_id: ViewportId,
|
parent_viewport_id: ViewportId,
|
||||||
) {
|
) {
|
||||||
|
crate::profile_function!();
|
||||||
|
|
||||||
self.write(|ctx| ctx.begin_frame_mut(new_input, viewport_id, parent_viewport_id));
|
self.write(|ctx| ctx.begin_frame_mut(new_input, viewport_id, parent_viewport_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1424,6 +1437,8 @@ impl Context {
|
|||||||
/// Call at the end of each frame.
|
/// Call at the end of each frame.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn end_frame(&self) -> FullOutput {
|
pub fn end_frame(&self) -> FullOutput {
|
||||||
|
crate::profile_function!();
|
||||||
|
|
||||||
let mut viewports: Vec<ViewportId> = self.write(|ctx| {
|
let mut viewports: Vec<ViewportId> = self.write(|ctx| {
|
||||||
ctx.layer_rects_prev_viewports.insert(
|
ctx.layer_rects_prev_viewports.insert(
|
||||||
ctx.get_viewport_id(),
|
ctx.get_viewport_id(),
|
||||||
@@ -1466,6 +1481,7 @@ impl Context {
|
|||||||
|
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
{
|
{
|
||||||
|
crate::profile_scope!("accesskit");
|
||||||
let state = self.frame_state_mut(|fs| fs.accesskit_state.take());
|
let state = self.frame_state_mut(|fs| fs.accesskit_state.take());
|
||||||
if let Some(state) = state {
|
if let Some(state) = state {
|
||||||
let has_focus = self.input(|i| i.raw.focused);
|
let has_focus = self.input(|i| i.raw.focused);
|
||||||
@@ -1564,6 +1580,7 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn drain_paint_lists(&self) -> Vec<ClippedShape> {
|
fn drain_paint_lists(&self) -> Vec<ClippedShape> {
|
||||||
|
crate::profile_function!();
|
||||||
self.write(|ctx| {
|
self.write(|ctx| {
|
||||||
ctx.graphics
|
ctx.graphics
|
||||||
.entry(ctx.get_viewport_id())
|
.entry(ctx.get_viewport_id())
|
||||||
@@ -1575,6 +1592,8 @@ impl Context {
|
|||||||
|
|
||||||
/// Tessellate the given shapes into triangle meshes.
|
/// Tessellate the given shapes into triangle meshes.
|
||||||
pub fn tessellate(&self, shapes: Vec<ClippedShape>) -> Vec<ClippedPrimitive> {
|
pub fn tessellate(&self, shapes: Vec<ClippedShape>) -> Vec<ClippedPrimitive> {
|
||||||
|
crate::profile_function!();
|
||||||
|
|
||||||
// A tempting optimization is to reuse the tessellation from last frame if the
|
// A tempting optimization is to reuse the tessellation from last frame if the
|
||||||
// shapes are the same, but just comparing the shapes takes about 50% of the time
|
// shapes are the same, but just comparing the shapes takes about 50% of the time
|
||||||
// it takes to tessellate them, so it is not a worth optimization.
|
// it takes to tessellate them, so it is not a worth optimization.
|
||||||
@@ -1598,13 +1617,16 @@ impl Context {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let paint_stats = PaintStats::from_shapes(&shapes);
|
let paint_stats = PaintStats::from_shapes(&shapes);
|
||||||
let clipped_primitives = tessellator::tessellate_shapes(
|
let clipped_primitives = {
|
||||||
|
crate::profile_scope!("tessellator::tessellate_shapes");
|
||||||
|
tessellator::tessellate_shapes(
|
||||||
pixels_per_point,
|
pixels_per_point,
|
||||||
tessellation_options,
|
tessellation_options,
|
||||||
font_tex_size,
|
font_tex_size,
|
||||||
prepared_discs,
|
prepared_discs,
|
||||||
shapes,
|
shapes,
|
||||||
);
|
)
|
||||||
|
};
|
||||||
ctx.paint_stats = paint_stats.with_clipped_primitives(&clipped_primitives);
|
ctx.paint_stats = paint_stats.with_clipped_primitives(&clipped_primitives);
|
||||||
clipped_primitives
|
clipped_primitives
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ impl Default for FrameState {
|
|||||||
|
|
||||||
impl FrameState {
|
impl FrameState {
|
||||||
pub(crate) fn begin_frame(&mut self, input: &InputState) {
|
pub(crate) fn begin_frame(&mut self, input: &InputState) {
|
||||||
|
crate::profile_function!();
|
||||||
let Self {
|
let Self {
|
||||||
used_ids,
|
used_ids,
|
||||||
available_rect,
|
available_rect,
|
||||||
|
|||||||
@@ -169,6 +169,7 @@ impl InputState {
|
|||||||
mut new: RawInput,
|
mut new: RawInput,
|
||||||
requested_repaint_last_frame: bool,
|
requested_repaint_last_frame: bool,
|
||||||
) -> InputState {
|
) -> InputState {
|
||||||
|
crate::profile_function!();
|
||||||
let time = new.time.unwrap_or(self.time + new.predicted_dt as f64);
|
let time = new.time.unwrap_or(self.time + new.predicted_dt as f64);
|
||||||
let unstable_dt = (time - self.time) as f32;
|
let unstable_dt = (time - self.time) as f32;
|
||||||
|
|
||||||
|
|||||||
@@ -591,3 +591,32 @@ pub fn __run_test_ui(mut add_contents: impl FnMut(&mut Ui)) {
|
|||||||
pub fn accesskit_root_id() -> Id {
|
pub fn accesskit_root_id() -> Id {
|
||||||
Id::new("accesskit_root")
|
Id::new("accesskit_root")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
mod profiling_scopes {
|
||||||
|
#![allow(unused_macros)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
|
/// Profiling macro for feature "puffin"
|
||||||
|
macro_rules! profile_function {
|
||||||
|
($($arg: tt)*) => {
|
||||||
|
#[cfg(not(target_arch = "wasm32"))] // Disabled on web because of the coarse 1ms clock resolution there.
|
||||||
|
#[cfg(feature = "puffin")]
|
||||||
|
puffin::profile_function!($($arg)*);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
pub(crate) use profile_function;
|
||||||
|
|
||||||
|
/// Profiling macro for feature "puffin"
|
||||||
|
macro_rules! profile_scope {
|
||||||
|
($($arg: tt)*) => {
|
||||||
|
#[cfg(not(target_arch = "wasm32"))] // Disabled on web because of the coarse 1ms clock resolution there.
|
||||||
|
#[cfg(feature = "puffin")]
|
||||||
|
puffin::profile_scope!($($arg)*);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
pub(crate) use profile_scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use profiling_scopes::*;
|
||||||
|
|||||||
@@ -511,6 +511,8 @@ impl Memory {
|
|||||||
new_input: &crate::data::input::RawInput,
|
new_input: &crate::data::input::RawInput,
|
||||||
viewport_id: ViewportId,
|
viewport_id: ViewportId,
|
||||||
) {
|
) {
|
||||||
|
crate::profile_function!();
|
||||||
|
|
||||||
self.viewport_id = viewport_id;
|
self.viewport_id = viewport_id;
|
||||||
self.interactions
|
self.interactions
|
||||||
.entry(viewport_id)
|
.entry(viewport_id)
|
||||||
|
|||||||
@@ -515,6 +515,7 @@ struct PersistedMap(Vec<(u64, SerializedElement)>);
|
|||||||
#[cfg(feature = "persistence")]
|
#[cfg(feature = "persistence")]
|
||||||
impl PersistedMap {
|
impl PersistedMap {
|
||||||
fn from_map(map: &IdTypeMap) -> Self {
|
fn from_map(map: &IdTypeMap) -> Self {
|
||||||
|
crate::profile_function!();
|
||||||
// filter out the elements which cannot be serialized:
|
// filter out the elements which cannot be serialized:
|
||||||
Self(
|
Self(
|
||||||
map.0
|
map.0
|
||||||
@@ -525,6 +526,7 @@ impl PersistedMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn into_map(self) -> IdTypeMap {
|
fn into_map(self) -> IdTypeMap {
|
||||||
|
crate::profile_function!();
|
||||||
IdTypeMap(
|
IdTypeMap(
|
||||||
self.0
|
self.0
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -542,6 +544,7 @@ impl serde::Serialize for IdTypeMap {
|
|||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
{
|
{
|
||||||
|
crate::profile_scope!("IdTypeMap::serialize");
|
||||||
PersistedMap::from_map(self).serialize(serializer)
|
PersistedMap::from_map(self).serialize(serializer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -552,6 +555,7 @@ impl<'de> serde::Deserialize<'de> for IdTypeMap {
|
|||||||
where
|
where
|
||||||
D: serde::Deserializer<'de>,
|
D: serde::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
|
crate::profile_scope!("IdTypeMap::deserialize");
|
||||||
<PersistedMap>::deserialize(deserializer).map(PersistedMap::into_map)
|
<PersistedMap>::deserialize(deserializer).map(PersistedMap::into_map)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ clipboard = ["egui-winit?/clipboard"]
|
|||||||
links = ["egui-winit?/links"]
|
links = ["egui-winit?/links"]
|
||||||
|
|
||||||
## Enable profiling with the [`puffin`](https://docs.rs/puffin) crate.
|
## Enable profiling with the [`puffin`](https://docs.rs/puffin) crate.
|
||||||
puffin = ["dep:puffin", "egui-winit?/puffin"]
|
puffin = ["dep:puffin", "egui-winit?/puffin", "egui/puffin"]
|
||||||
|
|
||||||
## Enable [`winit`](https://docs.rs/winit) integration.
|
## Enable [`winit`](https://docs.rs/winit) integration.
|
||||||
winit = ["egui-winit"]
|
winit = ["egui-winit"]
|
||||||
|
|||||||
Reference in New Issue
Block a user