summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2019-11-11 06:07:31 +0100
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2019-11-11 06:07:31 +0100
commit860a6923bbed57a21ce4b2cae331f6a3a51ca3fe (patch)
treeb179c26278ef95b6aa2520c1cef69b5fa264ebcf
parentd4d14b68f47e9527554a728ebbba9b840832626a (diff)
downloadiced-860a6923bbed57a21ce4b2cae331f6a3a51ca3fe.tar.gz
iced-860a6923bbed57a21ce4b2cae331f6a3a51ca3fe.tar.bz2
iced-860a6923bbed57a21ce4b2cae331f6a3a51ca3fe.zip
Split text measurements cache from rendering cache
This speeds up layouting in the most common scenario considerably! :tada:
-rw-r--r--core/src/widget/image.rs2
-rw-r--r--examples/scroll.rs4
-rw-r--r--native/src/renderer.rs11
-rw-r--r--native/src/user_interface.rs4
-rw-r--r--wgpu/Cargo.toml1
-rw-r--r--wgpu/src/renderer.rs43
-rw-r--r--wgpu/src/renderer/widget/text.rs2
-rw-r--r--wgpu/src/renderer/widget/text_input.rs4
-rw-r--r--winit/src/application.rs6
9 files changed, 53 insertions, 24 deletions
diff --git a/core/src/widget/image.rs b/core/src/widget/image.rs
index 7e1b1085..996ab5e1 100644
--- a/core/src/widget/image.rs
+++ b/core/src/widget/image.rs
@@ -1,6 +1,6 @@
//! Display images in your user interface.
-use crate::{Align, Length, Rectangle};
+use crate::{Length, Rectangle};
/// A frame that displays an image while keeping aspect ratio.
///
diff --git a/examples/scroll.rs b/examples/scroll.rs
index 98206268..50701879 100644
--- a/examples/scroll.rs
+++ b/examples/scroll.rs
@@ -1,6 +1,6 @@
use iced::{
- button, scrollable, Align, Application, Button, Column, Container, Element,
- Image, Length, Scrollable, Text,
+ button, scrollable, Align, Application, Button, Container, Element, Image,
+ Length, Scrollable, Text,
};
pub fn main() {
diff --git a/native/src/renderer.rs b/native/src/renderer.rs
index 5963d577..833de571 100644
--- a/native/src/renderer.rs
+++ b/native/src/renderer.rs
@@ -26,6 +26,15 @@ mod windowed;
pub use debugger::Debugger;
pub use windowed::{Target, Windowed};
-pub trait Renderer {
+use crate::{layout, Element};
+
+pub trait Renderer: Sized {
type Output;
+
+ fn layout<'a, Message>(
+ &mut self,
+ element: &Element<'a, Message, Self>,
+ ) -> layout::Node {
+ element.layout(self, &layout::Limits::NONE)
+ }
}
diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs
index 4343086b..f031b090 100644
--- a/native/src/user_interface.rs
+++ b/native/src/user_interface.rs
@@ -97,7 +97,7 @@ where
pub fn build<E: Into<Element<'a, Message, Renderer>>>(
root: E,
cache: Cache,
- renderer: &Renderer,
+ renderer: &mut Renderer,
) -> Self {
let root = root.into();
@@ -110,7 +110,7 @@ where
cache.layout
} else {
let layout_start = std::time::Instant::now();
- let layout = root.layout(renderer, &layout::Limits::NONE);
+ let layout = renderer.layout(&root);
dbg!(std::time::Instant::now() - layout_start);
layout
diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml
index 032f4ae0..3ebfa7ea 100644
--- a/wgpu/Cargo.toml
+++ b/wgpu/Cargo.toml
@@ -10,6 +10,7 @@ repository = "https://github.com/hecrj/iced"
[dependencies]
iced_native = { version = "0.1.0-alpha", path = "../native" }
wgpu = "0.4"
+glyph_brush = "0.6"
wgpu_glyph = { version = "0.5", git = "https://github.com/hecrj/wgpu_glyph", branch = "feature/scissoring" }
raw-window-handle = "0.3"
image = "0.22"
diff --git a/wgpu/src/renderer.rs b/wgpu/src/renderer.rs
index 7f7b79a5..87e499e2 100644
--- a/wgpu/src/renderer.rs
+++ b/wgpu/src/renderer.rs
@@ -22,8 +22,8 @@ pub struct Renderer {
queue: Queue,
quad_pipeline: quad::Pipeline,
image_pipeline: crate::image::Pipeline,
-
- glyph_brush: RefCell<wgpu_glyph::GlyphBrush<'static, ()>>,
+ text_pipeline: wgpu_glyph::GlyphBrush<'static, ()>,
+ text_measurements: RefCell<glyph_brush::GlyphBrush<'static, ()>>,
}
pub struct Layer<'a> {
@@ -73,11 +73,14 @@ impl Renderer {
let fonts = vec![default_font, mono_font];
- let glyph_brush =
- wgpu_glyph::GlyphBrushBuilder::using_fonts_bytes(fonts)
+ let text_pipeline =
+ wgpu_glyph::GlyphBrushBuilder::using_fonts_bytes(fonts.clone())
.initial_cache_size((2048, 2048))
.build(&mut device, TextureFormat::Bgra8UnormSrgb);
+ let text_measurements =
+ glyph_brush::GlyphBrushBuilder::using_fonts_bytes(fonts).build();
+
let quad_pipeline = quad::Pipeline::new(&mut device);
let image_pipeline = crate::image::Pipeline::new(&mut device);
@@ -86,8 +89,8 @@ impl Renderer {
queue,
quad_pipeline,
image_pipeline,
-
- glyph_brush: RefCell::new(glyph_brush),
+ text_pipeline,
+ text_measurements: RefCell::new(text_measurements),
}
}
@@ -293,8 +296,7 @@ impl Renderer {
let first = layers.first().unwrap();
let mut overlay = Layer::new(first.bounds, Vector::new(0, 0));
- let font_id =
- wgpu_glyph::FontId(self.glyph_brush.borrow().fonts().len() - 1);
+ let font_id = wgpu_glyph::FontId(self.text_pipeline.fonts().len() - 1);
let scale = wgpu_glyph::Scale { x: 20.0, y: 20.0 };
for (i, line) in lines.iter().enumerate() {
@@ -361,8 +363,6 @@ impl Renderer {
}
if layer.text.len() > 0 {
- let mut glyph_brush = self.glyph_brush.borrow_mut();
-
for text in layer.text.iter() {
// Target physical coordinates directly to avoid blurry text
let text = wgpu_glyph::Section {
@@ -378,10 +378,10 @@ impl Renderer {
..*text
};
- glyph_brush.queue(text);
+ self.text_pipeline.queue(text);
}
- glyph_brush
+ self.text_pipeline
.draw_queued_with_transform_and_scissoring(
&mut self.device,
encoder,
@@ -401,6 +401,25 @@ impl Renderer {
impl iced_native::Renderer for Renderer {
type Output = (Primitive, MouseCursor);
+
+ fn layout<'a, Message>(
+ &mut self,
+ element: &iced_native::Element<'a, Message, Self>,
+ ) -> iced_native::layout::Node {
+ let node = element.layout(self, &iced_native::layout::Limits::NONE);
+
+ // Trim measurements cache
+ // TODO: We should probably use a `GlyphCalculator` for this. However,
+ // it uses a lifetimed `GlyphCalculatorGuard` with side-effects on drop.
+ // This makes stuff quite inconvenient. A manual method for trimming the
+ // cache would make our lives easier.
+ self.text_measurements
+ .borrow_mut()
+ .process_queued(|_, _| {}, |_| {})
+ .expect("Trim text measurements");
+
+ node
+ }
}
impl Windowed for Renderer {
diff --git a/wgpu/src/renderer/widget/text.rs b/wgpu/src/renderer/widget/text.rs
index 713b514f..b9ccd787 100644
--- a/wgpu/src/renderer/widget/text.rs
+++ b/wgpu/src/renderer/widget/text.rs
@@ -22,7 +22,7 @@ impl text::Renderer for Renderer {
};
let (width, height) = if let Some(bounds) =
- self.glyph_brush.borrow_mut().glyph_bounds(&section)
+ self.text_measurements.borrow_mut().glyph_bounds(&section)
{
(bounds.width().ceil(), bounds.height().ceil())
} else {
diff --git a/wgpu/src/renderer/widget/text_input.rs b/wgpu/src/renderer/widget/text_input.rs
index b5f6c5f6..75eb20f7 100644
--- a/wgpu/src/renderer/widget/text_input.rs
+++ b/wgpu/src/renderer/widget/text_input.rs
@@ -78,7 +78,7 @@ impl text_input::Renderer for Renderer {
.to_string();
let mut text_value_width = self
- .glyph_brush
+ .text_measurements
.borrow_mut()
.glyph_bounds(Section {
text: text_before_cursor,
@@ -94,7 +94,7 @@ impl text_input::Renderer for Renderer {
if spaces_at_the_end > 0 {
let space_width = {
- let glyph_brush = self.glyph_brush.borrow();
+ let glyph_brush = self.text_measurements.borrow();
// TODO: Select appropriate font
let font = &glyph_brush.fonts()[0];
diff --git a/winit/src/application.rs b/winit/src/application.rs
index fdd659d9..331bafa0 100644
--- a/winit/src/application.rs
+++ b/winit/src/application.rs
@@ -61,7 +61,7 @@ pub trait Application {
let user_interface = UserInterface::build(
document(&mut self, size, &mut debug),
Cache::default(),
- &renderer,
+ &mut renderer,
);
debug.layout_finished();
@@ -87,7 +87,7 @@ pub trait Application {
let mut user_interface = UserInterface::build(
document(&mut self, size, &mut debug),
cache.take().unwrap(),
- &renderer,
+ &mut renderer,
);
debug.layout_finished();
@@ -130,7 +130,7 @@ pub trait Application {
let user_interface = UserInterface::build(
document(&mut self, size, &mut debug),
temp_cache,
- &renderer,
+ &mut renderer,
);
debug.layout_finished();