Split out tesselation from Context::end_frame()
This commit is contained in:
parent
901a6920be
commit
af11d766fc
9 changed files with 59 additions and 29 deletions
|
@ -13,6 +13,7 @@
|
||||||
* You can no longer throw windows
|
* You can no longer throw windows
|
||||||
* `Context::begin_frame()` no longer returns anything.
|
* `Context::begin_frame()` no longer returns anything.
|
||||||
* Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
|
* Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
|
||||||
|
* `Context::end_frame()` now returns "paint jobs" that need to be converted to triangles with `Context::tesselate()`.
|
||||||
|
|
||||||
## 0.2.0 - 2020-10-10
|
## 0.2.0 - 2020-10-10
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,8 @@ loop {
|
||||||
let raw_input: egui::RawInput = my_integration.gather_input();
|
let raw_input: egui::RawInput = my_integration.gather_input();
|
||||||
egui_ctx.begin_frame(raw_input);
|
egui_ctx.begin_frame(raw_input);
|
||||||
my_app.ui(&mut egui_ctx); // add panels, windows and widgets to `egui_ctx` here
|
my_app.ui(&mut egui_ctx); // add panels, windows and widgets to `egui_ctx` here
|
||||||
let (output, paint_jobs) = egui_ctx.end_frame();
|
let (output, paint_commands) = egui_ctx.end_frame();
|
||||||
|
let paint_jobs = self.ctx.tesselate(paint_commands); // create triangles to paint
|
||||||
my_integration.paint(paint_jobs);
|
my_integration.paint(paint_jobs);
|
||||||
my_integration.set_cursor_icon(output.cursor_icon);
|
my_integration.set_cursor_icon(output.cursor_icon);
|
||||||
// Also see `egui::Output` for more
|
// Also see `egui::Output` for more
|
||||||
|
|
|
@ -33,6 +33,19 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut ctx = egui::Context::new();
|
||||||
|
ctx.memory().all_collpasing_are_open = true; // expand the demo window with everything
|
||||||
|
let mut demo_windows = egui::demos::DemoWindows::default();
|
||||||
|
ctx.begin_frame(raw_input.clone());
|
||||||
|
demo_windows.ui(&ctx, &Default::default(), &mut None);
|
||||||
|
let (_, paint_commands) = ctx.end_frame();
|
||||||
|
|
||||||
|
c.bench_function("tesselate", |b| {
|
||||||
|
b.iter(|| ctx.tesselate(paint_commands.clone()))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut ctx = egui::Context::new();
|
let mut ctx = egui::Context::new();
|
||||||
ctx.begin_frame(raw_input);
|
ctx.begin_frame(raw_input);
|
||||||
|
@ -43,7 +56,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// let _ = ctx.end_frame(); // skip, because tessellating all that text is slow
|
let _ = ctx.end_frame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ struct Options {
|
||||||
/// The default style for new `Ui`:s.
|
/// The default style for new `Ui`:s.
|
||||||
style: Arc<Style>,
|
style: Arc<Style>,
|
||||||
/// Controls the tessellator.
|
/// Controls the tessellator.
|
||||||
paint_options: paint::PaintOptions,
|
tesselation_options: paint::TesselationOptions,
|
||||||
/// Font sizes etc.
|
/// Font sizes etc.
|
||||||
font_definitions: FontDefinitions,
|
font_definitions: FontDefinitions,
|
||||||
}
|
}
|
||||||
|
@ -242,8 +242,10 @@ impl Context {
|
||||||
|
|
||||||
/// Call at the end of each frame.
|
/// Call at the end of each frame.
|
||||||
/// Returns what has happened this frame (`Output`) as well as what you need to paint.
|
/// Returns what has happened this frame (`Output`) as well as what you need to paint.
|
||||||
|
/// You can transform the returned paint commands into triangles with a call to
|
||||||
|
/// `Context::tesselate`.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn end_frame(&self) -> (Output, PaintJobs) {
|
pub fn end_frame(&self) -> (Output, Vec<(Rect, PaintCmd)>) {
|
||||||
if self.input.wants_repaint() {
|
if self.input.wants_repaint() {
|
||||||
self.request_repaint();
|
self.request_repaint();
|
||||||
}
|
}
|
||||||
|
@ -256,8 +258,8 @@ impl Context {
|
||||||
output.needs_repaint = true;
|
output.needs_repaint = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let paint_jobs = self.paint();
|
let paint_commands = self.drain_paint_lists();
|
||||||
(output, paint_jobs)
|
(output, paint_commands)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drain_paint_lists(&self) -> Vec<(Rect, PaintCmd)> {
|
fn drain_paint_lists(&self) -> Vec<(Rect, PaintCmd)> {
|
||||||
|
@ -265,15 +267,17 @@ impl Context {
|
||||||
self.graphics().drain(memory.areas.order()).collect()
|
self.graphics().drain(memory.areas.order()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(&self) -> PaintJobs {
|
/// Tesselate the given paint commands into triangle meshes.
|
||||||
let mut paint_options = self.options.lock().paint_options;
|
pub fn tesselate(&self, paint_commands: Vec<(Rect, PaintCmd)>) -> PaintJobs {
|
||||||
paint_options.aa_size = 1.0 / self.pixels_per_point();
|
let mut tesselation_options = self.options.lock().tesselation_options;
|
||||||
let paint_commands = self.drain_paint_lists();
|
tesselation_options.aa_size = 1.0 / self.pixels_per_point();
|
||||||
let paint_stats = PaintStats::from_paint_commands(&paint_commands); // TODO: internal allocations
|
let paint_stats = PaintStats::from_paint_commands(&paint_commands); // TODO: internal allocations
|
||||||
let paint_jobs =
|
let paint_jobs = tessellator::tessellate_paint_commands(
|
||||||
tessellator::tessellate_paint_commands(paint_commands, paint_options, self.fonts());
|
paint_commands,
|
||||||
|
tesselation_options,
|
||||||
|
self.fonts(),
|
||||||
|
);
|
||||||
*self.paint_stats.lock() = paint_stats.with_paint_jobs(&paint_jobs);
|
*self.paint_stats.lock() = paint_stats.with_paint_jobs(&paint_jobs);
|
||||||
|
|
||||||
paint_jobs
|
paint_jobs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,9 +595,9 @@ impl Context {
|
||||||
CollapsingHeader::new("Painting")
|
CollapsingHeader::new("Painting")
|
||||||
.default_open(true)
|
.default_open(true)
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
let mut paint_options = self.options.lock().paint_options;
|
let mut tesselation_options = self.options.lock().tesselation_options;
|
||||||
paint_options.ui(ui);
|
tesselation_options.ui(ui);
|
||||||
self.options.lock().paint_options = paint_options;
|
self.options.lock().tesselation_options = tesselation_options;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,7 +712,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl paint::PaintOptions {
|
impl paint::TesselationOptions {
|
||||||
pub fn ui(&mut self, ui: &mut Ui) {
|
pub fn ui(&mut self, ui: &mut Ui) {
|
||||||
let Self {
|
let Self {
|
||||||
aa_size: _,
|
aa_size: _,
|
||||||
|
|
|
@ -26,7 +26,8 @@
|
||||||
//! let raw_input: egui::RawInput = my_integration.gather_input();
|
//! let raw_input: egui::RawInput = my_integration.gather_input();
|
||||||
//! egui_ctx.begin_frame(raw_input);
|
//! egui_ctx.begin_frame(raw_input);
|
||||||
//! my_app.ui(&egui_ctx); // add panels, windows and widgets to `egui_ctx` here
|
//! my_app.ui(&egui_ctx); // add panels, windows and widgets to `egui_ctx` here
|
||||||
//! let (output, paint_jobs) = egui_ctx.end_frame();
|
//! let (output, paint_commands) = egui_ctx.end_frame();
|
||||||
|
//! let paint_jobs = self.ctx.tesselate(paint_commands); // create triangles to paint
|
||||||
//! my_integration.paint(paint_jobs);
|
//! my_integration.paint(paint_jobs);
|
||||||
//! my_integration.set_cursor_icon(output.cursor_icon);
|
//! my_integration.set_cursor_icon(output.cursor_icon);
|
||||||
//! // Also see `egui::Output` for more
|
//! // Also see `egui::Output` for more
|
||||||
|
@ -116,7 +117,8 @@ pub fn text_egui_e2e() {
|
||||||
for _ in 0..NUM_FRAMES {
|
for _ in 0..NUM_FRAMES {
|
||||||
ctx.begin_frame(raw_input.clone());
|
ctx.begin_frame(raw_input.clone());
|
||||||
demo_windows.ui(&ctx, &Default::default(), &mut None);
|
demo_windows.ui(&ctx, &Default::default(), &mut None);
|
||||||
let (_output, paint_jobs) = ctx.end_frame();
|
let (_output, paint_commands) = ctx.end_frame();
|
||||||
|
let paint_jobs = ctx.tesselate(paint_commands);
|
||||||
assert!(!paint_jobs.is_empty());
|
assert!(!paint_jobs.is_empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@ pub use {
|
||||||
command::{PaintCmd, Stroke},
|
command::{PaintCmd, Stroke},
|
||||||
fonts::{FontDefinitions, FontFamily, Fonts, TextStyle},
|
fonts::{FontDefinitions, FontFamily, Fonts, TextStyle},
|
||||||
stats::PaintStats,
|
stats::PaintStats,
|
||||||
tessellator::{PaintJob, PaintJobs, PaintOptions, TextureId, Triangles, Vertex, WHITE_UV},
|
tessellator::{
|
||||||
|
PaintJob, PaintJobs, TesselationOptions, TextureId, Triangles, Vertex, WHITE_UV,
|
||||||
|
},
|
||||||
texture_atlas::Texture,
|
texture_atlas::Texture,
|
||||||
};
|
};
|
||||||
|
|
|
@ -446,7 +446,7 @@ use self::PathType::{Closed, Open};
|
||||||
|
|
||||||
/// Tesselation quality options
|
/// Tesselation quality options
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct PaintOptions {
|
pub struct TesselationOptions {
|
||||||
/// Size of a pixel in points, e.g. 0.5
|
/// Size of a pixel in points, e.g. 0.5
|
||||||
pub aa_size: f32,
|
pub aa_size: f32,
|
||||||
/// Anti-aliasing makes shapes appear smoother, but requires more triangles and is therefore slower.
|
/// Anti-aliasing makes shapes appear smoother, but requires more triangles and is therefore slower.
|
||||||
|
@ -459,20 +459,25 @@ pub struct PaintOptions {
|
||||||
pub debug_ignore_clip_rects: bool,
|
pub debug_ignore_clip_rects: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PaintOptions {
|
impl Default for TesselationOptions {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
aa_size: 1.0,
|
aa_size: 1.0,
|
||||||
anti_alias: true,
|
anti_alias: true,
|
||||||
|
coarse_tessellation_culling: true,
|
||||||
debug_paint_clip_rects: false,
|
debug_paint_clip_rects: false,
|
||||||
debug_ignore_clip_rects: false,
|
debug_ignore_clip_rects: false,
|
||||||
coarse_tessellation_culling: true,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tesselate the given convex area into a polygon.
|
/// Tesselate the given convex area into a polygon.
|
||||||
fn fill_closed_path(path: &[PathPoint], color: Srgba, options: PaintOptions, out: &mut Triangles) {
|
fn fill_closed_path(
|
||||||
|
path: &[PathPoint],
|
||||||
|
color: Srgba,
|
||||||
|
options: TesselationOptions,
|
||||||
|
out: &mut Triangles,
|
||||||
|
) {
|
||||||
if color == color::TRANSPARENT {
|
if color == color::TRANSPARENT {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -516,7 +521,7 @@ fn stroke_path(
|
||||||
path: &[PathPoint],
|
path: &[PathPoint],
|
||||||
path_type: PathType,
|
path_type: PathType,
|
||||||
stroke: Stroke,
|
stroke: Stroke,
|
||||||
options: PaintOptions,
|
options: TesselationOptions,
|
||||||
out: &mut Triangles,
|
out: &mut Triangles,
|
||||||
) {
|
) {
|
||||||
if stroke.width <= 0.0 || stroke.color == color::TRANSPARENT {
|
if stroke.width <= 0.0 || stroke.color == color::TRANSPARENT {
|
||||||
|
@ -669,7 +674,7 @@ fn mul_color(color: Srgba, factor: f32) -> Srgba {
|
||||||
fn tessellate_paint_command(
|
fn tessellate_paint_command(
|
||||||
clip_rect: Rect,
|
clip_rect: Rect,
|
||||||
command: PaintCmd,
|
command: PaintCmd,
|
||||||
options: PaintOptions,
|
options: TesselationOptions,
|
||||||
fonts: &Fonts,
|
fonts: &Fonts,
|
||||||
out: &mut Triangles,
|
out: &mut Triangles,
|
||||||
scratchpad_points: &mut Vec<Pos2>,
|
scratchpad_points: &mut Vec<Pos2>,
|
||||||
|
@ -833,7 +838,7 @@ fn tessellate_paint_command(
|
||||||
/// A list of clip rectangles with matching `Triangles`.
|
/// A list of clip rectangles with matching `Triangles`.
|
||||||
pub fn tessellate_paint_commands(
|
pub fn tessellate_paint_commands(
|
||||||
commands: Vec<(Rect, PaintCmd)>,
|
commands: Vec<(Rect, PaintCmd)>,
|
||||||
options: PaintOptions,
|
options: TesselationOptions,
|
||||||
fonts: &Fonts,
|
fonts: &Fonts,
|
||||||
) -> Vec<(Rect, Triangles)> {
|
) -> Vec<(Rect, Triangles)> {
|
||||||
let mut scratchpad_points = Vec::new();
|
let mut scratchpad_points = Vec::new();
|
||||||
|
|
|
@ -89,7 +89,8 @@ pub fn run(
|
||||||
};
|
};
|
||||||
app.ui(&ctx, &mut integration_context);
|
app.ui(&ctx, &mut integration_context);
|
||||||
let app_output = integration_context.output;
|
let app_output = integration_context.output;
|
||||||
let (egui_output, paint_jobs) = ctx.end_frame();
|
let (egui_output, paint_commands) = ctx.end_frame();
|
||||||
|
let paint_jobs = ctx.tesselate(paint_commands);
|
||||||
|
|
||||||
let frame_time = (Instant::now() - egui_start).as_secs_f64() as f32;
|
let frame_time = (Instant::now() - egui_start).as_secs_f64() as f32;
|
||||||
previous_frame_time = Some(frame_time);
|
previous_frame_time = Some(frame_time);
|
||||||
|
|
|
@ -44,7 +44,8 @@ impl WebBackend {
|
||||||
.take()
|
.take()
|
||||||
.expect("unmatched calls to begin_frame/end_frame");
|
.expect("unmatched calls to begin_frame/end_frame");
|
||||||
|
|
||||||
let (output, paint_jobs) = self.ctx.end_frame();
|
let (output, paint_commands) = self.ctx.end_frame();
|
||||||
|
let paint_jobs = self.ctx.tesselate(paint_commands);
|
||||||
|
|
||||||
self.auto_save();
|
self.auto_save();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue