aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortrimental <timmins.s.lucas@gmail.com>2018-10-01 05:54:08 +0800
committerChristian Duerr <chrisduerr@users.noreply.github.com>2018-09-30 21:54:08 +0000
commitb22999f1e7b39c1341caf797a98facb9010f89cf (patch)
tree4f97b33870c7058988c4edcdaf188f407053549b
parentf785f88a58daa3919255a268fa1da62aa07f13a7 (diff)
downloadalacritty-b22999f1e7b39c1341caf797a98facb9010f89cf.tar.gz
alacritty-b22999f1e7b39c1341caf797a98facb9010f89cf.zip
Drop terminal lock before rendering
The terminal lock is now dropped before rendering by storing all grid cells before clearing the screen. This frees the terminal to do other things since the lock is now free, which lead to a performance benefit with high throughput applications.
-rw-r--r--CHANGELOG.md1
-rw-r--r--src/display.rs59
-rw-r--r--src/renderer/mod.rs8
-rw-r--r--src/term/mod.rs1
4 files changed, 32 insertions, 37 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b6283e41..4ab2bce2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
+- Rendering now occurs without the terminal locked which improves performance
- Clear screen properly before rendering of content to prevent various graphical glitches
- Fix build failure on 32-bit systems
- Windows started as unfocused now show the hollow cursor if the setting is enabled
diff --git a/src/display.rs b/src/display.rs
index 928434d8..d806b33a 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -24,7 +24,7 @@ use config::Config;
use font::{self, Rasterize};
use meter::Meter;
use renderer::{self, GlyphCache, QuadRenderer};
-use term::{Term, SizeInfo};
+use term::{Term, SizeInfo, RenderableCell};
use sync::FairMutex;
use window::{self, Size, Pixels, Window, SetInnerSize};
@@ -325,27 +325,15 @@ impl Display {
///
/// This call may block if vsync is enabled
pub fn draw(&mut self, terminal: &FairMutex<Term>, config: &Config) {
- let terminal_locked = terminal.lock();
- let size_info = *terminal_locked.size_info();
- let visual_bell_intensity = terminal_locked.visual_bell.intensity();
- let background_color = terminal_locked.background_color();
-
- // Clear when terminal mutex isn't held. Mesa for
- // some reason takes a long time to call glClear(). The driver descends
- // into xcb_connect_to_fd() which ends up calling __poll_nocancel()
- // which blocks for a while.
- //
- // By keeping this outside of the critical region, the Mesa bug is
- // worked around to some extent. Since this doesn't actually address the
- // issue of glClear being slow, less time is available for input
- // handling and rendering.
- drop(terminal_locked);
-
- self.renderer.with_api(config, &size_info, visual_bell_intensity, |api| {
- api.clear(background_color);
- });
-
let mut terminal = terminal.lock();
+ let size_info = *terminal.size_info();
+ let visual_bell_intensity = terminal.visual_bell.intensity();
+ let background_color = terminal.background_color();
+
+ let window_focused = self.window.is_focused;
+ let grid_cells: Vec<RenderableCell> = terminal
+ .renderable_cells(config, window_focused)
+ .collect();
// Clear dirty flag
terminal.dirty = !terminal.visual_bell.completed();
@@ -366,6 +354,21 @@ impl Display {
}
}
+ // Clear when terminal mutex isn't held. Mesa for
+ // some reason takes a long time to call glClear(). The driver descends
+ // into xcb_connect_to_fd() which ends up calling __poll_nocancel()
+ // which blocks for a while.
+ //
+ // By keeping this outside of the critical region, the Mesa bug is
+ // worked around to some extent. Since this doesn't actually address the
+ // issue of glClear being slow, less time is available for input
+ // handling and rendering.
+ drop(terminal);
+
+ self.renderer.with_api(config, &size_info, visual_bell_intensity, |api| {
+ api.clear(background_color);
+ });
+
{
let glyph_cache = &mut self.glyph_cache;
@@ -373,18 +376,9 @@ impl Display {
{
let _sampler = self.meter.sampler();
- // Make a copy of size_info since the closure passed here
- // borrows terminal mutably
- //
- // TODO I wonder if the renderable cells iter could avoid the
- // mutable borrow
- let window_focused = self.window.is_focused;
self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| {
// Draw the grid
- api.render_cells(
- terminal.renderable_cells(config, window_focused),
- glyph_cache,
- );
+ api.render_cells(grid_cells.iter(), glyph_cache);
});
}
@@ -398,8 +392,6 @@ impl Display {
}
}
- // Unlock the terminal mutex; following call to swap_buffers() may block
- drop(terminal);
self.window
.swap_buffers()
.expect("swap buffers");
@@ -423,3 +415,4 @@ impl Display {
self.window().set_ime_spot(nspot_x, nspot_y);
}
}
+
diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs
index b461db0c..bcc896ef 100644
--- a/src/renderer/mod.rs
+++ b/src/renderer/mod.rs
@@ -374,7 +374,7 @@ pub struct RenderApi<'a> {
current_atlas: &'a mut usize,
program: &'a mut ShaderProgram,
config: &'a Config,
- visual_bell_intensity: f32
+ visual_bell_intensity: f32,
}
#[derive(Debug)]
@@ -799,7 +799,7 @@ impl<'a> RenderApi<'a> {
})
.collect::<Vec<_>>();
- self.render_cells(cells.into_iter(), glyph_cache);
+ self.render_cells(cells.iter(), glyph_cache);
}
#[inline]
@@ -817,12 +817,12 @@ impl<'a> RenderApi<'a> {
}
}
- pub fn render_cells<I>(
+ pub fn render_cells<'b, I>(
&mut self,
cells: I,
glyph_cache: &mut GlyphCache
)
- where I: Iterator<Item=RenderableCell>
+ where I: Iterator<Item=&'b RenderableCell>
{
for cell in cells {
// Get font key for cell
diff --git a/src/term/mod.rs b/src/term/mod.rs
index 9be8b96b..495a7567 100644
--- a/src/term/mod.rs
+++ b/src/term/mod.rs
@@ -372,6 +372,7 @@ impl<'a> RenderableCellsIter<'a> {
}
}
+#[derive(Debug)]
pub struct RenderableCell {
/// A _Display_ line (not necessarily an _Active_ line)
pub line: Line,